Merge branch 'for-linus' of git://one.firstfloor.org/home/andi/git/linux-2.6

* 'for-linus' of git://one.firstfloor.org/home/andi/git/linux-2.6: (231 commits)
  [PATCH] i386: Don't delete cpu_devs data to identify different x86 types in late_initcall
  [PATCH] i386: type may be unused
  [PATCH] i386: Some additional chipset register values validation.
  [PATCH] i386: Add missing !X86_PAE dependincy to the 2G/2G split.
  [PATCH] x86-64: Don't exclude asm-offsets.c in Documentation/dontdiff
  [PATCH] i386: avoid redundant preempt_disable in __unlazy_fpu
  [PATCH] i386: white space fixes in i387.h
  [PATCH] i386: Drop noisy e820 debugging printks
  [PATCH] x86-64: Fix allnoconfig error in genapic_flat.c
  [PATCH] x86-64: Shut up warnings for vfat compat ioctls on other file systems
  [PATCH] x86-64: Share identical video.S between i386 and x86-64
  [PATCH] x86-64: Remove CONFIG_REORDER
  [PATCH] x86-64: Print type and size correctly for unknown compat ioctls
  [PATCH] i386: Remove copy_*_user BUG_ONs for (size < 0)
  [PATCH] i386: Little cleanups in smpboot.c
  [PATCH] x86-64: Don't enable NUMA for a single node in K8 NUMA scanning
  [PATCH] x86: Use RDTSCP for synchronous get_cycles if possible
  [PATCH] i386: Add X86_FEATURE_RDTSCP
  [PATCH] i386: Implement X86_FEATURE_SYNC_RDTSC on i386
  [PATCH] i386: Implement alternative_io for i386
  ...

Fix up trivial conflict in include/linux/highmem.h manually.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
diff --git a/Documentation/driver-model/devres.txt b/Documentation/driver-model/devres.txt
index 5163b85..6c8d8f2 100644
--- a/Documentation/driver-model/devres.txt
+++ b/Documentation/driver-model/devres.txt
@@ -182,7 +182,7 @@
 
 	...
 
-	devres_close_group(dev, my_midlayer_something);
+	devres_close_group(dev, my_midlayer_create_something);
 	return 0;
   }
 
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 5c88ba1..5f96cb3 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -117,13 +117,6 @@
 
 ---------------------------
 
-What:	pci_module_init(driver)
-When:	January 2007
-Why:	Is replaced by pci_register_driver(pci_driver).
-Who:	Richard Knutsson <ricknu-0@student.ltu.se> and Greg Kroah-Hartman <gregkh@suse.de>
-
----------------------------
-
 What:	Usage of invalid timevals in setitimer
 When:	March 2007
 Why:	POSIX requires to validate timevals in the setitimer call. This
@@ -190,18 +183,10 @@
 
 ---------------------------
 
-What:	i2c_adapter.dev
-	i2c_adapter.list
+What:	i2c_adapter.list
 When:	July 2007
-Why:	Superfluous, given i2c_adapter.class_dev:
-	  * The "dev" was a stand-in for the physical device node that legacy
-	    drivers would not have; but now it's almost always present.  Any
-	    remaining legacy drivers must upgrade (they now trigger warnings).
-	  * The "list" duplicates class device children.
-	The delay in removing this is so upgraded lm_sensors and libsensors
-	can get deployed.  (Removal causes minor changes in the sysfs layout,
-	notably the location of the adapter type name and parenting the i2c
-	client hardware directly from their controller.)
+Why:	Superfluous, this list duplicates the one maintained by the driver
+	core.
 Who:	Jean Delvare <khali@linux-fr.org>,
 	David Brownell <dbrownell@users.sourceforge.net>
 
@@ -314,3 +299,27 @@
 Who:	David S. Miller <davem@davemloft.net>
 
 ---------------------------
+
+What:	read_dev_chars(), read_conf_data{,_lpm}() (s390 common I/O layer)
+When:	December 2007
+Why:	These functions are a leftover from 2.4 times. They have several
+	problems:
+	- Duplication of checks that are done in the device driver's
+	  interrupt handler
+	- common I/O layer can't do device specific error recovery
+	- device driver can't be notified for conditions happening during
+	  execution of the function
+	Device drivers should issue the read device characteristics and read
+	configuration data ccws and do the appropriate error handling
+	themselves.
+Who:	Cornelia Huck <cornelia.huck@de.ibm.com>
+
+---------------------------
+
+What:	i2c-ixp2000, i2c-ixp4xx and scx200_i2c drivers
+When:	September 2007
+Why:	Obsolete. The new i2c-gpio driver replaces all hardware-specific
+	I2C-over-GPIO drivers.
+Who:	Jean Delvare <khali@linux-fr.org>
+
+---------------------------
diff --git a/Documentation/i2c/busses/i2c-nforce2 b/Documentation/i2c/busses/i2c-nforce2
index 7f61fbc..fae3495 100644
--- a/Documentation/i2c/busses/i2c-nforce2
+++ b/Documentation/i2c/busses/i2c-nforce2
@@ -9,6 +9,8 @@
   * nForce4 MCP-04             10de:0034
   * nForce4 MCP51              10de:0264
   * nForce4 MCP55              10de:0368
+  * nForce4 MCP61              10de:03EB
+  * nForce4 MCP65              10de:0446
 
 Datasheet: not publicly available, but seems to be similar to the
            AMD-8111 SMBus 2.0 adapter.
diff --git a/Documentation/i2c/porting-clients b/Documentation/i2c/porting-clients
index ca272b2..7bf82c0 100644
--- a/Documentation/i2c/porting-clients
+++ b/Documentation/i2c/porting-clients
@@ -1,4 +1,4 @@
-Revision 6, 2005-11-20
+Revision 7, 2007-04-19
 Jean Delvare <khali@linux-fr.org>
 Greg KH <greg@kroah.com>
 
@@ -20,6 +20,10 @@
 
 Technical changes:
 
+* [Driver type] Any driver that was relying on i2c-isa has to be
+  converted to a proper isa, platform or pci driver. This is not
+  covered by this guide.
+
 * [Includes] Get rid of "version.h" and <linux/i2c-proc.h>.
   Includes typically look like that:
   #include <linux/module.h>
@@ -27,12 +31,10 @@
   #include <linux/slab.h>
   #include <linux/jiffies.h>
   #include <linux/i2c.h>
-  #include <linux/i2c-isa.h>	/* for ISA drivers */
   #include <linux/hwmon.h>	/* for hardware monitoring drivers */
   #include <linux/hwmon-sysfs.h>
   #include <linux/hwmon-vid.h>	/* if you need VRM support */
   #include <linux/err.h>	/* for class registration */
-  #include <asm/io.h>		/* if you have I/O operations */
   Please respect this inclusion order. Some extra headers may be
   required for a given driver (e.g. "lm75.h").
 
@@ -69,20 +71,16 @@
   sensors mailing list <lm-sensors@lm-sensors.org> by providing a
   patch to the Documentation/hwmon/sysfs-interface file.
 
-* [Attach] For I2C drivers, the attach function should make sure
-  that the adapter's class has I2C_CLASS_HWMON (or whatever class is
-  suitable for your driver), using the following construct:
+* [Attach] The attach function should make sure that the adapter's
+  class has I2C_CLASS_HWMON (or whatever class is suitable for your
+  driver), using the following construct:
   if (!(adapter->class & I2C_CLASS_HWMON))
           return 0;
-  ISA-only drivers of course don't need this.
   Call i2c_probe() instead of i2c_detect().
 
 * [Detect] As mentioned earlier, the flags parameter is gone.
   The type_name and client_name strings are replaced by a single
   name string, which will be filled with a lowercase, short string.
-  In i2c-only drivers, drop the i2c_is_isa_adapter check, it's
-  useless. Same for isa-only drivers, as the test would always be
-  true. Only hybrid drivers (which are quite rare) still need it.
   The labels used for error paths are reduced to the number needed.
   It is advised that the labels are given descriptive names such as
   exit and exit_free. Don't forget to properly set err before
diff --git a/Documentation/i2c/summary b/Documentation/i2c/summary
index 41dde87..aea60bf 100644
--- a/Documentation/i2c/summary
+++ b/Documentation/i2c/summary
@@ -4,17 +4,23 @@
 =============
 
 I2C (pronounce: I squared C) is a protocol developed by Philips. It is a 
-slow two-wire protocol (10-400 kHz), but it suffices for many types of 
-devices.
+slow two-wire protocol (variable speed, up to 400 kHz), with a high speed
+extension (3.4 MHz).  It provides an inexpensive bus for connecting many
+types of devices with infrequent or low bandwidth communications needs.
+I2C is widely used with embedded systems.  Some systems use variants that
+don't meet branding requirements, and so are not advertised as being I2C.
 
-SMBus (System Management Bus) is a subset of the I2C protocol. Many
-modern mainboards have a System Management Bus. There are a lot of 
-devices which can be connected to a SMBus; the most notable are modern 
-memory chips with EEPROM memories and chips for hardware monitoring.
+SMBus (System Management Bus) is based on the I2C protocol, and is mostly
+a subset of I2C protocols and signaling.  Many I2C devices will work on an
+SMBus, but some SMBus protocols add semantics beyond what is required to
+achieve I2C branding.  Modern PC mainboards rely on SMBus.  The most common
+devices connected through SMBus are RAM modules configured using I2C EEPROMs,
+and hardware monitoring chips.
 
-Because the SMBus is just a special case of the generalized I2C bus, we
-can simulate the SMBus protocol on plain I2C busses. The reverse is
-regretfully impossible.
+Because the SMBus is mostly a subset of the generalized I2C bus, we can
+use its protocols on many I2C systems.  However, there are systems that don't
+meet both SMBus and I2C electrical constraints; and others which can't
+implement all the common SMBus protocol semantics or messages.
 
 
 Terminology
@@ -29,6 +35,7 @@
 An Algorithm driver contains general code that can be used for a whole class
 of I2C adapters. Each specific adapter driver depends on one algorithm
 driver.
+
 A Driver driver (yes, this sounds ridiculous, sorry) contains the general
 code to access some type of device. Each detected device gets its own
 data in the Client structure. Usually, Driver and Client are more closely
@@ -40,6 +47,10 @@
 in this package. See the lm_sensors project http://www.lm-sensors.nu
 for device drivers.
 
+At this time, Linux only operates I2C (or SMBus) in master mode; you can't
+use these APIs to make a Linux system behave as a slave/device, either to
+speak a custom protocol or to emulate some other device.
+
 
 Included Bus Drivers
 ====================
diff --git a/Documentation/i2c/writing-clients b/Documentation/i2c/writing-clients
index fbcff96..3d8d36b 100644
--- a/Documentation/i2c/writing-clients
+++ b/Documentation/i2c/writing-clients
@@ -1,5 +1,5 @@
 This is a small guide for those who want to write kernel drivers for I2C
-or SMBus devices.
+or SMBus devices, using Linux as the protocol host/master (not slave).
 
 To set up a driver, you need to do several things. Some are optional, and
 some things can be done slightly or completely different. Use this as a
@@ -29,8 +29,16 @@
 	.driver = {
 		.name	= "foo",
 	},
+
+	/* iff driver uses driver model ("new style") binding model: */
+	.probe		= foo_probe,
+	.remove		= foo_remove,
+
+	/* else, driver uses "legacy" binding model: */
 	.attach_adapter	= foo_attach_adapter,
 	.detach_client	= foo_detach_client,
+
+	/* these may be used regardless of the driver binding model */
 	.shutdown	= foo_shutdown,	/* optional */
 	.suspend	= foo_suspend,	/* optional */
 	.resume		= foo_resume,	/* optional */
@@ -40,7 +48,8 @@
 The name field is the driver name, and must not contain spaces.  It
 should match the module name (if the driver can be compiled as a module),
 although you can use MODULE_ALIAS (passing "foo" in this example) to add
-another name for the module.
+another name for the module.  If the driver name doesn't match the module
+name, the module won't be automatically loaded (hotplug/coldplug).
 
 All other fields are for call-back functions which will be explained 
 below.
@@ -65,16 +74,13 @@
 
   struct foo_data {
     struct i2c_client client;
-    struct semaphore lock; /* For ISA access in `sensors' drivers. */
-    int sysctl_id;         /* To keep the /proc directory entry for 
-                              `sensors' drivers. */
     enum chips type;       /* To keep the chips type for `sensors' drivers. */
    
     /* Because the i2c bus is slow, it is often useful to cache the read
        information of a chip for some time (for example, 1 or 2 seconds).
        It depends of course on the device whether this is really worthwhile
        or even sensible. */
-    struct semaphore update_lock; /* When we are reading lots of information,
+    struct mutex update_lock;     /* When we are reading lots of information,
                                      another process should not update the
                                      below information */
     char valid;                   /* != 0 if the following fields are valid. */
@@ -95,8 +101,7 @@
 I have found it useful to define foo_read and foo_write function for this.
 For some cases, it will be easier to call the i2c functions directly,
 but many chips have some kind of register-value idea that can easily
-be encapsulated. Also, some chips have both ISA and I2C interfaces, and
-it useful to abstract from this (only for `sensors' drivers).
+be encapsulated.
 
 The below functions are simple examples, and should not be copied
 literally.
@@ -119,28 +124,101 @@
       return i2c_smbus_write_word_data(client,reg,value);
   }
 
-For sensors code, you may have to cope with ISA registers too. Something
-like the below often works. Note the locking! 
-
-  int foo_read_value(struct i2c_client *client, u8 reg)
-  {
-    int res;
-    if (i2c_is_isa_client(client)) {
-      down(&(((struct foo_data *) (client->data)) -> lock));
-      outb_p(reg,client->addr + FOO_ADDR_REG_OFFSET);
-      res = inb_p(client->addr + FOO_DATA_REG_OFFSET);
-      up(&(((struct foo_data *) (client->data)) -> lock));
-      return res;
-    } else
-      return i2c_smbus_read_byte_data(client,reg);
-  }
-
-Writing is done the same way.
-
 
 Probing and attaching
 =====================
 
+The Linux I2C stack was originally written to support access to hardware
+monitoring chips on PC motherboards, and thus it embeds some assumptions
+that are more appropriate to SMBus (and PCs) than to I2C.  One of these
+assumptions is that most adapters and devices drivers support the SMBUS_QUICK
+protocol to probe device presence.  Another is that devices and their drivers
+can be sufficiently configured using only such probe primitives.
+
+As Linux and its I2C stack became more widely used in embedded systems
+and complex components such as DVB adapters, those assumptions became more
+problematic.  Drivers for I2C devices that issue interrupts need more (and
+different) configuration information, as do drivers handling chip variants
+that can't be distinguished by protocol probing, or which need some board
+specific information to operate correctly.
+
+Accordingly, the I2C stack now has two models for associating I2C devices
+with their drivers:  the original "legacy" model, and a newer one that's
+fully compatible with the Linux 2.6 driver model.  These models do not mix,
+since the "legacy" model requires drivers to create "i2c_client" device
+objects after SMBus style probing, while the Linux driver model expects
+drivers to be given such device objects in their probe() routines.
+
+
+Standard Driver Model Binding ("New Style")
+-------------------------------------------
+
+System infrastructure, typically board-specific initialization code or
+boot firmware, reports what I2C devices exist.  For example, there may be
+a table, in the kernel or from the boot loader, identifying I2C devices
+and linking them to board-specific configuration information about IRQs
+and other wiring artifacts, chip type, and so on.  That could be used to
+create i2c_client objects for each I2C device.
+
+I2C device drivers using this binding model work just like any other
+kind of driver in Linux:  they provide a probe() method to bind to
+those devices, and a remove() method to unbind.
+
+	static int foo_probe(struct i2c_client *client);
+	static int foo_remove(struct i2c_client *client);
+
+Remember that the i2c_driver does not create those client handles.  The
+handle may be used during foo_probe().  If foo_probe() reports success
+(zero not a negative status code) it may save the handle and use it until
+foo_remove() returns.  That binding model is used by most Linux drivers.
+
+Drivers match devices when i2c_client.driver_name and the driver name are
+the same; this approach is used in several other busses that don't have
+device typing support in the hardware.  The driver and module name should
+match, so hotplug/coldplug mechanisms will modprobe the driver.
+
+
+Device Creation (Standard driver model)
+---------------------------------------
+
+If you know for a fact that an I2C device is connected to a given I2C bus,
+you can instantiate that device by simply filling an i2c_board_info
+structure with the device address and driver name, and calling
+i2c_new_device().  This will create the device, then the driver core will
+take care of finding the right driver and will call its probe() method.
+If a driver supports different device types, you can specify the type you
+want using the type field.  You can also specify an IRQ and platform data
+if needed.
+
+Sometimes you know that a device is connected to a given I2C bus, but you
+don't know the exact address it uses.  This happens on TV adapters for
+example, where the same driver supports dozens of slightly different
+models, and I2C device addresses change from one model to the next.  In
+that case, you can use the i2c_new_probed_device() variant, which is
+similar to i2c_new_device(), except that it takes an additional list of
+possible I2C addresses to probe.  A device is created for the first
+responsive address in the list.  If you expect more than one device to be
+present in the address range, simply call i2c_new_probed_device() that
+many times.
+
+The call to i2c_new_device() or i2c_new_probed_device() typically happens
+in the I2C bus driver. You may want to save the returned i2c_client
+reference for later use.
+
+
+Device Deletion (Standard driver model)
+---------------------------------------
+
+Each I2C device which has been created using i2c_new_device() or
+i2c_new_probed_device() can be unregistered by calling
+i2c_unregister_device().  If you don't call it explicitly, it will be
+called automatically before the underlying I2C bus itself is removed, as a
+device can't survive its parent in the device driver model.
+
+
+Legacy Driver Binding Model
+---------------------------
+
 Most i2c devices can be present on several i2c addresses; for some this
 is determined in hardware (by soldering some chip pins to Vcc or Ground),
 for others this can be changed in software (by writing to specific client
@@ -157,13 +235,9 @@
 You do not have to use this parameter interface; but don't try to use
 function i2c_probe() if you don't.
 
-NOTE: If you want to write a `sensors' driver, the interface is slightly
-      different! See below.
 
-
-
-Probing classes
----------------
+Probing classes (Legacy model)
+------------------------------
 
 All parameters are given as lists of unsigned 16-bit integers. Lists are
 terminated by I2C_CLIENT_END.
@@ -210,8 +284,8 @@
 without any prefix!
 
 
-Attaching to an adapter
------------------------
+Attaching to an adapter (Legacy model)
+--------------------------------------
 
 Whenever a new adapter is inserted, or for all adapters if the driver is
 being registered, the callback attach_adapter() is called. Now is the
@@ -237,17 +311,13 @@
 are already in use (by some other registered client) are skipped.
 
 
-The detect client function
---------------------------
+The detect client function (Legacy model)
+-----------------------------------------
 
 The detect client function is called by i2c_probe. The `kind' parameter
 contains -1 for a probed detection, 0 for a forced detection, or a positive
 number for a forced detection with a chip type forced.
 
-Below, some things are only needed if this is a `sensors' driver. Those
-parts are between /* SENSORS ONLY START */ and /* SENSORS ONLY END */
-markers. 
-
 Returning an error different from -ENODEV in a detect function will cause
 the detection to stop: other addresses and adapters won't be scanned.
 This should only be done on fatal or internal errors, such as a memory
@@ -256,64 +326,20 @@
 For now, you can ignore the `flags' parameter. It is there for future use.
 
   int foo_detect_client(struct i2c_adapter *adapter, int address, 
-                        unsigned short flags, int kind)
+                        int kind)
   {
     int err = 0;
     int i;
-    struct i2c_client *new_client;
+    struct i2c_client *client;
     struct foo_data *data;
-    const char *client_name = ""; /* For non-`sensors' drivers, put the real
-                                     name here! */
+    const char *name = "";
    
     /* Let's see whether this adapter can support what we need.
-       Please substitute the things you need here! 
-       For `sensors' drivers, add `! is_isa &&' to the if statement */
+       Please substitute the things you need here! */
     if (!i2c_check_functionality(adapter,I2C_FUNC_SMBUS_WORD_DATA |
                                         I2C_FUNC_SMBUS_WRITE_BYTE))
        goto ERROR0;
 
-    /* SENSORS ONLY START */
-    const char *type_name = "";
-    int is_isa = i2c_is_isa_adapter(adapter);
-
-    /* Do this only if the chip can additionally be found on the ISA bus
-       (hybrid chip). */
-
-    if (is_isa) {
-
-      /* Discard immediately if this ISA range is already used */
-      /* FIXME: never use check_region(), only request_region() */
-      if (check_region(address,FOO_EXTENT))
-        goto ERROR0;
-
-      /* Probe whether there is anything on this address.
-         Some example code is below, but you will have to adapt this
-         for your own driver */
-
-      if (kind < 0) /* Only if no force parameter was used */ {
-        /* We may need long timeouts at least for some chips. */
-        #define REALLY_SLOW_IO
-        i = inb_p(address + 1);
-        if (inb_p(address + 2) != i)
-          goto ERROR0;
-        if (inb_p(address + 3) != i)
-          goto ERROR0;
-        if (inb_p(address + 7) != i)
-          goto ERROR0;
-        #undef REALLY_SLOW_IO
-
-        /* Let's just hope nothing breaks here */
-        i = inb_p(address + 5) & 0x7f;
-        outb_p(~i & 0x7f,address+5);
-        if ((inb_p(address + 5) & 0x7f) != (~i & 0x7f)) {
-          outb_p(i,address+5);
-          return 0;
-        }
-      }
-    }
-
-    /* SENSORS ONLY END */
-
     /* 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 several i2c functions safely */
@@ -323,13 +349,12 @@
       goto ERROR0;
     }
 
-    new_client = &data->client;
-    i2c_set_clientdata(new_client, data);
+    client = &data->client;
+    i2c_set_clientdata(client, data);
 
-    new_client->addr = address;
-    new_client->adapter = adapter;
-    new_client->driver = &foo_driver;
-    new_client->flags = 0;
+    client->addr = address;
+    client->adapter = adapter;
+    client->driver = &foo_driver;
 
     /* Now, we do the remaining detection. If no `force' parameter is used. */
 
@@ -337,19 +362,17 @@
        parameter was used. */
     if (kind < 0) {
       /* The below is of course bogus */
-      if (foo_read(new_client,FOO_REG_GENERIC) != FOO_GENERIC_VALUE)
+      if (foo_read(client, FOO_REG_GENERIC) != FOO_GENERIC_VALUE)
          goto ERROR1;
     }
 
-    /* SENSORS ONLY START */
-
     /* Next, specific detection. This is especially important for `sensors'
        devices. */
 
     /* Determine the chip type. Not needed if a `force_CHIPTYPE' parameter
        was used. */
     if (kind <= 0) {
-      i = foo_read(new_client,FOO_REG_CHIPTYPE);
+      i = foo_read(client, FOO_REG_CHIPTYPE);
       if (i == FOO_TYPE_1) 
         kind = chip1; /* As defined in the enum */
       else if (i == FOO_TYPE_2)
@@ -363,63 +386,31 @@
 
     /* Now set the type and chip names */
     if (kind == chip1) {
-      type_name = "chip1"; /* For /proc entry */
-      client_name = "CHIP 1";
+      name = "chip1";
     } else if (kind == chip2) {
-      type_name = "chip2"; /* For /proc entry */
-      client_name = "CHIP 2";
+      name = "chip2";
     }
    
-    /* Reserve the ISA region */
-    if (is_isa)
-      request_region(address,FOO_EXTENT,type_name);
-
-    /* SENSORS ONLY END */
-
     /* Fill in the remaining client fields. */
-    strcpy(new_client->name,client_name);
-
-    /* SENSORS ONLY BEGIN */
+    strlcpy(client->name, name, I2C_NAME_SIZE);
     data->type = kind;
-    /* SENSORS ONLY END */
-
-    data->valid = 0; /* Only if you use this field */
-    init_MUTEX(&data->update_lock); /* Only if you use this field */
+    mutex_init(&data->update_lock); /* Only if you use this field */
 
     /* Any other initializations in data must be done here too. */
 
-    /* Tell the i2c layer a new client has arrived */
-    if ((err = i2c_attach_client(new_client)))
-      goto ERROR3;
-
-    /* SENSORS ONLY BEGIN */
-    /* Register a new directory entry with module sensors. See below for
-       the `template' structure. */
-    if ((i = i2c_register_entry(new_client, type_name,
-                                    foo_dir_table_template,THIS_MODULE)) < 0) {
-      err = i;
-      goto ERROR4;
-    }
-    data->sysctl_id = i;
-
-    /* SENSORS ONLY END */
-
     /* This function can write default values to the client registers, if
        needed. */
-    foo_init_client(new_client);
+    foo_init_client(client);
+
+    /* Tell the i2c layer a new client has arrived */
+    if ((err = i2c_attach_client(client)))
+      goto ERROR1;
+
     return 0;
 
     /* OK, this is not exactly good programming practice, usually. But it is
        very code-efficient in this case. */
 
-    ERROR4:
-      i2c_detach_client(new_client);
-    ERROR3:
-    ERROR2:
-    /* SENSORS ONLY START */
-      if (is_isa)
-        release_region(address,FOO_EXTENT);
-    /* SENSORS ONLY END */
     ERROR1:
       kfree(data);
     ERROR0:
@@ -427,8 +418,8 @@
   }
 
 
-Removing the client
-===================
+Removing the client (Legacy model)
+==================================
 
 The detach_client call back function is called when a client should be
 removed. It may actually fail, but only when panicking. This code is
@@ -436,22 +427,12 @@
 
   int foo_detach_client(struct i2c_client *client)
   {
-    int err,i;
-
-    /* SENSORS ONLY START */
-    /* Deregister with the `i2c-proc' module. */
-    i2c_deregister_entry(((struct lm78_data *)(client->data))->sysctl_id);
-    /* SENSORS ONLY END */
+    int err;
 
     /* Try to detach the client from i2c space */
     if ((err = i2c_detach_client(client)))
       return err;
 
-    /* HYBRID SENSORS CHIP ONLY START */
-    if i2c_is_isa_client(client)
-      release_region(client->addr,LM78_EXTENT);
-    /* HYBRID SENSORS CHIP ONLY END */
-
     kfree(i2c_get_clientdata(client));
     return 0;
   }
@@ -464,45 +445,34 @@
 you have to do some initializing. Fortunately, just attaching (registering)
 the driver module is usually enough.
 
-  /* Keep track of how far we got in the initialization process. If several
-     things have to initialized, and we fail halfway, only those things
-     have to be cleaned up! */
-  static int __initdata foo_initialized = 0;
-
   static int __init foo_init(void)
   {
     int res;
-    printk("foo version %s (%s)\n",FOO_VERSION,FOO_DATE);
     
     if ((res = i2c_add_driver(&foo_driver))) {
       printk("foo: Driver registration failed, module not inserted.\n");
-      foo_cleanup();
       return res;
     }
-    foo_initialized ++;
     return 0;
   }
 
-  void foo_cleanup(void)
+  static void __exit foo_cleanup(void)
   {
-    if (foo_initialized == 1) {
-      if ((res = i2c_del_driver(&foo_driver))) {
-        printk("foo: Driver registration failed, module not removed.\n");
-        return;
-      }
-      foo_initialized --;
-    }
+    i2c_del_driver(&foo_driver);
   }
 
   /* Substitute your own name and email address */
   MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>"
   MODULE_DESCRIPTION("Driver for Barf Inc. Foo I2C devices");
 
+  /* a few non-GPL license types are also allowed */
+  MODULE_LICENSE("GPL");
+
   module_init(foo_init);
   module_exit(foo_cleanup);
 
 Note that some functions are marked by `__init', and some data structures
-by `__init_data'.  Hose functions and structures can be removed after
+by `__initdata'.  These functions and structures can be removed after
 kernel booting (or module loading) is completed.
 
 
@@ -632,110 +602,7 @@
 Below all general purpose routines are listed, that were not mentioned
 before.
 
-  /* This call returns a unique low identifier for each registered adapter,
-   * or -1 if the adapter was not registered.
+  /* This call returns a unique low identifier for each registered adapter.
    */
   extern int i2c_adapter_id(struct i2c_adapter *adap);
 
-
-The sensors sysctl/proc interface
-=================================
-
-This section only applies if you write `sensors' drivers.
-
-Each sensors driver creates a directory in /proc/sys/dev/sensors for each
-registered client. The directory is called something like foo-i2c-4-65.
-The sensors module helps you to do this as easily as possible.
-
-The template
-------------
-
-You will need to define a ctl_table template. This template will automatically
-be copied to a newly allocated structure and filled in where necessary when
-you call sensors_register_entry.
-
-First, I will give an example definition.
-  static ctl_table foo_dir_table_template[] = {
-    { FOO_SYSCTL_FUNC1, "func1", NULL, 0, 0644, NULL, &i2c_proc_real,
-      &i2c_sysctl_real,NULL,&foo_func },
-    { FOO_SYSCTL_FUNC2, "func2", NULL, 0, 0644, NULL, &i2c_proc_real,
-      &i2c_sysctl_real,NULL,&foo_func },
-    { FOO_SYSCTL_DATA, "data", NULL, 0, 0644, NULL, &i2c_proc_real,
-      &i2c_sysctl_real,NULL,&foo_data },
-    { 0 }
-  };
-
-In the above example, three entries are defined. They can either be
-accessed through the /proc interface, in the /proc/sys/dev/sensors/*
-directories, as files named func1, func2 and data, or alternatively 
-through the sysctl interface, in the appropriate table, with identifiers
-FOO_SYSCTL_FUNC1, FOO_SYSCTL_FUNC2 and FOO_SYSCTL_DATA.
-
-The third, sixth and ninth parameters should always be NULL, and the
-fourth should always be 0. The fifth is the mode of the /proc file;
-0644 is safe, as the file will be owned by root:root. 
-
-The seventh and eighth parameters should be &i2c_proc_real and
-&i2c_sysctl_real if you want to export lists of reals (scaled
-integers). You can also use your own function for them, as usual.
-Finally, the last parameter is the call-back to gather the data
-(see below) if you use the *_proc_real functions. 
-
-
-Gathering the data
-------------------
-
-The call back functions (foo_func and foo_data in the above example)
-can be called in several ways; the operation parameter determines
-what should be done:
-
-  * If operation == SENSORS_PROC_REAL_INFO, you must return the
-    magnitude (scaling) in nrels_mag;
-  * If operation == SENSORS_PROC_REAL_READ, you must read information
-    from the chip and return it in results. The number of integers
-    to display should be put in nrels_mag;
-  * If operation == SENSORS_PROC_REAL_WRITE, you must write the
-    supplied information to the chip. nrels_mag will contain the number
-    of integers, results the integers themselves.
-
-The *_proc_real functions will display the elements as reals for the
-/proc interface. If you set the magnitude to 2, and supply 345 for
-SENSORS_PROC_REAL_READ, it would display 3.45; and if the user would
-write 45.6 to the /proc file, it would be returned as 4560 for
-SENSORS_PROC_REAL_WRITE. A magnitude may even be negative!
-
-An example function:
-
-  /* FOO_FROM_REG and FOO_TO_REG translate between scaled values and
-     register values. Note the use of the read cache. */
-  void foo_in(struct i2c_client *client, int operation, int ctl_name, 
-              int *nrels_mag, long *results)
-  {
-    struct foo_data *data = client->data;
-    int nr = ctl_name - FOO_SYSCTL_FUNC1; /* reduce to 0 upwards */
-    
-    if (operation == SENSORS_PROC_REAL_INFO)
-      *nrels_mag = 2;
-    else if (operation == SENSORS_PROC_REAL_READ) {
-      /* Update the readings cache (if necessary) */
-      foo_update_client(client);
-      /* Get the readings from the cache */
-      results[0] = FOO_FROM_REG(data->foo_func_base[nr]);
-      results[1] = FOO_FROM_REG(data->foo_func_more[nr]);
-      results[2] = FOO_FROM_REG(data->foo_func_readonly[nr]);
-      *nrels_mag = 2;
-    } else if (operation == SENSORS_PROC_REAL_WRITE) {
-      if (*nrels_mag >= 1) {
-        /* Update the cache */
-        data->foo_base[nr] = FOO_TO_REG(results[0]);
-        /* Update the chip */
-        foo_write_value(client,FOO_REG_FUNC_BASE(nr),data->foo_base[nr]);
-      }
-      if (*nrels_mag >= 2) {
-        /* Update the cache */
-        data->foo_more[nr] = FOO_TO_REG(results[1]);
-        /* Update the chip */
-        foo_write_value(client,FOO_REG_FUNC_MORE(nr),data->foo_more[nr]);
-      }
-    }
-  }
diff --git a/Documentation/input/input-programming.txt b/Documentation/input/input-programming.txt
index 180e0689..d9d5230 100644
--- a/Documentation/input/input-programming.txt
+++ b/Documentation/input/input-programming.txt
@@ -1,5 +1,3 @@
-$Id: input-programming.txt,v 1.4 2001/05/04 09:47:14 vojtech Exp $
-
 Programming input drivers
 ~~~~~~~~~~~~~~~~~~~~~~~~~
 
@@ -20,28 +18,51 @@
 #include <asm/irq.h>
 #include <asm/io.h>
 
+static struct input_dev *button_dev;
+
 static void button_interrupt(int irq, void *dummy, struct pt_regs *fp)
 {
-	input_report_key(&button_dev, BTN_1, inb(BUTTON_PORT) & 1);
-	input_sync(&button_dev);
+	input_report_key(button_dev, BTN_1, inb(BUTTON_PORT) & 1);
+	input_sync(button_dev);
 }
 
 static int __init button_init(void)
 {
+	int error;
+
 	if (request_irq(BUTTON_IRQ, button_interrupt, 0, "button", NULL)) {
                 printk(KERN_ERR "button.c: Can't allocate irq %d\n", button_irq);
                 return -EBUSY;
         }
-	
-	button_dev.evbit[0] = BIT(EV_KEY);
-	button_dev.keybit[LONG(BTN_0)] = BIT(BTN_0);
-	
-	input_register_device(&button_dev);
+
+	button_dev = input_allocate_device();
+	if (!button_dev) {
+		printk(KERN_ERR "button.c: Not enough memory\n");
+		error = -ENOMEM;
+		goto err_free_irq;
+	}
+
+	button_dev->evbit[0] = BIT(EV_KEY);
+	button_dev->keybit[LONG(BTN_0)] = BIT(BTN_0);
+
+	error = input_register_device(button_dev);
+	if (error) {
+		printk(KERN_ERR "button.c: Failed to register device\n");
+		goto err_free_dev;
+	}
+
+	return 0;
+
+ err_free_dev:
+	input_free_device(button_dev);
+ err_free_irq:
+	free_irq(BUTTON_IRQ, button_interrupt);
+	return error;
 }
 
 static void __exit button_exit(void)
 {
-        input_unregister_device(&button_dev);
+        input_unregister_device(button_dev);
 	free_irq(BUTTON_IRQ, button_interrupt);
 }
 
@@ -58,17 +79,18 @@
 booting the kernel, it grabs the required resources (it should also check
 for the presence of the device).
 
-Then it sets the input bitfields. This way the device driver tells the other
+Then it allocates a new input device structure with input_aloocate_device()
+and sets up input bitfields. This way the device driver tells the other
 parts of the input systems what it is - what events can be generated or
-accepted by this input device. Our example device can only generate EV_KEY type
-events, and from those only BTN_0 event code. Thus we only set these two
-bits. We could have used
+accepted by this input device. Our example device can only generate EV_KEY
+type events, and from those only BTN_0 event code. Thus we only set these
+two bits. We could have used
 
 	set_bit(EV_KEY, button_dev.evbit);
 	set_bit(BTN_0, button_dev.keybit);
 
 as well, but with more than single bits the first approach tends to be
-shorter. 
+shorter.
 
 Then the example driver registers the input device structure by calling
 
@@ -76,16 +98,15 @@
 
 This adds the button_dev structure to linked lists of the input driver and
 calls device handler modules _connect functions to tell them a new input
-device has appeared. Because the _connect functions may call kmalloc(,
-GFP_KERNEL), which can sleep, input_register_device() must not be called
-from an interrupt or with a spinlock held.
+device has appeared. input_register_device() may sleep and therefore must
+not be called from an interrupt or with a spinlock held.
 
 While in use, the only used function of the driver is
 
 	button_interrupt()
 
 which upon every interrupt from the button checks its state and reports it
-via the 
+via the
 
 	input_report_key()
 
@@ -113,16 +134,10 @@
 release the interrupt and when it must resume polling or grab the interrupt
 again. To do that, we would add this to our example driver:
 
-int button_used = 0;
-
 static int button_open(struct input_dev *dev)
 {
-        if (button_used++)
-                return 0;
-
 	if (request_irq(BUTTON_IRQ, button_interrupt, 0, "button", NULL)) {
                 printk(KERN_ERR "button.c: Can't allocate irq %d\n", button_irq);
-                button_used--;
                 return -EBUSY;
         }
 
@@ -131,20 +146,21 @@
 
 static void button_close(struct input_dev *dev)
 {
-        if (!--button_used)
-                free_irq(IRQ_AMIGA_VERTB, button_interrupt);
+        free_irq(IRQ_AMIGA_VERTB, button_interrupt);
 }
 
 static int __init button_init(void)
 {
 	...
-	button_dev.open = button_open;
-	button_dev.close = button_close;
+	button_dev->open = button_open;
+	button_dev->close = button_close;
 	...
 }
 
-Note the button_used variable - we have to track how many times the open
-function was called to know when exactly our device stops being used.
+Note that input core keeps track of number of users for the device and
+makes sure that dev->open() is called only when the first user connects
+to the device and that dev->close() is called when the very last user
+disconnects. Calls to both callbacks are serialized.
 
 The open() callback should return a 0 in case of success or any nonzero value
 in case of failure. The close() callback (which is void) must always succeed.
@@ -175,7 +191,7 @@
 
 	input_report_rel(struct input_dev *dev, int code, int value)
 
-function. Events are generated only for nonzero value. 
+function. Events are generated only for nonzero value.
 
 However EV_ABS requires a little special care. Before calling
 input_register_device, you have to fill additional fields in the input_dev
@@ -187,6 +203,10 @@
 	button_dev.absfuzz[ABS_X] = 4;
 	button_dev.absflat[ABS_X] = 8;
 
+Or, you can just say:
+
+	input_set_abs_params(button_dev, ABS_X, 0, 255, 4, 8);
+
 This setting would be appropriate for a joystick X axis, with the minimum of
 0, maximum of 255 (which the joystick *must* be able to reach, no problem if
 it sometimes reports more, but it must be able to always reach the min and
@@ -197,14 +217,7 @@
 that the thing is precise and always returns to exactly the center position
 (if it has any).
 
-1.4 The void *private field
-~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-This field in the input structure can be used to point to any private data
-structures in the input device driver, in case the driver handles more than
-one device. You'll need it in the open and close callbacks.
-
-1.5 NBITS(), LONG(), BIT()
+1.4 NBITS(), LONG(), BIT()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 These three macros from input.h help some bitfield computations:
@@ -213,13 +226,9 @@
 	LONG(x)  - returns the index in the array in longs for bit x
 	BIT(x)   - returns the index in a long for bit x
 
-1.6 The number, id* and name fields
+1.5 The id* and name fields
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-The dev->number is assigned by the input system to the input device when it
-is registered. It has no use except for identifying the device to the user
-in system messages.
-
 The dev->name should be set before registering the input device by the input
 device driver. It's a string like 'Generic button device' containing a
 user friendly name of the device.
@@ -234,15 +243,25 @@
 
 The id and name fields can be passed to userland via the evdev interface.
 
-1.7 The keycode, keycodemax, keycodesize fields
+1.6 The keycode, keycodemax, keycodesize fields
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-These two fields will be used for any input devices that report their data
-as scancodes. If not all scancodes can be known by autodetection, they may
-need to be set by userland utilities. The keycode array then is an array
-used to map from scancodes to input system keycodes. The keycode max will
-contain the size of the array and keycodesize the size of each entry in it
-(in bytes).
+These three fields should be used by input devices that have dense keymaps.
+The keycode is an array used to map from scancodes to input system keycodes.
+The keycode max should contain the size of the array and keycodesize the
+size of each entry in it (in bytes).
+
+Userspace can query and alter current scancode to keycode mappings using
+EVIOCGKEYCODE and EVIOCSKEYCODE ioctls on corresponding evdev interface.
+When a device has all 3 aforementioned fields filled in, the driver may
+rely on kernel's default implementation of setting and querying keycode
+mappings.
+
+1.7 dev->getkeycode() and dev->setkeycode()
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+getkeycode() and setkeycode() callbacks allow drivers to override default
+keycode/keycodesize/keycodemax mapping mechanism provided by input core
+and implement sparse keycode maps.
 
 1.8 Key autorepeat
 ~~~~~~~~~~~~~~~~~~
@@ -266,7 +285,7 @@
 driver can handle these events, it has to set the respective bits in evbit,
 *and* also the callback routine:
 
-	button_dev.event = button_event;
+	button_dev->event = button_event;
 
 int button_event(struct input_dev *dev, unsigned int type, unsigned int code, int value);
 {
diff --git a/Documentation/pci.txt b/Documentation/pci.txt
index cdf2f3c..e2c9d0a 100644
--- a/Documentation/pci.txt
+++ b/Documentation/pci.txt
@@ -124,10 +124,6 @@
 
 	err_handler	See Documentation/pci-error-recovery.txt
 
-	multithread_probe	Enable multi-threaded probe/scan. Driver must
-			provide its own locking/syncronization for init
-			operations if this is enabled.
-
 
 The ID table is an array of struct pci_device_id entries ending with an
 all-zero entry.  Each entry consists of:
@@ -163,9 +159,9 @@
 /sys/bus/pci/drivers/{driver}/new_id
 
 All fields are passed in as hexadecimal values (no leading 0x).
-Users need pass only as many fields as necessary:
-	o vendor, device, subvendor, and subdevice fields default
-	  to PCI_ANY_ID (FFFFFFFF),
+The vendor and device fields are mandatory, the others are optional. Users
+need pass only as many optional fields as necessary:
+	o subvendor and subdevice fields default to PCI_ANY_ID (FFFFFFFF)
 	o class and classmask fields default to 0
 	o driver_data defaults to 0UL.
 
@@ -549,8 +545,6 @@
 pci_set_power_state()		Set PCI Power Management state (0=D0 ... 3=D3)
 pci_find_capability()		Find specified capability in device's capability
 				list.
-pci_module_init()		Inline helper function for ensuring correct
-				pci_driver initialization and error handling.
 pci_resource_start()		Returns bus start address for a given PCI region
 pci_resource_end()		Returns bus end address for a given PCI region
 pci_resource_len()		Returns the byte length of a PCI region
diff --git a/Documentation/power/pci.txt b/Documentation/power/pci.txt
index b6a3cbf..e00b099 100644
--- a/Documentation/power/pci.txt
+++ b/Documentation/power/pci.txt
@@ -203,7 +203,7 @@
 
 Usage:
 
-if (dev->driver && dev->driver->suspend)
+if (dev->driver && dev->driver->resume)
 	dev->driver->resume(dev)
 
 The resume callback may be called from any power state, and is always meant to
diff --git a/Documentation/scsi/aacraid.txt b/Documentation/scsi/aacraid.txt
index dc8e44fc..2368e7e 100644
--- a/Documentation/scsi/aacraid.txt
+++ b/Documentation/scsi/aacraid.txt
@@ -37,7 +37,11 @@
 	9005:0286:9005:029d	Adaptec	2420SA (Intruder HP release)
 	9005:0286:9005:02ac	Adaptec	1800 (Typhoon44)
 	9005:0285:9005:02b5	Adaptec	5445 (Voodoo44)
+	9005:0285:15d9:02b5	SMC	AOC-USAS-S4i
+	9005:0285:15d9:02c9	SMC	AOC-USAS-S4iR
 	9005:0285:9005:02b6	Adaptec	5805 (Voodoo80)
+	9005:0285:15d9:02b6	SMC	AOC-USAS-S8i
+	9005:0285:15d9:02ca	SMC	AOC-USAS-S8iR
 	9005:0285:9005:02b7	Adaptec	5085 (Voodoo08)
 	9005:0285:9005:02bb	Adaptec	3405 (Marauder40LP)
 	9005:0285:9005:02bc	Adaptec	3805 (Marauder80LP)
@@ -93,6 +97,9 @@
 	9005:0286:9005:02ae		(Aurora Lite ARK)
 	9005:0285:9005:02b0		(Sunrise Lake ARK)
 	9005:0285:9005:02b1	Adaptec	(Voodoo 8 internal 8 external)
+	9005:0285:108e:7aac	SUN	STK RAID REM (Voodoo44 Coyote)
+	9005:0285:108e:0286	SUN	SG-XPCIESAS-R-IN (Cougar)
+	9005:0285:108e:0287	SUN	SG-XPCIESAS-R-EX (Prometheus)
 
 People
 -------------------------
diff --git a/Documentation/scsi/ncr53c8xx.txt b/Documentation/scsi/ncr53c8xx.txt
index caf10b1..88ef88b 100644
--- a/Documentation/scsi/ncr53c8xx.txt
+++ b/Documentation/scsi/ncr53c8xx.txt
@@ -562,11 +562,6 @@
 support by the driver of this feature at linux start-up and enable
 this feature after boot-up only for devices that support it safely.
 
-CONFIG_SCSI_NCR53C8XX_PROFILE_SUPPORT  (default answer: n)
-    This option must be set for profiling information to be gathered 
-    and printed out through the proc file system. This features may 
-    impact performances.
-
 CONFIG_SCSI_NCR53C8XX_IOMAPPED       (default answer: n)
     Answer "y" if you suspect your mother board to not allow memory mapped I/O.
     May slow down performance a little.  This option is required by
diff --git a/Documentation/usb/usb-serial.txt b/Documentation/usb/usb-serial.txt
index d61f6e7..b18e86a 100644
--- a/Documentation/usb/usb-serial.txt
+++ b/Documentation/usb/usb-serial.txt
@@ -42,7 +42,7 @@
   http://www.connecttech.com
 
   For any questions or problems with this driver, please contact
-  Stuart MacDonald at stuartm@connecttech.com
+  Connect Tech's Support Department at support@connecttech.com
 
 
 HandSpring Visor, Palm USB, and Clié USB driver
diff --git a/MAINTAINERS b/MAINTAINERS
index 4b307e6..0492dd8 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -733,6 +733,13 @@
 L:	linux-kernel@vger.kernel.org
 S:	Maintained
 
+BLACKFIN I2C TWI DRIVER
+P:	Sonic Zhang
+M:	sonic.zhang@analog.com
+L:	uclinux-dist-devel@blackfin.uclinux.org (subscribers-only)
+W:	http://blackfin.uclinux.org/
+S:	Supported
+
 BLOCK LAYER
 P:	Jens Axboe
 M:	axboe@kernel.dk
@@ -1459,6 +1466,11 @@
 W:	http://www.icp-vortex.com/
 S:	Supported
 
+GENERIC GPIO I2C DRIVER
+P:	Haavard Skinnemoen
+M:	hskinnemoen@atmel.com
+S:	Supported
+
 GENERIC HDLC DRIVER, N2, C101, PCI200SYN and WANXL DRIVERS
 P:	Krzysztof Halasa
 M:	khc@pm.waw.pl
@@ -1631,6 +1643,13 @@
 T:	quilt http://khali.linux-fr.org/devel/linux-2.6/jdelvare-i2c/
 S:	Maintained
 
+I2C-TINY-USB DRIVER
+P:	Till Harbaum
+M:	till@harbaum.org
+L:	i2c@lm-sensors.org
+T:	http://www.harbaum.org/till/i2c_tiny_usb
+S:	Maintained
+
 i386 BOOT CODE
 P:	Riley H. Williams
 M:	Riley@Williams.Name
@@ -2209,6 +2228,16 @@
 W:	http://www.tazenda.demon.co.uk/phil/linux-hp
 S:	Maintained
 
+MAC80211
+P:	Jiri Benc
+M:	jbenc@suse.cz
+P:	Michael Wu
+M:	flamingice@sourmilk.net
+L:	linux-wireless@vger.kernel.org
+W:	http://linuxwireless.org/
+T:	git kernel.org:/pub/scm/linux/kernel/git/jbenc/mac80211.git
+S:	Maintained
+
 MARVELL YUKON / SYSKONNECT DRIVER
 P:	Mirko Lindner
 M: 	mlindner@syskonnect.de
@@ -3640,8 +3669,8 @@
 S:	Maintained
 
 USB SERIAL WHITEHEAT DRIVER
-P:	Stuart MacDonald
-M:	stuartm@connecttech.com
+P:	Support Department
+M:	support@connecttech.com
 L:	linux-usb-users@lists.sourceforge.net
 L:	linux-usb-devel@lists.sourceforge.net
 W:	http://www.connecttech.com
diff --git a/arch/alpha/kernel/err_common.c b/arch/alpha/kernel/err_common.c
index 687580b..13d53b1 100644
--- a/arch/alpha/kernel/err_common.c
+++ b/arch/alpha/kernel/err_common.c
@@ -7,7 +7,6 @@
  */
 
 #include <linux/init.h>
-#include <linux/pci.h>
 #include <linux/sched.h>
 
 #include <asm/io.h>
diff --git a/arch/alpha/kernel/err_ev6.c b/arch/alpha/kernel/err_ev6.c
index 69b5f4e..11aee01 100644
--- a/arch/alpha/kernel/err_ev6.c
+++ b/arch/alpha/kernel/err_ev6.c
@@ -7,7 +7,6 @@
  */
 
 #include <linux/init.h>
-#include <linux/pci.h>
 #include <linux/sched.h>
 
 #include <asm/io.h>
diff --git a/arch/alpha/kernel/err_ev7.c b/arch/alpha/kernel/err_ev7.c
index 95463ab..bc799f7 100644
--- a/arch/alpha/kernel/err_ev7.c
+++ b/arch/alpha/kernel/err_ev7.c
@@ -7,7 +7,6 @@
  */
 
 #include <linux/init.h>
-#include <linux/pci.h>
 #include <linux/sched.h>
 
 #include <asm/io.h>
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index e7baca2..db00376 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -255,6 +255,7 @@
 	depends on MMU
 	select PLAT_IOP
 	select PCI
+	select ARCH_SUPPORTS_MSI
 	help
 	  Support for Intel's IOP13XX (XScale) family of processors.
 
diff --git a/arch/arm/mach-omap1/pm.c b/arch/arm/mach-omap1/pm.c
index 0383ab3..6f4ea4b 100644
--- a/arch/arm/mach-omap1/pm.c
+++ b/arch/arm/mach-omap1/pm.c
@@ -72,12 +72,12 @@
 
 static unsigned short enable_dyn_sleep = 1;
 
-static ssize_t omap_pm_sleep_while_idle_show(struct subsystem * subsys, char *buf)
+static ssize_t omap_pm_sleep_while_idle_show(struct kset *kset, char *buf)
 {
 	return sprintf(buf, "%hu\n", enable_dyn_sleep);
 }
 
-static ssize_t omap_pm_sleep_while_idle_store(struct subsystem * subsys,
+static ssize_t omap_pm_sleep_while_idle_store(struct kset *kset,
 					      const char * buf,
 					      size_t n)
 {
@@ -100,7 +100,7 @@
 	.store  = omap_pm_sleep_while_idle_store,
 };
 
-extern struct subsystem power_subsys;
+extern struct kset power_subsys;
 static void (*omap_sram_idle)(void) = NULL;
 static void (*omap_sram_suspend)(unsigned long r0, unsigned long r1) = NULL;
 
diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig
index c6f8d68..a9af760 100644
--- a/arch/i386/Kconfig
+++ b/arch/i386/Kconfig
@@ -1057,6 +1057,7 @@
 	bool "PCI support" if !X86_VISWS
 	depends on !X86_VOYAGER
 	default y if X86_VISWS
+	select ARCH_SUPPORTS_MSI if (X86_LOCAL_APIC && X86_IO_APIC)
 	help
 	  Find out whether you have a PCI motherboard. PCI is the name of a
 	  bus system, i.e. the way the CPU talks to the other stuff inside
diff --git a/arch/i386/kernel/cpu/cpufreq/longhaul.c b/arch/i386/kernel/cpu/cpufreq/longhaul.c
index 2b030d6..a3df9c0 100644
--- a/arch/i386/kernel/cpu/cpufreq/longhaul.c
+++ b/arch/i386/kernel/cpu/cpufreq/longhaul.c
@@ -590,20 +590,23 @@
 static int enable_arbiter_disable(void)
 {
 	struct pci_dev *dev;
+	int status;
 	int reg;
 	u8 pci_cmd;
 
+	status = 1;
 	/* Find PLE133 host bridge */
 	reg = 0x78;
-	dev = pci_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8601_0, NULL);
+	dev = pci_get_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8601_0,
+			     NULL);
 	/* Find CLE266 host bridge */
 	if (dev == NULL) {
 		reg = 0x76;
-		dev = pci_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_862X_0, NULL);
+		dev = pci_get_device(PCI_VENDOR_ID_VIA,
+				     PCI_DEVICE_ID_VIA_862X_0, NULL);
 		/* Find CN400 V-Link host bridge */
 		if (dev == NULL)
-			dev = pci_find_device(PCI_VENDOR_ID_VIA, 0x7259, NULL);
-
+			dev = pci_get_device(PCI_VENDOR_ID_VIA, 0x7259, NULL);
 	}
 	if (dev != NULL) {
 		/* Enable access to port 0x22 */
@@ -615,10 +618,11 @@
 			if (!(pci_cmd & 1<<7)) {
 				printk(KERN_ERR PFX
 					"Can't enable access to port 0x22.\n");
-				return 0;
+				status = 0;
 			}
 		}
-		return 1;
+		pci_dev_put(dev);
+		return status;
 	}
 	return 0;
 }
@@ -629,7 +633,7 @@
 	u8 pci_cmd;
 
 	/* Find VT8235 southbridge */
-	dev = pci_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235, NULL);
+	dev = pci_get_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235, NULL);
 	if (dev != NULL) {
 		/* Set transition time to max */
 		pci_read_config_byte(dev, 0xec, &pci_cmd);
@@ -641,6 +645,7 @@
 		pci_read_config_byte(dev, 0xe5, &pci_cmd);
 		pci_cmd |= 1 << 7;
 		pci_write_config_byte(dev, 0xe5, pci_cmd);
+		pci_dev_put(dev);
 		return 1;
 	}
 	return 0;
@@ -678,7 +683,7 @@
 				sizeof(samuel2_eblcr));
 			break;
 		case 1 ... 15:
-			longhaul_version = TYPE_LONGHAUL_V2;
+			longhaul_version = TYPE_LONGHAUL_V1;
 			if (c->x86_mask < 8) {
 				cpu_model = CPU_SAMUEL2;
 				cpuname = "C3 'Samuel 2' [C5B]";
diff --git a/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c b/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c
index 4786fed..4c76b51 100644
--- a/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c
+++ b/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c
@@ -27,7 +27,6 @@
 #include <linux/cpufreq.h>
 #include <linux/slab.h>
 #include <linux/cpumask.h>
-#include <linux/sched.h>	/* current / set_cpus_allowed() */
 
 #include <asm/processor.h>
 #include <asm/msr.h>
@@ -62,7 +61,7 @@
 	if (!cpu_online(cpu) || (newstate > DC_DISABLE) || (newstate == DC_RESV))
 		return -EINVAL;
 
-	rdmsr(MSR_IA32_THERM_STATUS, l, h);
+	rdmsr_on_cpu(cpu, MSR_IA32_THERM_STATUS, &l, &h);
 
 	if (l & 0x01)
 		dprintk("CPU#%d currently thermal throttled\n", cpu);
@@ -70,10 +69,10 @@
 	if (has_N44_O17_errata[cpu] && (newstate == DC_25PT || newstate == DC_DFLT))
 		newstate = DC_38PT;
 
-	rdmsr(MSR_IA32_THERM_CONTROL, l, h);
+	rdmsr_on_cpu(cpu, MSR_IA32_THERM_CONTROL, &l, &h);
 	if (newstate == DC_DISABLE) {
 		dprintk("CPU#%d disabling modulation\n", cpu);
-		wrmsr(MSR_IA32_THERM_CONTROL, l & ~(1<<4), h);
+		wrmsr_on_cpu(cpu, MSR_IA32_THERM_CONTROL, l & ~(1<<4), h);
 	} else {
 		dprintk("CPU#%d setting duty cycle to %d%%\n",
 			cpu, ((125 * newstate) / 10));
@@ -84,7 +83,7 @@
 		 */
 		l = (l & ~14);
 		l = l | (1<<4) | ((newstate & 0x7)<<1);
-		wrmsr(MSR_IA32_THERM_CONTROL, l, h);
+		wrmsr_on_cpu(cpu, MSR_IA32_THERM_CONTROL, l, h);
 	}
 
 	return 0;
@@ -111,7 +110,6 @@
 {
 	unsigned int    newstate = DC_RESV;
 	struct cpufreq_freqs freqs;
-	cpumask_t cpus_allowed;
 	int i;
 
 	if (cpufreq_frequency_table_target(policy, &p4clockmod_table[0], target_freq, relation, &newstate))
@@ -132,17 +130,8 @@
 	/* run on each logical CPU, see section 13.15.3 of IA32 Intel Architecture Software
 	 * Developer's Manual, Volume 3
 	 */
-	cpus_allowed = current->cpus_allowed;
-
-	for_each_cpu_mask(i, policy->cpus) {
-		cpumask_t this_cpu = cpumask_of_cpu(i);
-
-		set_cpus_allowed(current, this_cpu);
-		BUG_ON(smp_processor_id() != i);
-
+	for_each_cpu_mask(i, policy->cpus)
 		cpufreq_p4_setdc(i, p4clockmod_table[newstate].index);
-	}
-	set_cpus_allowed(current, cpus_allowed);
 
 	/* notifiers */
 	for_each_cpu_mask(i, policy->cpus) {
@@ -256,17 +245,9 @@
 
 static unsigned int cpufreq_p4_get(unsigned int cpu)
 {
-	cpumask_t cpus_allowed;
 	u32 l, h;
 
-	cpus_allowed = current->cpus_allowed;
-
-	set_cpus_allowed(current, cpumask_of_cpu(cpu));
-	BUG_ON(smp_processor_id() != cpu);
-
-	rdmsr(MSR_IA32_THERM_CONTROL, l, h);
-
-	set_cpus_allowed(current, cpus_allowed);
+	rdmsr_on_cpu(cpu, MSR_IA32_THERM_CONTROL, &l, &h);
 
 	if (l & 0x10) {
 		l = l >> 1;
diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c
index fe3b670..7cf3d20 100644
--- a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c
+++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c
@@ -661,7 +661,8 @@
 
 	dprintk("cfid 0x%x, cvid 0x%x\n", data->currfid, data->currvid);
 	data->powernow_table = powernow_table;
-	print_basics(data);
+	if (first_cpu(cpu_core_map[data->cpu]) == data->cpu)
+		print_basics(data);
 
 	for (j = 0; j < data->numps; j++)
 		if ((pst[j].fid==data->currfid) && (pst[j].vid==data->currvid))
@@ -814,7 +815,8 @@
 
 	/* fill in data */
 	data->numps = data->acpi_data.state_count;
-	print_basics(data);
+	if (first_cpu(cpu_core_map[data->cpu]) == data->cpu)
+		print_basics(data);
 	powernow_k8_acpi_pst_values(data, 0);
 
 	/* notify BIOS that we exist */
diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k8.h b/arch/i386/kernel/cpu/cpufreq/powernow-k8.h
index 0fb2a30..95be501 100644
--- a/arch/i386/kernel/cpu/cpufreq/powernow-k8.h
+++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.h
@@ -215,8 +215,10 @@
 
 static void powernow_k8_acpi_pst_values(struct powernow_k8_data *data, unsigned int index);
 
+#ifdef CONFIG_X86_POWERNOW_K8_ACPI
 static int fill_powernow_table_pstate(struct powernow_k8_data *data, struct cpufreq_frequency_table *powernow_table);
 static int fill_powernow_table_fidvid(struct powernow_k8_data *data, struct cpufreq_frequency_table *powernow_table);
+#endif
 
 #ifdef CONFIG_SMP
 static inline void define_siblings(int cpu, cpumask_t cpu_sharedcore_mask[])
diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
index f43b987..35489fd 100644
--- a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
+++ b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
@@ -720,6 +720,7 @@
 			cpu_set(j, set_mask);
 
 		set_cpus_allowed(current, set_mask);
+		preempt_disable();
 		if (unlikely(!cpu_isset(smp_processor_id(), set_mask))) {
 			dprintk("couldn't limit to CPUs in this domain\n");
 			retval = -EAGAIN;
@@ -727,6 +728,7 @@
 				/* We haven't started the transition yet. */
 				goto migrate_end;
 			}
+			preempt_enable();
 			break;
 		}
 
@@ -761,10 +763,13 @@
 		}
 
 		wrmsr(MSR_IA32_PERF_CTL, oldmsr, h);
-		if (policy->shared_type == CPUFREQ_SHARED_TYPE_ANY)
+		if (policy->shared_type == CPUFREQ_SHARED_TYPE_ANY) {
+			preempt_enable();
 			break;
+		}
 
 		cpu_set(j, covered_cpus);
+		preempt_enable();
 	}
 
 	for_each_cpu_mask(k, online_policy_cpus) {
@@ -796,8 +801,11 @@
 			cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
 		}
 	}
+	set_cpus_allowed(current, saved_mask);
+	return 0;
 
 migrate_end:
+	preempt_enable();
 	set_cpus_allowed(current, saved_mask);
 	return 0;
 }
diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c b/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c
index d59277c..b1acc8c 100644
--- a/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c
+++ b/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c
@@ -13,7 +13,6 @@
 #include <linux/moduleparam.h>
 #include <linux/init.h>
 #include <linux/cpufreq.h>
-#include <linux/pci.h>
 #include <linux/slab.h>
 
 #include <asm/msr.h>
diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c b/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c
index ff0d898..e1c509a 100644
--- a/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c
+++ b/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c
@@ -17,10 +17,10 @@
 #include <linux/moduleparam.h>
 #include <linux/init.h>
 #include <linux/cpufreq.h>
-#include <linux/pci.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
 #include <asm/ist.h>
+#include <asm/io.h>
 
 #include "speedstep-lib.h"
 
diff --git a/arch/i386/kernel/i8253.c b/arch/i386/kernel/i8253.c
index 10cef5c..f8a3c40 100644
--- a/arch/i386/kernel/i8253.c
+++ b/arch/i386/kernel/i8253.c
@@ -110,7 +110,7 @@
 	 * Start pit with the boot cpu mask and make it global after the
 	 * IO_APIC has been initialized.
 	 */
-	pit_clockevent.cpumask = cpumask_of_cpu(0);
+	pit_clockevent.cpumask = cpumask_of_cpu(smp_processor_id());
 	pit_clockevent.mult = div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC, 32);
 	pit_clockevent.max_delta_ns =
 		clockevent_delta2ns(0x7FFF, &pit_clockevent);
diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c
index f23a17b..1b623cd 100644
--- a/arch/i386/kernel/io_apic.c
+++ b/arch/i386/kernel/io_apic.c
@@ -2579,19 +2579,19 @@
 	if (irq < 0)
 		return irq;
 
-	set_irq_msi(irq, desc);
 	ret = msi_compose_msg(dev, irq, &msg);
 	if (ret < 0) {
 		destroy_irq(irq);
 		return ret;
 	}
 
+	set_irq_msi(irq, desc);
 	write_msi_msg(irq, &msg);
 
 	set_irq_chip_and_handler_name(irq, &msi_chip, handle_edge_irq,
 				      "edge");
 
-	return irq;
+	return 0;
 }
 
 void arch_teardown_msi_irq(unsigned int irq)
diff --git a/arch/i386/mach-voyager/setup.c b/arch/i386/mach-voyager/setup.c
index cfa16c1..447bb10 100644
--- a/arch/i386/mach-voyager/setup.c
+++ b/arch/i386/mach-voyager/setup.c
@@ -40,10 +40,16 @@
 {
 }
 
-static struct irqaction irq0  = { timer_interrupt, IRQF_DISABLED, CPU_MASK_NONE, "timer", NULL, NULL};
+static struct irqaction irq0  = {
+	.handler = timer_interrupt,
+	.flags = IRQF_DISABLED | IRQF_NOBALANCING,
+	.mask = CPU_MASK_NONE,
+	.name = "timer"
+};
 
 void __init time_init_hook(void)
 {
+	irq0.mask = cpumask_of_cpu(safe_smp_processor_id());
 	setup_irq(0, &irq0);
 }
 
diff --git a/arch/i386/mach-voyager/voyager_cat.c b/arch/i386/mach-voyager/voyager_cat.c
index 943a947..26a2d4c 100644
--- a/arch/i386/mach-voyager/voyager_cat.c
+++ b/arch/i386/mach-voyager/voyager_cat.c
@@ -1111,7 +1111,7 @@
 				printk(KERN_ERR "Voyager front panel switch turned off\n");
 				voyager_status.switch_off = 1;
 				voyager_status.request_from_kernel = 1;
-				up(&kvoyagerd_sem);
+				wake_up_process(voyager_thread);
 			}
 			/* Tell the hardware we're taking care of the
 			 * shutdown, otherwise it will power the box off
@@ -1157,7 +1157,7 @@
 			outb(VOYAGER_CAT_END, CAT_CMD);
 			voyager_status.power_fail = 1;
 			voyager_status.request_from_kernel = 1;
-			up(&kvoyagerd_sem);
+			wake_up_process(voyager_thread);
 		}
 		
 		
diff --git a/arch/i386/mach-voyager/voyager_smp.c b/arch/i386/mach-voyager/voyager_smp.c
index b9ce33c..1a5e448 100644
--- a/arch/i386/mach-voyager/voyager_smp.c
+++ b/arch/i386/mach-voyager/voyager_smp.c
@@ -536,15 +536,6 @@
 		& ~( voyager_extended_vic_processors
 		     & voyager_allowed_boot_processors);
 
-	/* For the 486, we can't use the 4Mb page table trick, so
-	 * must map a region of memory */
-#ifdef CONFIG_M486
-	int i;
-	unsigned long *page_table_copies = (unsigned long *)
-		__get_free_page(GFP_KERNEL);
-#endif
-	pgd_t orig_swapper_pg_dir0;
-
 	/* This is an area in head.S which was used to set up the
 	 * initial kernel stack.  We need to alter this to give the
 	 * booting CPU a new stack (taken from its idle process) */
@@ -573,6 +564,8 @@
 	hijack_source.idt.Segment = (start_phys_address >> 4) & 0xFFFF;
 
 	cpucount++;
+	alternatives_smp_switch(1);
+
 	idle = fork_idle(cpu);
 	if(IS_ERR(idle))
 		panic("failed fork for CPU%d", cpu);
@@ -587,24 +580,11 @@
 	VDEBUG(("VOYAGER SMP: Booting CPU%d at 0x%lx[%x:%x], stack %p\n", cpu, 
 		(unsigned long)hijack_source.val, hijack_source.idt.Segment,
 		hijack_source.idt.Offset, stack_start.esp));
-	/* set the original swapper_pg_dir[0] to map 0 to 4Mb transparently
-	 * (so that the booting CPU can find start_32 */
-	orig_swapper_pg_dir0 = swapper_pg_dir[0];
-#ifdef CONFIG_M486
-	if(page_table_copies == NULL)
-		panic("No free memory for 486 page tables\n");
-	for(i = 0; i < PAGE_SIZE/sizeof(unsigned long); i++)
-		page_table_copies[i] = (i * PAGE_SIZE) 
-			| _PAGE_RW | _PAGE_USER | _PAGE_PRESENT;
 
-	((unsigned long *)swapper_pg_dir)[0] = 
-		((virt_to_phys(page_table_copies)) & PAGE_MASK)
-		| _PAGE_RW | _PAGE_USER | _PAGE_PRESENT;
-#else
-	((unsigned long *)swapper_pg_dir)[0] = 
-		(virt_to_phys(pg0) & PAGE_MASK)
-		| _PAGE_RW | _PAGE_USER | _PAGE_PRESENT;
-#endif
+	/* init lowmem identity mapping */
+	clone_pgd_range(swapper_pg_dir, swapper_pg_dir + USER_PGD_PTRS,
+			min_t(unsigned long, KERNEL_PGD_PTRS, USER_PGD_PTRS));
+	flush_tlb_all();
 
 	if(quad_boot) {
 		printk("CPU %d: non extended Quad boot\n", cpu);
@@ -647,11 +627,7 @@
 		udelay(100);
 	}
 	/* reset the page table */
-	swapper_pg_dir[0] = orig_swapper_pg_dir0;
-	local_flush_tlb();
-#ifdef CONFIG_M486
-	free_page((unsigned long)page_table_copies);
-#endif
+	zap_low_mappings();
 	  
 	if (cpu_booted_map) {
 		VDEBUG(("CPU%d: Booted successfully, back in CPU %d\n",
@@ -1068,20 +1044,11 @@
 	}
 }
 
-/* Call this function on all CPUs using the function_interrupt above 
-    <func> The function to run. This must be fast and non-blocking.
-    <info> An arbitrary pointer to pass to the function.
-    <retry> If true, keep retrying until ready.
-    <wait> If true, wait until function has completed on other CPUs.
-    [RETURNS] 0 on success, else a negative status code. Does not return until
-    remote CPUs are nearly ready to execute <<func>> or are or have executed.
-*/
-int
-smp_call_function (void (*func) (void *info), void *info, int retry,
-		   int wait)
+static int
+__smp_call_function_mask (void (*func) (void *info), void *info, int retry,
+			  int wait, __u32 mask)
 {
 	struct call_data_struct data;
-	__u32 mask = cpus_addr(cpu_online_map)[0];
 
 	mask &= ~(1<<smp_processor_id());
 
@@ -1102,7 +1069,7 @@
 	call_data = &data;
 	wmb();
 	/* Send a message to all other CPUs and wait for them to respond */
-	send_CPI_allbutself(VIC_CALL_FUNCTION_CPI);
+	send_CPI(mask, VIC_CALL_FUNCTION_CPI);
 
 	/* Wait for response */
 	while (data.started)
@@ -1116,8 +1083,48 @@
 
 	return 0;
 }
+
+/* Call this function on all CPUs using the function_interrupt above
+    <func> The function to run. This must be fast and non-blocking.
+    <info> An arbitrary pointer to pass to the function.
+    <retry> If true, keep retrying until ready.
+    <wait> If true, wait until function has completed on other CPUs.
+    [RETURNS] 0 on success, else a negative status code. Does not return until
+    remote CPUs are nearly ready to execute <<func>> or are or have executed.
+*/
+int
+smp_call_function(void (*func) (void *info), void *info, int retry,
+		   int wait)
+{
+	__u32 mask = cpus_addr(cpu_online_map)[0];
+
+	return __smp_call_function_mask(func, info, retry, wait, mask);
+}
 EXPORT_SYMBOL(smp_call_function);
 
+/*
+ * smp_call_function_single - Run a function on another CPU
+ * @func: The function to run. This must be fast and non-blocking.
+ * @info: An arbitrary pointer to pass to the function.
+ * @nonatomic: Currently unused.
+ * @wait: If true, wait until function has completed on other CPUs.
+ *
+ * Retrurns 0 on success, else a negative status code.
+ *
+ * Does not return until the remote CPU is nearly ready to execute <func>
+ * or is or has executed.
+ */
+
+int
+smp_call_function_single(int cpu, void (*func) (void *info), void *info,
+			 int nonatomic, int wait)
+{
+	__u32 mask = 1 << cpu;
+
+	return __smp_call_function_mask(func, info, nonatomic, wait, mask);
+}
+EXPORT_SYMBOL(smp_call_function_single);
+
 /* Sorry about the name.  In an APIC based system, the APICs
  * themselves are programmed to send a timer interrupt.  This is used
  * by linux to reschedule the processor.  Voyager doesn't have this,
diff --git a/arch/i386/mach-voyager/voyager_thread.c b/arch/i386/mach-voyager/voyager_thread.c
index f398873..fdc1d92 100644
--- a/arch/i386/mach-voyager/voyager_thread.c
+++ b/arch/i386/mach-voyager/voyager_thread.c
@@ -24,33 +24,16 @@
 #include <linux/kmod.h>
 #include <linux/completion.h>
 #include <linux/sched.h>
+#include <linux/kthread.h>
 #include <asm/desc.h>
 #include <asm/voyager.h>
 #include <asm/vic.h>
 #include <asm/mtrr.h>
 #include <asm/msr.h>
 
-#define THREAD_NAME "kvoyagerd"
 
-/* external variables */
-int kvoyagerd_running = 0;
-DECLARE_MUTEX_LOCKED(kvoyagerd_sem);
-
-static int thread(void *);
-
-static __u8 set_timeout = 0;
-
-/* Start the machine monitor thread.  Return 1 if OK, 0 if fail */
-static int __init
-voyager_thread_start(void)
-{
-	if(kernel_thread(thread, NULL, CLONE_KERNEL) < 0) {
-		/* This is serious, but not fatal */
-		printk(KERN_ERR "Voyager: Failed to create system monitor thread!!!\n");
-		return 1;
-	}
-	return 0;
-}
+struct task_struct *voyager_thread;
+static __u8 set_timeout;
 
 static int
 execute(const char *string)
@@ -110,31 +93,15 @@
 	}
 }
 
-static void
-wakeup(unsigned long unused)
-{
-	up(&kvoyagerd_sem);
-}
-
 static int
 thread(void *unused)
 {
-	struct timer_list wakeup_timer;
-
-	kvoyagerd_running = 1;
-
-	daemonize(THREAD_NAME);
-
-	set_timeout = 0;
-
-	init_timer(&wakeup_timer);
-
-	sigfillset(&current->blocked);
-
 	printk(KERN_NOTICE "Voyager starting monitor thread\n");
 
-	for(;;) {
-		down_interruptible(&kvoyagerd_sem);
+	for (;;) {
+		set_current_state(TASK_INTERRUPTIBLE);
+		schedule_timeout(set_timeout ? HZ : MAX_SCHEDULE_TIMEOUT);
+
 		VDEBUG(("Voyager Daemon awoken\n"));
 		if(voyager_status.request_from_kernel == 0) {
 			/* probably awoken from timeout */
@@ -143,20 +110,26 @@
 			check_from_kernel();
 			voyager_status.request_from_kernel = 0;
 		}
-		if(set_timeout) {
-			del_timer(&wakeup_timer);
-			wakeup_timer.expires = HZ + jiffies;
-			wakeup_timer.function = wakeup;
-			add_timer(&wakeup_timer);
-		}
 	}
 }
 
+static int __init
+voyager_thread_start(void)
+{
+	voyager_thread = kthread_run(thread, NULL, "kvoyagerd");
+	if (IS_ERR(voyager_thread)) {
+		printk(KERN_ERR "Voyager: Failed to create system monitor thread.\n");
+		return PTR_ERR(voyager_thread);
+	}
+	return 0;
+}
+
+
 static void __exit
 voyager_thread_stop(void)
 {
-	/* FIXME: do nothing at the moment */
+	kthread_stop(voyager_thread);
 }
 
 module_init(voyager_thread_start);
-//module_exit(voyager_thread_stop);
+module_exit(voyager_thread_stop);
diff --git a/arch/i386/pci/fixup.c b/arch/i386/pci/fixup.c
index 8053b17..b62eafb 100644
--- a/arch/i386/pci/fixup.c
+++ b/arch/i386/pci/fixup.c
@@ -354,7 +354,7 @@
 		printk(KERN_DEBUG "Boot video device is %s\n", pci_name(pdev));
 	}
 }
-DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_video);
+DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_video);
 
 /*
  * Some Toshiba laptops need extra code to enable their TI TSB43AB22/A.
diff --git a/arch/i386/pci/i386.c b/arch/i386/pci/i386.c
index 43005f0..bcd2f94 100644
--- a/arch/i386/pci/i386.c
+++ b/arch/i386/pci/i386.c
@@ -246,8 +246,8 @@
 			continue;
 		if (!r->start && r->end) {
 			printk(KERN_ERR "PCI: Device %s not available "
-				"because of resource collisions\n",
-				pci_name(dev));
+				"because of resource %d collisions\n",
+				pci_name(dev), idx);
 			return -EINVAL;
 		}
 		if (r->flags & IORESOURCE_IO)
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
index e19185d..3b71f97 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
@@ -14,6 +14,7 @@
 	select PCI if (!IA64_HP_SIM)
 	select ACPI if (!IA64_HP_SIM)
 	select PM if (!IA64_HP_SIM)
+	select ARCH_SUPPORTS_MSI
 	default y
 	help
 	  The Itanium Processor Family is Intel's 64-bit successor to
diff --git a/arch/ia64/sn/kernel/huberror.c b/arch/ia64/sn/kernel/huberror.c
index fcf7f93..2c3f9df 100644
--- a/arch/ia64/sn/kernel/huberror.c
+++ b/arch/ia64/sn/kernel/huberror.c
@@ -8,7 +8,6 @@
 
 #include <linux/types.h>
 #include <linux/interrupt.h>
-#include <linux/pci.h>
 #include <asm/delay.h>
 #include <asm/sn/sn_sal.h>
 #include "ioerror.h"
diff --git a/arch/ia64/sn/kernel/msi_sn.c b/arch/ia64/sn/kernel/msi_sn.c
index 49873aa..83f190f 100644
--- a/arch/ia64/sn/kernel/msi_sn.c
+++ b/arch/ia64/sn/kernel/msi_sn.c
@@ -87,7 +87,6 @@
 	if (irq < 0)
 		return irq;
 
-	set_irq_msi(irq, entry);
 	/*
 	 * Set up the vector plumbing.  Let the prom (via sn_intr_alloc)
 	 * decide which cpu to direct this msi at by default.
@@ -144,10 +143,11 @@
 	 */
 	msg.data = 0x100 + irq;
 
+	set_irq_msi(irq, entry);
 	write_msi_msg(irq, &msg);
 	set_irq_chip_and_handler(irq, &sn_msi_chip, handle_edge_irq);
 
-	return irq;
+	return 0;
 }
 
 #ifdef CONFIG_SMP
diff --git a/arch/ia64/sn/kernel/xpnet.c b/arch/ia64/sn/kernel/xpnet.c
index 5419acb..88fad85 100644
--- a/arch/ia64/sn/kernel/xpnet.c
+++ b/arch/ia64/sn/kernel/xpnet.c
@@ -24,7 +24,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/ioport.h>
 #include <linux/netdevice.h>
diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig
index a8e1e60..b8536c7 100644
--- a/arch/m68k/Kconfig
+++ b/arch/m68k/Kconfig
@@ -409,6 +409,9 @@
 	help
 	  Say Y here to report ST-RAM usage statistics in /proc/stram.
 
+config ATARI_KBD_CORE
+	bool
+
 config HEARTBEAT
 	bool "Use power LED as a heartbeat" if AMIGA || APOLLO || ATARI || MAC ||Q40
 	default y if !AMIGA && !APOLLO && !ATARI && !MAC && !Q40 && HP300
diff --git a/arch/m68k/Makefile b/arch/m68k/Makefile
index 34d826d..c20831a 100644
--- a/arch/m68k/Makefile
+++ b/arch/m68k/Makefile
@@ -21,7 +21,7 @@
 LDFLAGS := -m m68kelf
 ifneq ($(COMPILE_ARCH),$(ARCH))
 	# prefix for cross-compiling binaries
-	CROSS_COMPILE = m68k-linux-
+	CROSS_COMPILE = m68k-linux-gnu-
 endif
 
 ifdef CONFIG_SUN3
diff --git a/arch/m68k/amiga/config.c b/arch/m68k/amiga/config.c
index 3204f41..3574853 100644
--- a/arch/m68k/amiga/config.c
+++ b/arch/m68k/amiga/config.c
@@ -22,9 +22,7 @@
 #include <linux/vt_kern.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
-#ifdef CONFIG_ZORRO
 #include <linux/zorro.h>
-#endif
 
 #include <asm/bootinfo.h>
 #include <asm/setup.h>
@@ -62,55 +60,51 @@
 static char s_cd32[] __initdata = "CD32";
 static char s_draco[] __initdata = "Draco";
 static char *amiga_models[] __initdata = {
-    [AMI_500-AMI_500]		= s_a500,
-    [AMI_500PLUS-AMI_500]	= s_a500p,
-    [AMI_600-AMI_500]		= s_a600,
-    [AMI_1000-AMI_500]		= s_a1000,
-    [AMI_1200-AMI_500]		= s_a1200,
-    [AMI_2000-AMI_500]		= s_a2000,
-    [AMI_2500-AMI_500]		= s_a2500,
-    [AMI_3000-AMI_500]		= s_a3000,
-    [AMI_3000T-AMI_500]		= s_a3000t,
-    [AMI_3000PLUS-AMI_500]	= s_a3000p,
-    [AMI_4000-AMI_500]		= s_a4000,
-    [AMI_4000T-AMI_500]		= s_a4000t,
-    [AMI_CDTV-AMI_500]		= s_cdtv,
-    [AMI_CD32-AMI_500]		= s_cd32,
-    [AMI_DRACO-AMI_500]		= s_draco,
+	[AMI_500-AMI_500]	= s_a500,
+	[AMI_500PLUS-AMI_500]	= s_a500p,
+	[AMI_600-AMI_500]	= s_a600,
+	[AMI_1000-AMI_500]	= s_a1000,
+	[AMI_1200-AMI_500]	= s_a1200,
+	[AMI_2000-AMI_500]	= s_a2000,
+	[AMI_2500-AMI_500]	= s_a2500,
+	[AMI_3000-AMI_500]	= s_a3000,
+	[AMI_3000T-AMI_500]	= s_a3000t,
+	[AMI_3000PLUS-AMI_500]	= s_a3000p,
+	[AMI_4000-AMI_500]	= s_a4000,
+	[AMI_4000T-AMI_500]	= s_a4000t,
+	[AMI_CDTV-AMI_500]	= s_cdtv,
+	[AMI_CD32-AMI_500]	= s_cd32,
+	[AMI_DRACO-AMI_500]	= s_draco,
 };
 
 static char amiga_model_name[13] = "Amiga ";
 
-extern char m68k_debug_device[];
-
 static void amiga_sched_init(irq_handler_t handler);
 /* amiga specific irq functions */
-extern void amiga_init_IRQ (void);
+extern void amiga_init_IRQ(void);
 static void amiga_get_model(char *model);
 static int amiga_get_hardware_list(char *buffer);
 /* amiga specific timer functions */
-static unsigned long amiga_gettimeoffset (void);
-static int a3000_hwclk (int, struct rtc_time *);
-static int a2000_hwclk (int, struct rtc_time *);
-static int amiga_set_clock_mmss (unsigned long);
-static unsigned int amiga_get_ss (void);
-extern void amiga_mksound( unsigned int count, unsigned int ticks );
-static void amiga_reset (void);
+static unsigned long amiga_gettimeoffset(void);
+static int a3000_hwclk(int, struct rtc_time *);
+static int a2000_hwclk(int, struct rtc_time *);
+static int amiga_set_clock_mmss(unsigned long);
+static unsigned int amiga_get_ss(void);
+extern void amiga_mksound(unsigned int count, unsigned int ticks);
+static void amiga_reset(void);
 extern void amiga_init_sound(void);
-static void amiga_savekmsg_init(void);
 static void amiga_mem_console_write(struct console *co, const char *b,
 				    unsigned int count);
 void amiga_serial_console_write(struct console *co, const char *s,
 				unsigned int count);
-static void amiga_debug_init(void);
 #ifdef CONFIG_HEARTBEAT
 static void amiga_heartbeat(int on);
 #endif
 
 static struct console amiga_console_driver = {
-	.name =		"debug",
-	.flags =	CON_PRINTBUFFER,
-	.index =	-1,
+	.name	= "debug",
+	.flags	= CON_PRINTBUFFER,
+	.index	= -1,
 };
 
 
@@ -119,24 +113,24 @@
      */
 
 static struct {
-    struct resource _ciab, _ciaa, _custom, _kickstart;
+	struct resource _ciab, _ciaa, _custom, _kickstart;
 } mb_resources = {
-    ._ciab = {
-	.name = "CIA B", .start = 0x00bfd000, .end = 0x00bfdfff
-    },
-    ._ciaa = {
-	.name = "CIA A", .start = 0x00bfe000, .end = 0x00bfefff
-    },
-    ._custom = {
-	.name = "Custom I/O", .start = 0x00dff000, .end = 0x00dfffff
-    },
-    ._kickstart = {
-	.name = "Kickstart ROM", .start = 0x00f80000, .end = 0x00ffffff
-    }
+	._ciab = {
+		.name = "CIA B", .start = 0x00bfd000, .end = 0x00bfdfff
+	},
+	._ciaa = {
+		.name = "CIA A", .start = 0x00bfe000, .end = 0x00bfefff
+	},
+	._custom = {
+		.name = "Custom I/O", .start = 0x00dff000, .end = 0x00dfffff
+	},
+	._kickstart = {
+		.name = "Kickstart ROM", .start = 0x00f80000, .end = 0x00ffffff
+	}
 };
 
 static struct resource rtc_resource = {
-    .start = 0x00dc0000, .end = 0x00dcffff
+	.start = 0x00dc0000, .end = 0x00dcffff
 };
 
 static struct resource ram_resource[NUM_MEMINFO];
@@ -148,57 +142,57 @@
 
 int amiga_parse_bootinfo(const struct bi_record *record)
 {
-    int unknown = 0;
-    const unsigned long *data = record->data;
+	int unknown = 0;
+	const unsigned long *data = record->data;
 
-    switch (record->tag) {
+	switch (record->tag) {
 	case BI_AMIGA_MODEL:
-	    amiga_model = *data;
-	    break;
+		amiga_model = *data;
+		break;
 
 	case BI_AMIGA_ECLOCK:
-	    amiga_eclock = *data;
-	    break;
+		amiga_eclock = *data;
+		break;
 
 	case BI_AMIGA_CHIPSET:
-	    amiga_chipset = *data;
-	    break;
+		amiga_chipset = *data;
+		break;
 
 	case BI_AMIGA_CHIP_SIZE:
-	    amiga_chip_size = *(const int *)data;
-	    break;
+		amiga_chip_size = *(const int *)data;
+		break;
 
 	case BI_AMIGA_VBLANK:
-	    amiga_vblank = *(const unsigned char *)data;
-	    break;
+		amiga_vblank = *(const unsigned char *)data;
+		break;
 
 	case BI_AMIGA_PSFREQ:
-	    amiga_psfreq = *(const unsigned char *)data;
-	    break;
+		amiga_psfreq = *(const unsigned char *)data;
+		break;
 
 	case BI_AMIGA_AUTOCON:
 #ifdef CONFIG_ZORRO
-	    if (zorro_num_autocon < ZORRO_NUM_AUTO) {
-		const struct ConfigDev *cd = (struct ConfigDev *)data;
-		struct zorro_dev *dev = &zorro_autocon[zorro_num_autocon++];
-		dev->rom = cd->cd_Rom;
-		dev->slotaddr = cd->cd_SlotAddr;
-		dev->slotsize = cd->cd_SlotSize;
-		dev->resource.start = (unsigned long)cd->cd_BoardAddr;
-		dev->resource.end = dev->resource.start+cd->cd_BoardSize-1;
-	    } else
-		printk("amiga_parse_bootinfo: too many AutoConfig devices\n");
+		if (zorro_num_autocon < ZORRO_NUM_AUTO) {
+			const struct ConfigDev *cd = (struct ConfigDev *)data;
+			struct zorro_dev *dev = &zorro_autocon[zorro_num_autocon++];
+			dev->rom = cd->cd_Rom;
+			dev->slotaddr = cd->cd_SlotAddr;
+			dev->slotsize = cd->cd_SlotSize;
+			dev->resource.start = (unsigned long)cd->cd_BoardAddr;
+			dev->resource.end = dev->resource.start + cd->cd_BoardSize - 1;
+		} else
+			printk("amiga_parse_bootinfo: too many AutoConfig devices\n");
 #endif /* CONFIG_ZORRO */
-	    break;
+		break;
 
 	case BI_AMIGA_SERPER:
-	    /* serial port period: ignored here */
-	    break;
+		/* serial port period: ignored here */
+		break;
 
 	default:
-	    unknown = 1;
-    }
-    return(unknown);
+		unknown = 1;
+	}
+	return unknown;
 }
 
     /*
@@ -207,159 +201,159 @@
 
 static void __init amiga_identify(void)
 {
-  /* Fill in some default values, if necessary */
-  if (amiga_eclock == 0)
-    amiga_eclock = 709379;
+	/* Fill in some default values, if necessary */
+	if (amiga_eclock == 0)
+		amiga_eclock = 709379;
 
-  memset(&amiga_hw_present, 0, sizeof(amiga_hw_present));
+	memset(&amiga_hw_present, 0, sizeof(amiga_hw_present));
 
-  printk("Amiga hardware found: ");
-  if (amiga_model >= AMI_500 && amiga_model <= AMI_DRACO) {
-    printk("[%s] ", amiga_models[amiga_model-AMI_500]);
-    strcat(amiga_model_name, amiga_models[amiga_model-AMI_500]);
-  }
+	printk("Amiga hardware found: ");
+	if (amiga_model >= AMI_500 && amiga_model <= AMI_DRACO) {
+		printk("[%s] ", amiga_models[amiga_model-AMI_500]);
+		strcat(amiga_model_name, amiga_models[amiga_model-AMI_500]);
+	}
 
-  switch(amiga_model) {
-  case AMI_UNKNOWN:
-    goto Generic;
+	switch (amiga_model) {
+	case AMI_UNKNOWN:
+		goto Generic;
 
-  case AMI_600:
-  case AMI_1200:
-    AMIGAHW_SET(A1200_IDE);
-    AMIGAHW_SET(PCMCIA);
-  case AMI_500:
-  case AMI_500PLUS:
-  case AMI_1000:
-  case AMI_2000:
-  case AMI_2500:
-    AMIGAHW_SET(A2000_CLK);	/* Is this correct for all models? */
-    goto Generic;
+	case AMI_600:
+	case AMI_1200:
+		AMIGAHW_SET(A1200_IDE);
+		AMIGAHW_SET(PCMCIA);
+	case AMI_500:
+	case AMI_500PLUS:
+	case AMI_1000:
+	case AMI_2000:
+	case AMI_2500:
+		AMIGAHW_SET(A2000_CLK);	/* Is this correct for all models? */
+		goto Generic;
 
-  case AMI_3000:
-  case AMI_3000T:
-    AMIGAHW_SET(AMBER_FF);
-    AMIGAHW_SET(MAGIC_REKICK);
-    /* fall through */
-  case AMI_3000PLUS:
-    AMIGAHW_SET(A3000_SCSI);
-    AMIGAHW_SET(A3000_CLK);
-    AMIGAHW_SET(ZORRO3);
-    goto Generic;
+	case AMI_3000:
+	case AMI_3000T:
+		AMIGAHW_SET(AMBER_FF);
+		AMIGAHW_SET(MAGIC_REKICK);
+		/* fall through */
+	case AMI_3000PLUS:
+		AMIGAHW_SET(A3000_SCSI);
+		AMIGAHW_SET(A3000_CLK);
+		AMIGAHW_SET(ZORRO3);
+		goto Generic;
 
-  case AMI_4000T:
-    AMIGAHW_SET(A4000_SCSI);
-    /* fall through */
-  case AMI_4000:
-    AMIGAHW_SET(A4000_IDE);
-    AMIGAHW_SET(A3000_CLK);
-    AMIGAHW_SET(ZORRO3);
-    goto Generic;
+	case AMI_4000T:
+		AMIGAHW_SET(A4000_SCSI);
+		/* fall through */
+	case AMI_4000:
+		AMIGAHW_SET(A4000_IDE);
+		AMIGAHW_SET(A3000_CLK);
+		AMIGAHW_SET(ZORRO3);
+		goto Generic;
 
-  case AMI_CDTV:
-  case AMI_CD32:
-    AMIGAHW_SET(CD_ROM);
-    AMIGAHW_SET(A2000_CLK);             /* Is this correct? */
-    goto Generic;
+	case AMI_CDTV:
+	case AMI_CD32:
+		AMIGAHW_SET(CD_ROM);
+		AMIGAHW_SET(A2000_CLK);             /* Is this correct? */
+		goto Generic;
 
-  Generic:
-    AMIGAHW_SET(AMI_VIDEO);
-    AMIGAHW_SET(AMI_BLITTER);
-    AMIGAHW_SET(AMI_AUDIO);
-    AMIGAHW_SET(AMI_FLOPPY);
-    AMIGAHW_SET(AMI_KEYBOARD);
-    AMIGAHW_SET(AMI_MOUSE);
-    AMIGAHW_SET(AMI_SERIAL);
-    AMIGAHW_SET(AMI_PARALLEL);
-    AMIGAHW_SET(CHIP_RAM);
-    AMIGAHW_SET(PAULA);
+	Generic:
+		AMIGAHW_SET(AMI_VIDEO);
+		AMIGAHW_SET(AMI_BLITTER);
+		AMIGAHW_SET(AMI_AUDIO);
+		AMIGAHW_SET(AMI_FLOPPY);
+		AMIGAHW_SET(AMI_KEYBOARD);
+		AMIGAHW_SET(AMI_MOUSE);
+		AMIGAHW_SET(AMI_SERIAL);
+		AMIGAHW_SET(AMI_PARALLEL);
+		AMIGAHW_SET(CHIP_RAM);
+		AMIGAHW_SET(PAULA);
 
-    switch(amiga_chipset) {
-    case CS_OCS:
-    case CS_ECS:
-    case CS_AGA:
-      switch (amiga_custom.deniseid & 0xf) {
-      case 0x0c:
-	AMIGAHW_SET(DENISE_HR);
-	break;
-      case 0x08:
-	AMIGAHW_SET(LISA);
-	break;
-      }
-      break;
-    default:
-      AMIGAHW_SET(DENISE);
-      break;
-    }
-    switch ((amiga_custom.vposr>>8) & 0x7f) {
-    case 0x00:
-      AMIGAHW_SET(AGNUS_PAL);
-      break;
-    case 0x10:
-      AMIGAHW_SET(AGNUS_NTSC);
-      break;
-    case 0x20:
-    case 0x21:
-      AMIGAHW_SET(AGNUS_HR_PAL);
-      break;
-    case 0x30:
-    case 0x31:
-      AMIGAHW_SET(AGNUS_HR_NTSC);
-      break;
-    case 0x22:
-    case 0x23:
-      AMIGAHW_SET(ALICE_PAL);
-      break;
-    case 0x32:
-    case 0x33:
-      AMIGAHW_SET(ALICE_NTSC);
-      break;
-    }
-    AMIGAHW_SET(ZORRO);
-    break;
+		switch (amiga_chipset) {
+		case CS_OCS:
+		case CS_ECS:
+		case CS_AGA:
+			switch (amiga_custom.deniseid & 0xf) {
+			case 0x0c:
+				AMIGAHW_SET(DENISE_HR);
+				break;
+			case 0x08:
+				AMIGAHW_SET(LISA);
+				break;
+			}
+			break;
+		default:
+			AMIGAHW_SET(DENISE);
+			break;
+		}
+		switch ((amiga_custom.vposr>>8) & 0x7f) {
+		case 0x00:
+			AMIGAHW_SET(AGNUS_PAL);
+			break;
+		case 0x10:
+			AMIGAHW_SET(AGNUS_NTSC);
+			break;
+		case 0x20:
+		case 0x21:
+			AMIGAHW_SET(AGNUS_HR_PAL);
+			break;
+		case 0x30:
+		case 0x31:
+			AMIGAHW_SET(AGNUS_HR_NTSC);
+			break;
+		case 0x22:
+		case 0x23:
+			AMIGAHW_SET(ALICE_PAL);
+			break;
+		case 0x32:
+		case 0x33:
+			AMIGAHW_SET(ALICE_NTSC);
+			break;
+		}
+		AMIGAHW_SET(ZORRO);
+		break;
 
-  case AMI_DRACO:
-    panic("No support for Draco yet");
+	case AMI_DRACO:
+		panic("No support for Draco yet");
 
-  default:
-    panic("Unknown Amiga Model");
-  }
+	default:
+		panic("Unknown Amiga Model");
+	}
 
-#define AMIGAHW_ANNOUNCE(name, str)			\
-  if (AMIGAHW_PRESENT(name))				\
-    printk(str)
+#define AMIGAHW_ANNOUNCE(name, str)		\
+	if (AMIGAHW_PRESENT(name))		\
+		printk(str)
 
-  AMIGAHW_ANNOUNCE(AMI_VIDEO, "VIDEO ");
-  AMIGAHW_ANNOUNCE(AMI_BLITTER, "BLITTER ");
-  AMIGAHW_ANNOUNCE(AMBER_FF, "AMBER_FF ");
-  AMIGAHW_ANNOUNCE(AMI_AUDIO, "AUDIO ");
-  AMIGAHW_ANNOUNCE(AMI_FLOPPY, "FLOPPY ");
-  AMIGAHW_ANNOUNCE(A3000_SCSI, "A3000_SCSI ");
-  AMIGAHW_ANNOUNCE(A4000_SCSI, "A4000_SCSI ");
-  AMIGAHW_ANNOUNCE(A1200_IDE, "A1200_IDE ");
-  AMIGAHW_ANNOUNCE(A4000_IDE, "A4000_IDE ");
-  AMIGAHW_ANNOUNCE(CD_ROM, "CD_ROM ");
-  AMIGAHW_ANNOUNCE(AMI_KEYBOARD, "KEYBOARD ");
-  AMIGAHW_ANNOUNCE(AMI_MOUSE, "MOUSE ");
-  AMIGAHW_ANNOUNCE(AMI_SERIAL, "SERIAL ");
-  AMIGAHW_ANNOUNCE(AMI_PARALLEL, "PARALLEL ");
-  AMIGAHW_ANNOUNCE(A2000_CLK, "A2000_CLK ");
-  AMIGAHW_ANNOUNCE(A3000_CLK, "A3000_CLK ");
-  AMIGAHW_ANNOUNCE(CHIP_RAM, "CHIP_RAM ");
-  AMIGAHW_ANNOUNCE(PAULA, "PAULA ");
-  AMIGAHW_ANNOUNCE(DENISE, "DENISE ");
-  AMIGAHW_ANNOUNCE(DENISE_HR, "DENISE_HR ");
-  AMIGAHW_ANNOUNCE(LISA, "LISA ");
-  AMIGAHW_ANNOUNCE(AGNUS_PAL, "AGNUS_PAL ");
-  AMIGAHW_ANNOUNCE(AGNUS_NTSC, "AGNUS_NTSC ");
-  AMIGAHW_ANNOUNCE(AGNUS_HR_PAL, "AGNUS_HR_PAL ");
-  AMIGAHW_ANNOUNCE(AGNUS_HR_NTSC, "AGNUS_HR_NTSC ");
-  AMIGAHW_ANNOUNCE(ALICE_PAL, "ALICE_PAL ");
-  AMIGAHW_ANNOUNCE(ALICE_NTSC, "ALICE_NTSC ");
-  AMIGAHW_ANNOUNCE(MAGIC_REKICK, "MAGIC_REKICK ");
-  AMIGAHW_ANNOUNCE(PCMCIA, "PCMCIA ");
-  if (AMIGAHW_PRESENT(ZORRO))
-    printk("ZORRO%s ", AMIGAHW_PRESENT(ZORRO3) ? "3" : "");
-  printk("\n");
+	AMIGAHW_ANNOUNCE(AMI_VIDEO, "VIDEO ");
+	AMIGAHW_ANNOUNCE(AMI_BLITTER, "BLITTER ");
+	AMIGAHW_ANNOUNCE(AMBER_FF, "AMBER_FF ");
+	AMIGAHW_ANNOUNCE(AMI_AUDIO, "AUDIO ");
+	AMIGAHW_ANNOUNCE(AMI_FLOPPY, "FLOPPY ");
+	AMIGAHW_ANNOUNCE(A3000_SCSI, "A3000_SCSI ");
+	AMIGAHW_ANNOUNCE(A4000_SCSI, "A4000_SCSI ");
+	AMIGAHW_ANNOUNCE(A1200_IDE, "A1200_IDE ");
+	AMIGAHW_ANNOUNCE(A4000_IDE, "A4000_IDE ");
+	AMIGAHW_ANNOUNCE(CD_ROM, "CD_ROM ");
+	AMIGAHW_ANNOUNCE(AMI_KEYBOARD, "KEYBOARD ");
+	AMIGAHW_ANNOUNCE(AMI_MOUSE, "MOUSE ");
+	AMIGAHW_ANNOUNCE(AMI_SERIAL, "SERIAL ");
+	AMIGAHW_ANNOUNCE(AMI_PARALLEL, "PARALLEL ");
+	AMIGAHW_ANNOUNCE(A2000_CLK, "A2000_CLK ");
+	AMIGAHW_ANNOUNCE(A3000_CLK, "A3000_CLK ");
+	AMIGAHW_ANNOUNCE(CHIP_RAM, "CHIP_RAM ");
+	AMIGAHW_ANNOUNCE(PAULA, "PAULA ");
+	AMIGAHW_ANNOUNCE(DENISE, "DENISE ");
+	AMIGAHW_ANNOUNCE(DENISE_HR, "DENISE_HR ");
+	AMIGAHW_ANNOUNCE(LISA, "LISA ");
+	AMIGAHW_ANNOUNCE(AGNUS_PAL, "AGNUS_PAL ");
+	AMIGAHW_ANNOUNCE(AGNUS_NTSC, "AGNUS_NTSC ");
+	AMIGAHW_ANNOUNCE(AGNUS_HR_PAL, "AGNUS_HR_PAL ");
+	AMIGAHW_ANNOUNCE(AGNUS_HR_NTSC, "AGNUS_HR_NTSC ");
+	AMIGAHW_ANNOUNCE(ALICE_PAL, "ALICE_PAL ");
+	AMIGAHW_ANNOUNCE(ALICE_NTSC, "ALICE_NTSC ");
+	AMIGAHW_ANNOUNCE(MAGIC_REKICK, "MAGIC_REKICK ");
+	AMIGAHW_ANNOUNCE(PCMCIA, "PCMCIA ");
+	if (AMIGAHW_PRESENT(ZORRO))
+		printk("ZORRO%s ", AMIGAHW_PRESENT(ZORRO3) ? "3" : "");
+	printk("\n");
 
 #undef AMIGAHW_ANNOUNCE
 }
@@ -370,119 +364,105 @@
 
 void __init config_amiga(void)
 {
-  int i;
+	int i;
 
-  amiga_debug_init();
-  amiga_identify();
+	amiga_identify();
 
-  /* Yuk, we don't have PCI memory */
-  iomem_resource.name = "Memory";
-  for (i = 0; i < 4; i++)
-    request_resource(&iomem_resource, &((struct resource *)&mb_resources)[i]);
+	/* Yuk, we don't have PCI memory */
+	iomem_resource.name = "Memory";
+	for (i = 0; i < 4; i++)
+		request_resource(&iomem_resource, &((struct resource *)&mb_resources)[i]);
 
-  mach_sched_init      = amiga_sched_init;
-  mach_init_IRQ        = amiga_init_IRQ;
-  mach_get_model       = amiga_get_model;
-  mach_get_hardware_list = amiga_get_hardware_list;
-  mach_gettimeoffset   = amiga_gettimeoffset;
-  if (AMIGAHW_PRESENT(A3000_CLK)){
-    mach_hwclk         = a3000_hwclk;
-    rtc_resource.name = "A3000 RTC";
-    request_resource(&iomem_resource, &rtc_resource);
-  }
-  else{ /* if (AMIGAHW_PRESENT(A2000_CLK)) */
-    mach_hwclk         = a2000_hwclk;
-    rtc_resource.name = "A2000 RTC";
-    request_resource(&iomem_resource, &rtc_resource);
-  }
+	mach_sched_init      = amiga_sched_init;
+	mach_init_IRQ        = amiga_init_IRQ;
+	mach_get_model       = amiga_get_model;
+	mach_get_hardware_list = amiga_get_hardware_list;
+	mach_gettimeoffset   = amiga_gettimeoffset;
+	if (AMIGAHW_PRESENT(A3000_CLK)) {
+		mach_hwclk         = a3000_hwclk;
+		rtc_resource.name = "A3000 RTC";
+		request_resource(&iomem_resource, &rtc_resource);
+	} else /* if (AMIGAHW_PRESENT(A2000_CLK)) */ {
+		mach_hwclk         = a2000_hwclk;
+		rtc_resource.name = "A2000 RTC";
+		request_resource(&iomem_resource, &rtc_resource);
+	}
 
-  mach_max_dma_address = 0xffffffff; /*
-				      * default MAX_DMA=0xffffffff
-				      * on all machines. If we don't
-				      * do so, the SCSI code will not
-				      * be able to allocate any mem
-				      * for transfers, unless we are
-				      * dealing with a Z2 mem only
-				      * system.                  /Jes
-				      */
+	/*
+	 * default MAX_DMA=0xffffffff on all machines. If we don't do so, the SCSI
+	 * code will not be able to allocate any mem for transfers, unless we are
+	 * dealing with a Z2 mem only system.                  /Jes
+	 */
+	mach_max_dma_address = 0xffffffff;
 
-  mach_set_clock_mmss  = amiga_set_clock_mmss;
-  mach_get_ss          = amiga_get_ss;
-  mach_reset           = amiga_reset;
+	mach_set_clock_mmss  = amiga_set_clock_mmss;
+	mach_get_ss          = amiga_get_ss;
+	mach_reset           = amiga_reset;
 #if defined(CONFIG_INPUT_M68K_BEEP) || defined(CONFIG_INPUT_M68K_BEEP_MODULE)
-  mach_beep            = amiga_mksound;
+	mach_beep            = amiga_mksound;
 #endif
 
 #ifdef CONFIG_HEARTBEAT
-  mach_heartbeat = amiga_heartbeat;
+	mach_heartbeat = amiga_heartbeat;
 #endif
 
-  /* Fill in the clock values (based on the 700 kHz E-Clock) */
-  amiga_masterclock = 40*amiga_eclock;	/* 28 MHz */
-  amiga_colorclock = 5*amiga_eclock;	/* 3.5 MHz */
+	/* Fill in the clock values (based on the 700 kHz E-Clock) */
+	amiga_masterclock = 40*amiga_eclock;	/* 28 MHz */
+	amiga_colorclock = 5*amiga_eclock;	/* 3.5 MHz */
 
-  /* clear all DMA bits */
-  amiga_custom.dmacon = DMAF_ALL;
-  /* ensure that the DMA master bit is set */
-  amiga_custom.dmacon = DMAF_SETCLR | DMAF_MASTER;
+	/* clear all DMA bits */
+	amiga_custom.dmacon = DMAF_ALL;
+	/* ensure that the DMA master bit is set */
+	amiga_custom.dmacon = DMAF_SETCLR | DMAF_MASTER;
 
-  /* don't use Z2 RAM as system memory on Z3 capable machines */
-  if (AMIGAHW_PRESENT(ZORRO3)) {
-    int i, j;
-    u32 disabled_z2mem = 0;
-    for (i = 0; i < m68k_num_memory; i++)
-      if (m68k_memory[i].addr < 16*1024*1024) {
-	if (i == 0) {
-	  /* don't cut off the branch we're sitting on */
-	  printk("Warning: kernel runs in Zorro II memory\n");
-	  continue;
+	/* don't use Z2 RAM as system memory on Z3 capable machines */
+	if (AMIGAHW_PRESENT(ZORRO3)) {
+		int i, j;
+		u32 disabled_z2mem = 0;
+
+		for (i = 0; i < m68k_num_memory; i++) {
+			if (m68k_memory[i].addr < 16*1024*1024) {
+				if (i == 0) {
+					/* don't cut off the branch we're sitting on */
+					printk("Warning: kernel runs in Zorro II memory\n");
+					continue;
+				}
+				disabled_z2mem += m68k_memory[i].size;
+				m68k_num_memory--;
+				for (j = i; j < m68k_num_memory; j++)
+					m68k_memory[j] = m68k_memory[j+1];
+				i--;
+			}
+		}
+		if (disabled_z2mem)
+		printk("%dK of Zorro II memory will not be used as system memory\n",
+		disabled_z2mem>>10);
 	}
-	disabled_z2mem += m68k_memory[i].size;
-	m68k_num_memory--;
-	for (j = i; j < m68k_num_memory; j++)
-	  m68k_memory[j] = m68k_memory[j+1];
-	i--;
-      }
-    if (disabled_z2mem)
-      printk("%dK of Zorro II memory will not be used as system memory\n",
-	     disabled_z2mem>>10);
-  }
 
-  /* request all RAM */
-  for (i = 0; i < m68k_num_memory; i++) {
-    ram_resource[i].name =
-      (m68k_memory[i].addr >= 0x01000000) ? "32-bit Fast RAM" :
-      (m68k_memory[i].addr < 0x00c00000) ? "16-bit Fast RAM" :
-      "16-bit Slow RAM";
-    ram_resource[i].start = m68k_memory[i].addr;
-    ram_resource[i].end = m68k_memory[i].addr+m68k_memory[i].size-1;
-    request_resource(&iomem_resource, &ram_resource[i]);
-  }
+	/* request all RAM */
+	for (i = 0; i < m68k_num_memory; i++) {
+		ram_resource[i].name =
+			(m68k_memory[i].addr >= 0x01000000) ? "32-bit Fast RAM" :
+			(m68k_memory[i].addr < 0x00c00000) ? "16-bit Fast RAM" :
+			"16-bit Slow RAM";
+		ram_resource[i].start = m68k_memory[i].addr;
+		ram_resource[i].end = m68k_memory[i].addr+m68k_memory[i].size-1;
+		request_resource(&iomem_resource, &ram_resource[i]);
+	}
 
-  /* initialize chipram allocator */
-  amiga_chip_init ();
+	/* initialize chipram allocator */
+	amiga_chip_init();
 
-  /* debugging using chipram */
-  if (!strcmp( m68k_debug_device, "mem" )){
-	  if (!AMIGAHW_PRESENT(CHIP_RAM))
-		  printk("Warning: no chipram present for debugging\n");
-	  else {
-		  amiga_savekmsg_init();
-		  amiga_console_driver.write = amiga_mem_console_write;
-		  register_console(&amiga_console_driver);
-	  }
-  }
+	/* our beloved beeper */
+	if (AMIGAHW_PRESENT(AMI_AUDIO))
+		amiga_init_sound();
 
-  /* our beloved beeper */
-  if (AMIGAHW_PRESENT(AMI_AUDIO))
-	  amiga_init_sound();
-
-  /*
-   * if it is an A3000, set the magic bit that forces
-   * a hard rekick
-   */
-  if (AMIGAHW_PRESENT(MAGIC_REKICK))
-	  *(unsigned char *)ZTWO_VADDR(0xde0002) |= 0x80;
+	/*
+	 * if it is an A3000, set the magic bit that forces
+	 * a hard rekick
+	 */
+	if (AMIGAHW_PRESENT(MAGIC_REKICK))
+		*(unsigned char *)ZTWO_VADDR(0xde0002) |= 0x80;
 }
 
 static unsigned short jiffy_ticks;
@@ -490,12 +470,12 @@
 static void __init amiga_sched_init(irq_handler_t timer_routine)
 {
 	static struct resource sched_res = {
-	    .name = "timer", .start = 0x00bfd400, .end = 0x00bfd5ff,
+		.name = "timer", .start = 0x00bfd400, .end = 0x00bfd5ff,
 	};
 	jiffy_ticks = (amiga_eclock+HZ/2)/HZ;
 
 	if (request_resource(&mb_resources._ciab, &sched_res))
-	    printk("Cannot allocate ciab.ta{lo,hi}\n");
+		printk("Cannot allocate ciab.ta{lo,hi}\n");
 	ciab.cra &= 0xC0;   /* turn off timer A, continuous mode, from Eclk */
 	ciab.talo = jiffy_ticks % 256;
 	ciab.tahi = jiffy_ticks / 256;
@@ -513,7 +493,7 @@
 #define TICK_SIZE 10000
 
 /* This is always executed with interrupts disabled.  */
-static unsigned long amiga_gettimeoffset (void)
+static unsigned long amiga_gettimeoffset(void)
 {
 	unsigned short hi, lo, hi2;
 	unsigned long ticks, offset = 0;
@@ -585,15 +565,15 @@
 
 	tod_2000.cntrl1 = TOD2000_CNTRL1_HOLD;
 
-	while ((tod_2000.cntrl1 & TOD2000_CNTRL1_BUSY) && cnt--)
-	{
-	        tod_2000.cntrl1 &= ~TOD2000_CNTRL1_HOLD;
-	        udelay(70);
-	        tod_2000.cntrl1 |= TOD2000_CNTRL1_HOLD;
+	while ((tod_2000.cntrl1 & TOD2000_CNTRL1_BUSY) && cnt--) {
+		tod_2000.cntrl1 &= ~TOD2000_CNTRL1_HOLD;
+		udelay(70);
+		tod_2000.cntrl1 |= TOD2000_CNTRL1_HOLD;
 	}
 
 	if (!cnt)
-		printk(KERN_INFO "hwclk: timed out waiting for RTC (0x%x)\n", tod_2000.cntrl1);
+		printk(KERN_INFO "hwclk: timed out waiting for RTC (0x%x)\n",
+			tod_2000.cntrl1);
 
 	if (!op) { /* read */
 		t->tm_sec  = tod_2000.second1     * 10 + tod_2000.second2;
@@ -606,7 +586,7 @@
 		if (t->tm_year <= 69)
 			t->tm_year += 100;
 
-		if (!(tod_2000.cntrl3 & TOD2000_CNTRL3_24HMODE)){
+		if (!(tod_2000.cntrl3 & TOD2000_CNTRL3_24HMODE)) {
 			if (!(tod_2000.hour1 & TOD2000_HOUR1_PM) && t->tm_hour == 12)
 				t->tm_hour = 0;
 			else if ((tod_2000.hour1 & TOD2000_HOUR1_PM) && t->tm_hour != 12)
@@ -642,7 +622,7 @@
 	return 0;
 }
 
-static int amiga_set_clock_mmss (unsigned long nowtime)
+static int amiga_set_clock_mmss(unsigned long nowtime)
 {
 	short real_seconds = nowtime % 60, real_minutes = (nowtime / 60) % 60;
 
@@ -660,8 +640,7 @@
 
 		tod_2000.cntrl1 |= TOD2000_CNTRL1_HOLD;
 
-		while ((tod_2000.cntrl1 & TOD2000_CNTRL1_BUSY) && cnt--)
-		{
+		while ((tod_2000.cntrl1 & TOD2000_CNTRL1_BUSY) && cnt--) {
 			tod_2000.cntrl1 &= ~TOD2000_CNTRL1_HOLD;
 			udelay(70);
 			tod_2000.cntrl1 |= TOD2000_CNTRL1_HOLD;
@@ -681,7 +660,7 @@
 	return 0;
 }
 
-static unsigned int amiga_get_ss( void )
+static unsigned int amiga_get_ss(void)
 {
 	unsigned int s;
 
@@ -695,71 +674,72 @@
 	return s;
 }
 
-static NORET_TYPE void amiga_reset( void )
+static NORET_TYPE void amiga_reset(void)
     ATTRIB_NORET;
 
-static void amiga_reset (void)
+static void amiga_reset(void)
 {
-  unsigned long jmp_addr040 = virt_to_phys(&&jmp_addr_label040);
-  unsigned long jmp_addr = virt_to_phys(&&jmp_addr_label);
+	unsigned long jmp_addr040 = virt_to_phys(&&jmp_addr_label040);
+	unsigned long jmp_addr = virt_to_phys(&&jmp_addr_label);
 
-  local_irq_disable();
-  if (CPU_IS_040_OR_060)
-    /* Setup transparent translation registers for mapping
-     * of 16 MB kernel segment before disabling translation
-     */
-    __asm__ __volatile__
-      ("movel    %0,%/d0\n\t"
-       "andl     #0xff000000,%/d0\n\t"
-       "orw      #0xe020,%/d0\n\t"   /* map 16 MB, enable, cacheable */
-       ".chip    68040\n\t"
-       "movec    %%d0,%%itt0\n\t"
-       "movec    %%d0,%%dtt0\n\t"
-       ".chip    68k\n\t"
-       "jmp      %0@\n\t"
-       : /* no outputs */
-       : "a" (jmp_addr040));
-  else
-    /* for 680[23]0, just disable translation and jump to the physical
-     * address of the label
-     */
-    __asm__ __volatile__
-      ("pmove  %/tc,%@\n\t"
-       "bclr   #7,%@\n\t"
-       "pmove  %@,%/tc\n\t"
-       "jmp    %0@\n\t"
-       : /* no outputs */
-       : "a" (jmp_addr));
- jmp_addr_label040:
-  /* disable translation on '040 now */
-  __asm__ __volatile__
-    ("moveq #0,%/d0\n\t"
-     ".chip 68040\n\t"
-     "movec %%d0,%%tc\n\t"	/* disable MMU */
-     ".chip 68k\n\t"
-     : /* no outputs */
-     : /* no inputs */
-     : "d0");
+	local_irq_disable();
+	if (CPU_IS_040_OR_060)
+		/* Setup transparent translation registers for mapping
+		 * of 16 MB kernel segment before disabling translation
+		 */
+		asm volatile ("\n"
+			"	move.l	%0,%%d0\n"
+			"	and.l	#0xff000000,%%d0\n"
+			"	or.w	#0xe020,%%d0\n"   /* map 16 MB, enable, cacheable */
+			"	.chip	68040\n"
+			"	movec	%%d0,%%itt0\n"
+			"	movec	%%d0,%%dtt0\n"
+			"	.chip	68k\n"
+			"	jmp	%0@\n"
+			: /* no outputs */
+			: "a" (jmp_addr040)
+			: "d0");
+	else
+		/* for 680[23]0, just disable translation and jump to the physical
+		 * address of the label
+		 */
+		asm volatile ("\n"
+			"	pmove	%%tc,%@\n"
+			"	bclr	#7,%@\n"
+			"	pmove	%@,%%tc\n"
+			"	jmp	%0@\n"
+			: /* no outputs */
+			: "a" (jmp_addr));
+jmp_addr_label040:
+	/* disable translation on '040 now */
+	asm volatile ("\n"
+		"	moveq	#0,%%d0\n"
+		"	.chip	68040\n"
+		"	movec	%%d0,%%tc\n"	/* disable MMU */
+		"	.chip	68k\n"
+		: /* no outputs */
+		: /* no inputs */
+		: "d0");
 
- jmp_addr_label:
-  /* pickup reset address from AmigaOS ROM, reset devices and jump
-   * to reset address
-   */
-  __asm__ __volatile__
-    ("movew #0x2700,%/sr\n\t"
-     "leal  0x01000000,%/a0\n\t"
-     "subl  %/a0@(-0x14),%/a0\n\t"
-     "movel %/a0@(4),%/a0\n\t"
-     "subql #2,%/a0\n\t"
-     "bra   1f\n\t"
-     /* align on a longword boundary */
-     __ALIGN_STR "\n"
-     "1:\n\t"
-     "reset\n\t"
-     "jmp   %/a0@" : /* Just that gcc scans it for % escapes */ );
+	jmp_addr_label:
+	/* pickup reset address from AmigaOS ROM, reset devices and jump
+	 * to reset address
+	 */
+	asm volatile ("\n"
+		"	move.w	#0x2700,%sr\n"
+		"	lea	0x01000000,%a0\n"
+		"	sub.l	%a0@(-0x14),%a0\n"
+		"	move.l	%a0@(4),%a0\n"
+		"	subq.l	#2,%a0\n"
+		"	jra	1f\n"
+		/* align on a longword boundary */
+		"	" __ALIGN_STR "\n"
+		"1:\n"
+		"	reset\n"
+		"	jmp   %a0@");
 
-  for (;;);
-
+	for (;;)
+		;
 }
 
 
@@ -773,11 +753,11 @@
 #define SAVEKMSG_MAGIC2		0x4B4D5347	/* 'KMSG' */
 
 struct savekmsg {
-    unsigned long magic1;		/* SAVEKMSG_MAGIC1 */
-    unsigned long magic2;		/* SAVEKMSG_MAGIC2 */
-    unsigned long magicptr;		/* address of magic1 */
-    unsigned long size;
-    char data[0];
+	unsigned long magic1;		/* SAVEKMSG_MAGIC1 */
+	unsigned long magic2;		/* SAVEKMSG_MAGIC2 */
+	unsigned long magicptr;		/* address of magic1 */
+	unsigned long size;
+	char data[0];
 };
 
 static struct savekmsg *savekmsg;
@@ -785,113 +765,132 @@
 static void amiga_mem_console_write(struct console *co, const char *s,
 				    unsigned int count)
 {
-    if (savekmsg->size+count <= SAVEKMSG_MAXMEM-sizeof(struct savekmsg)) {
-        memcpy(savekmsg->data+savekmsg->size, s, count);
-        savekmsg->size += count;
-    }
+	if (savekmsg->size + count <= SAVEKMSG_MAXMEM-sizeof(struct savekmsg)) {
+		memcpy(savekmsg->data + savekmsg->size, s, count);
+		savekmsg->size += count;
+	}
 }
 
-static void amiga_savekmsg_init(void)
+static int __init amiga_savekmsg_setup(char *arg)
 {
-    static struct resource debug_res = { .name = "Debug" };
+	static struct resource debug_res = { .name = "Debug" };
 
-    savekmsg = amiga_chip_alloc_res(SAVEKMSG_MAXMEM, &debug_res);
-    savekmsg->magic1 = SAVEKMSG_MAGIC1;
-    savekmsg->magic2 = SAVEKMSG_MAGIC2;
-    savekmsg->magicptr = ZTWO_PADDR(savekmsg);
-    savekmsg->size = 0;
+	if (!MACH_IS_AMIGA || strcmp(arg, "mem"))
+		goto done;
+
+	if (!AMIGAHW_PRESENT(CHIP_RAM)) {
+		printk("Warning: no chipram present for debugging\n");
+		goto done;
+	}
+
+	savekmsg = amiga_chip_alloc_res(SAVEKMSG_MAXMEM, &debug_res);
+	savekmsg->magic1 = SAVEKMSG_MAGIC1;
+	savekmsg->magic2 = SAVEKMSG_MAGIC2;
+	savekmsg->magicptr = ZTWO_PADDR(savekmsg);
+	savekmsg->size = 0;
+
+	amiga_console_driver.write = amiga_mem_console_write;
+	register_console(&amiga_console_driver);
+
+done:
+	return 0;
 }
 
+early_param("debug", amiga_savekmsg_setup);
+
 static void amiga_serial_putc(char c)
 {
-    amiga_custom.serdat = (unsigned char)c | 0x100;
-    while (!(amiga_custom.serdatr & 0x2000))
-	;
+	amiga_custom.serdat = (unsigned char)c | 0x100;
+	while (!(amiga_custom.serdatr & 0x2000))
+		;
 }
 
 void amiga_serial_console_write(struct console *co, const char *s,
-				       unsigned int count)
+				unsigned int count)
 {
-    while (count--) {
-	if (*s == '\n')
-	    amiga_serial_putc('\r');
-	amiga_serial_putc(*s++);
-    }
+	while (count--) {
+		if (*s == '\n')
+			amiga_serial_putc('\r');
+		amiga_serial_putc(*s++);
+	}
 }
 
 #ifdef CONFIG_SERIAL_CONSOLE
 void amiga_serial_puts(const char *s)
 {
-    amiga_serial_console_write(NULL, s, strlen(s));
+	amiga_serial_console_write(NULL, s, strlen(s));
 }
 
 int amiga_serial_console_wait_key(struct console *co)
 {
-    int ch;
+	int ch;
 
-    while (!(amiga_custom.intreqr & IF_RBF))
-	barrier();
-    ch = amiga_custom.serdatr & 0xff;
-    /* clear the interrupt, so that another character can be read */
-    amiga_custom.intreq = IF_RBF;
-    return ch;
+	while (!(amiga_custom.intreqr & IF_RBF))
+		barrier();
+	ch = amiga_custom.serdatr & 0xff;
+	/* clear the interrupt, so that another character can be read */
+	amiga_custom.intreq = IF_RBF;
+	return ch;
 }
 
 void amiga_serial_gets(struct console *co, char *s, int len)
 {
-    int ch, cnt = 0;
+	int ch, cnt = 0;
 
-    while (1) {
-	ch = amiga_serial_console_wait_key(co);
+	while (1) {
+		ch = amiga_serial_console_wait_key(co);
 
-	/* Check for backspace. */
-	if (ch == 8 || ch == 127) {
-	    if (cnt == 0) {
-		amiga_serial_putc('\007');
-		continue;
-	    }
-	    cnt--;
-	    amiga_serial_puts("\010 \010");
-	    continue;
+		/* Check for backspace. */
+		if (ch == 8 || ch == 127) {
+			if (cnt == 0) {
+				amiga_serial_putc('\007');
+				continue;
+			}
+			cnt--;
+			amiga_serial_puts("\010 \010");
+			continue;
+		}
+
+		/* Check for enter. */
+		if (ch == 10 || ch == 13)
+			break;
+
+		/* See if line is too long. */
+		if (cnt >= len + 1) {
+			amiga_serial_putc(7);
+			cnt--;
+			continue;
+		}
+
+		/* Store and echo character. */
+		s[cnt++] = ch;
+		amiga_serial_putc(ch);
 	}
-
-	/* Check for enter. */
-	if (ch == 10 || ch == 13)
-	    break;
-
-	/* See if line is too long. */
-	if (cnt >= len + 1) {
-	    amiga_serial_putc(7);
-	    cnt--;
-	    continue;
-	}
-
-	/* Store and echo character. */
-	s[cnt++] = ch;
-	amiga_serial_putc(ch);
-    }
-    /* Print enter. */
-    amiga_serial_puts("\r\n");
-    s[cnt] = 0;
+	/* Print enter. */
+	amiga_serial_puts("\r\n");
+	s[cnt] = 0;
 }
 #endif
 
-static void __init amiga_debug_init(void)
+static int __init amiga_debug_setup(char *arg)
 {
-	if (!strcmp( m68k_debug_device, "ser" )) {
+	if (MACH_IS_AMIGA && !strcmp(arg, "ser")) {
 		/* no initialization required (?) */
 		amiga_console_driver.write = amiga_serial_console_write;
 		register_console(&amiga_console_driver);
 	}
+	return 0;
 }
 
+early_param("debug", amiga_debug_setup);
+
 #ifdef CONFIG_HEARTBEAT
 static void amiga_heartbeat(int on)
 {
-    if (on)
-	ciaa.pra &= ~2;
-    else
-	ciaa.pra |= 2;
+	if (on)
+		ciaa.pra &= ~2;
+	else
+		ciaa.pra |= 2;
 }
 #endif
 
@@ -901,81 +900,81 @@
 
 static void amiga_get_model(char *model)
 {
-    strcpy(model, amiga_model_name);
+	strcpy(model, amiga_model_name);
 }
 
 
 static int amiga_get_hardware_list(char *buffer)
 {
-    int len = 0;
+	int len = 0;
 
-    if (AMIGAHW_PRESENT(CHIP_RAM))
-	len += sprintf(buffer+len, "Chip RAM:\t%ldK\n", amiga_chip_size>>10);
-    len += sprintf(buffer+len, "PS Freq:\t%dHz\nEClock Freq:\t%ldHz\n",
-		   amiga_psfreq, amiga_eclock);
-    if (AMIGAHW_PRESENT(AMI_VIDEO)) {
-	char *type;
-	switch(amiga_chipset) {
-	    case CS_OCS:
-		type = "OCS";
-		break;
-	    case CS_ECS:
-		type = "ECS";
-		break;
-	    case CS_AGA:
-		type = "AGA";
-		break;
-	    default:
-		type = "Old or Unknown";
-		break;
+	if (AMIGAHW_PRESENT(CHIP_RAM))
+		len += sprintf(buffer+len, "Chip RAM:\t%ldK\n", amiga_chip_size>>10);
+	len += sprintf(buffer+len, "PS Freq:\t%dHz\nEClock Freq:\t%ldHz\n",
+			amiga_psfreq, amiga_eclock);
+	if (AMIGAHW_PRESENT(AMI_VIDEO)) {
+		char *type;
+		switch (amiga_chipset) {
+		case CS_OCS:
+			type = "OCS";
+			break;
+		case CS_ECS:
+			type = "ECS";
+			break;
+		case CS_AGA:
+			type = "AGA";
+			break;
+		default:
+			type = "Old or Unknown";
+			break;
+		}
+		len += sprintf(buffer+len, "Graphics:\t%s\n", type);
 	}
-	len += sprintf(buffer+len, "Graphics:\t%s\n", type);
-    }
 
 #define AMIGAHW_ANNOUNCE(name, str)			\
-    if (AMIGAHW_PRESENT(name))				\
-	len += sprintf (buffer+len, "\t%s\n", str)
+	if (AMIGAHW_PRESENT(name))			\
+		len += sprintf (buffer+len, "\t%s\n", str)
 
-    len += sprintf (buffer + len, "Detected hardware:\n");
+	len += sprintf (buffer + len, "Detected hardware:\n");
 
-    AMIGAHW_ANNOUNCE(AMI_VIDEO, "Amiga Video");
-    AMIGAHW_ANNOUNCE(AMI_BLITTER, "Blitter");
-    AMIGAHW_ANNOUNCE(AMBER_FF, "Amber Flicker Fixer");
-    AMIGAHW_ANNOUNCE(AMI_AUDIO, "Amiga Audio");
-    AMIGAHW_ANNOUNCE(AMI_FLOPPY, "Floppy Controller");
-    AMIGAHW_ANNOUNCE(A3000_SCSI, "SCSI Controller WD33C93 (A3000 style)");
-    AMIGAHW_ANNOUNCE(A4000_SCSI, "SCSI Controller NCR53C710 (A4000T style)");
-    AMIGAHW_ANNOUNCE(A1200_IDE, "IDE Interface (A1200 style)");
-    AMIGAHW_ANNOUNCE(A4000_IDE, "IDE Interface (A4000 style)");
-    AMIGAHW_ANNOUNCE(CD_ROM, "Internal CD ROM drive");
-    AMIGAHW_ANNOUNCE(AMI_KEYBOARD, "Keyboard");
-    AMIGAHW_ANNOUNCE(AMI_MOUSE, "Mouse Port");
-    AMIGAHW_ANNOUNCE(AMI_SERIAL, "Serial Port");
-    AMIGAHW_ANNOUNCE(AMI_PARALLEL, "Parallel Port");
-    AMIGAHW_ANNOUNCE(A2000_CLK, "Hardware Clock (A2000 style)");
-    AMIGAHW_ANNOUNCE(A3000_CLK, "Hardware Clock (A3000 style)");
-    AMIGAHW_ANNOUNCE(CHIP_RAM, "Chip RAM");
-    AMIGAHW_ANNOUNCE(PAULA, "Paula 8364");
-    AMIGAHW_ANNOUNCE(DENISE, "Denise 8362");
-    AMIGAHW_ANNOUNCE(DENISE_HR, "Denise 8373");
-    AMIGAHW_ANNOUNCE(LISA, "Lisa 8375");
-    AMIGAHW_ANNOUNCE(AGNUS_PAL, "Normal/Fat PAL Agnus 8367/8371");
-    AMIGAHW_ANNOUNCE(AGNUS_NTSC, "Normal/Fat NTSC Agnus 8361/8370");
-    AMIGAHW_ANNOUNCE(AGNUS_HR_PAL, "Fat Hires PAL Agnus 8372");
-    AMIGAHW_ANNOUNCE(AGNUS_HR_NTSC, "Fat Hires NTSC Agnus 8372");
-    AMIGAHW_ANNOUNCE(ALICE_PAL, "PAL Alice 8374");
-    AMIGAHW_ANNOUNCE(ALICE_NTSC, "NTSC Alice 8374");
-    AMIGAHW_ANNOUNCE(MAGIC_REKICK, "Magic Hard Rekick");
-    AMIGAHW_ANNOUNCE(PCMCIA, "PCMCIA Slot");
+	AMIGAHW_ANNOUNCE(AMI_VIDEO, "Amiga Video");
+	AMIGAHW_ANNOUNCE(AMI_BLITTER, "Blitter");
+	AMIGAHW_ANNOUNCE(AMBER_FF, "Amber Flicker Fixer");
+	AMIGAHW_ANNOUNCE(AMI_AUDIO, "Amiga Audio");
+	AMIGAHW_ANNOUNCE(AMI_FLOPPY, "Floppy Controller");
+	AMIGAHW_ANNOUNCE(A3000_SCSI, "SCSI Controller WD33C93 (A3000 style)");
+	AMIGAHW_ANNOUNCE(A4000_SCSI, "SCSI Controller NCR53C710 (A4000T style)");
+	AMIGAHW_ANNOUNCE(A1200_IDE, "IDE Interface (A1200 style)");
+	AMIGAHW_ANNOUNCE(A4000_IDE, "IDE Interface (A4000 style)");
+	AMIGAHW_ANNOUNCE(CD_ROM, "Internal CD ROM drive");
+	AMIGAHW_ANNOUNCE(AMI_KEYBOARD, "Keyboard");
+	AMIGAHW_ANNOUNCE(AMI_MOUSE, "Mouse Port");
+	AMIGAHW_ANNOUNCE(AMI_SERIAL, "Serial Port");
+	AMIGAHW_ANNOUNCE(AMI_PARALLEL, "Parallel Port");
+	AMIGAHW_ANNOUNCE(A2000_CLK, "Hardware Clock (A2000 style)");
+	AMIGAHW_ANNOUNCE(A3000_CLK, "Hardware Clock (A3000 style)");
+	AMIGAHW_ANNOUNCE(CHIP_RAM, "Chip RAM");
+	AMIGAHW_ANNOUNCE(PAULA, "Paula 8364");
+	AMIGAHW_ANNOUNCE(DENISE, "Denise 8362");
+	AMIGAHW_ANNOUNCE(DENISE_HR, "Denise 8373");
+	AMIGAHW_ANNOUNCE(LISA, "Lisa 8375");
+	AMIGAHW_ANNOUNCE(AGNUS_PAL, "Normal/Fat PAL Agnus 8367/8371");
+	AMIGAHW_ANNOUNCE(AGNUS_NTSC, "Normal/Fat NTSC Agnus 8361/8370");
+	AMIGAHW_ANNOUNCE(AGNUS_HR_PAL, "Fat Hires PAL Agnus 8372");
+	AMIGAHW_ANNOUNCE(AGNUS_HR_NTSC, "Fat Hires NTSC Agnus 8372");
+	AMIGAHW_ANNOUNCE(ALICE_PAL, "PAL Alice 8374");
+	AMIGAHW_ANNOUNCE(ALICE_NTSC, "NTSC Alice 8374");
+	AMIGAHW_ANNOUNCE(MAGIC_REKICK, "Magic Hard Rekick");
+	AMIGAHW_ANNOUNCE(PCMCIA, "PCMCIA Slot");
 #ifdef CONFIG_ZORRO
-    if (AMIGAHW_PRESENT(ZORRO))
-	len += sprintf(buffer+len, "\tZorro II%s AutoConfig: %d Expansion "
-				   "Device%s\n",
-		       AMIGAHW_PRESENT(ZORRO3) ? "I" : "",
-		       zorro_num_autocon, zorro_num_autocon == 1 ? "" : "s");
+	if (AMIGAHW_PRESENT(ZORRO))
+		len += sprintf(buffer+len, "\tZorro II%s AutoConfig: %d Expansion "
+				"Device%s\n",
+				AMIGAHW_PRESENT(ZORRO3) ? "I" : "",
+				zorro_num_autocon, zorro_num_autocon == 1 ? "" : "s");
 #endif /* CONFIG_ZORRO */
 
 #undef AMIGAHW_ANNOUNCE
 
-    return(len);
+	return len;
 }
diff --git a/arch/m68k/atari/Makefile b/arch/m68k/atari/Makefile
index 8cb6236..2cb8619 100644
--- a/arch/m68k/atari/Makefile
+++ b/arch/m68k/atari/Makefile
@@ -8,3 +8,4 @@
 ifeq ($(CONFIG_PCI),y)
 obj-$(CONFIG_HADES)	+= hades-pci.o
 endif
+obj-$(CONFIG_ATARI_KBD_CORE)	+= atakeyb.o
diff --git a/arch/m68k/atari/atakeyb.c b/arch/m68k/atari/atakeyb.c
new file mode 100644
index 0000000..1c29603
--- /dev/null
+++ b/arch/m68k/atari/atakeyb.c
@@ -0,0 +1,730 @@
+/*
+ * linux/atari/atakeyb.c
+ *
+ * Atari Keyboard driver for 680x0 Linux
+ *
+ * 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.
+ */
+
+/*
+ * Atari support by Robert de Vries
+ * enhanced by Bjoern Brauel and Roman Hodek
+ */
+
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/errno.h>
+#include <linux/keyboard.h>
+#include <linux/delay.h>
+#include <linux/timer.h>
+#include <linux/kd.h>
+#include <linux/random.h>
+#include <linux/init.h>
+#include <linux/kbd_kern.h>
+
+#include <asm/atariints.h>
+#include <asm/atarihw.h>
+#include <asm/atarikb.h>
+#include <asm/atari_joystick.h>
+#include <asm/irq.h>
+
+static void atakeyb_rep(unsigned long ignore);
+extern unsigned int keymap_count;
+
+/* Hook for MIDI serial driver */
+void (*atari_MIDI_interrupt_hook) (void);
+/* Hook for mouse driver */
+void (*atari_mouse_interrupt_hook) (char *);
+/* Hook for keyboard inputdev  driver */
+void (*atari_input_keyboard_interrupt_hook) (unsigned char, char);
+/* Hook for mouse inputdev  driver */
+void (*atari_input_mouse_interrupt_hook) (char *);
+
+/* variables for IKBD self test: */
+
+/* state: 0: off; >0: in progress; >1: 0xf1 received */
+static volatile int ikbd_self_test;
+/* timestamp when last received a char */
+static volatile unsigned long self_test_last_rcv;
+/* bitmap of keys reported as broken */
+static unsigned long broken_keys[128/(sizeof(unsigned long)*8)] = { 0, };
+
+#define BREAK_MASK	(0x80)
+
+/*
+ * ++roman: The following changes were applied manually:
+ *
+ *  - The Alt (= Meta) key works in combination with Shift and
+ *    Control, e.g. Alt+Shift+a sends Meta-A (0xc1), Alt+Control+A sends
+ *    Meta-Ctrl-A (0x81) ...
+ *
+ *  - The parentheses on the keypad send '(' and ')' with all
+ *    modifiers (as would do e.g. keypad '+'), but they cannot be used as
+ *    application keys (i.e. sending Esc O c).
+ *
+ *  - HELP and UNDO are mapped to be F21 and F24, resp, that send the
+ *    codes "\E[M" and "\E[P". (This is better than the old mapping to
+ *    F11 and F12, because these codes are on Shift+F1/2 anyway.) This
+ *    way, applications that allow their own keyboard mappings
+ *    (e.g. tcsh, X Windows) can be configured to use them in the way
+ *    the label suggests (providing help or undoing).
+ *
+ *  - Console switching is done with Alt+Fx (consoles 1..10) and
+ *    Shift+Alt+Fx (consoles 11..20).
+ *
+ *  - The misc. special function implemented in the kernel are mapped
+ *    to the following key combinations:
+ *
+ *      ClrHome          -> Home/Find
+ *      Shift + ClrHome  -> End/Select
+ *      Shift + Up       -> Page Up
+ *      Shift + Down     -> Page Down
+ *      Alt + Help       -> show system status
+ *      Shift + Help     -> show memory info
+ *      Ctrl + Help      -> show registers
+ *      Ctrl + Alt + Del -> Reboot
+ *      Alt + Undo       -> switch to last console
+ *      Shift + Undo     -> send interrupt
+ *      Alt + Insert     -> stop/start output (same as ^S/^Q)
+ *      Alt + Up         -> Scroll back console (if implemented)
+ *      Alt + Down       -> Scroll forward console (if implemented)
+ *      Alt + CapsLock   -> NumLock
+ *
+ * ++Andreas:
+ *
+ *  - Help mapped to K_HELP
+ *  - Undo mapped to K_UNDO (= K_F246)
+ *  - Keypad Left/Right Parenthesis mapped to new K_PPAREN[LR]
+ */
+
+static u_short ataplain_map[NR_KEYS] __initdata = {
+	0xf200, 0xf01b, 0xf031, 0xf032, 0xf033, 0xf034, 0xf035, 0xf036,
+	0xf037, 0xf038, 0xf039, 0xf030, 0xf02d, 0xf03d, 0xf008, 0xf009,
+	0xfb71, 0xfb77, 0xfb65, 0xfb72, 0xfb74, 0xfb79, 0xfb75, 0xfb69,
+	0xfb6f, 0xfb70, 0xf05b, 0xf05d, 0xf201, 0xf702, 0xfb61, 0xfb73,
+	0xfb64, 0xfb66, 0xfb67, 0xfb68, 0xfb6a, 0xfb6b, 0xfb6c, 0xf03b,
+	0xf027, 0xf060, 0xf700, 0xf05c, 0xfb7a, 0xfb78, 0xfb63, 0xfb76,
+	0xfb62, 0xfb6e, 0xfb6d, 0xf02c, 0xf02e, 0xf02f, 0xf700, 0xf200,
+	0xf703, 0xf020, 0xf207, 0xf100, 0xf101, 0xf102, 0xf103, 0xf104,
+	0xf105, 0xf106, 0xf107, 0xf108, 0xf109, 0xf200, 0xf200, 0xf114,
+	0xf603, 0xf200, 0xf30b, 0xf601, 0xf200, 0xf602, 0xf30a, 0xf200,
+	0xf600, 0xf200, 0xf115, 0xf07f, 0xf200, 0xf200, 0xf200, 0xf200,
+	0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
+	0xf200, 0xf1ff, 0xf11b, 0xf312, 0xf313, 0xf30d, 0xf30c, 0xf307,
+	0xf308, 0xf309, 0xf304, 0xf305, 0xf306, 0xf301, 0xf302, 0xf303,
+	0xf300, 0xf310, 0xf30e, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
+	0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200
+};
+
+typedef enum kb_state_t {
+	KEYBOARD, AMOUSE, RMOUSE, JOYSTICK, CLOCK, RESYNC
+} KB_STATE_T;
+
+#define	IS_SYNC_CODE(sc)	((sc) >= 0x04 && (sc) <= 0xfb)
+
+typedef struct keyboard_state {
+	unsigned char buf[6];
+	int len;
+	KB_STATE_T state;
+} KEYBOARD_STATE;
+
+KEYBOARD_STATE kb_state;
+
+#define	DEFAULT_KEYB_REP_DELAY	(HZ/4)
+#define	DEFAULT_KEYB_REP_RATE	(HZ/25)
+
+/* These could be settable by some ioctl() in future... */
+static unsigned int key_repeat_delay = DEFAULT_KEYB_REP_DELAY;
+static unsigned int key_repeat_rate = DEFAULT_KEYB_REP_RATE;
+
+static unsigned char rep_scancode;
+static struct timer_list atakeyb_rep_timer = {
+	.function = atakeyb_rep,
+};
+
+static void atakeyb_rep(unsigned long ignore)
+{
+	/* Disable keyboard for the time we call handle_scancode(), else a race
+	 * in the keyboard tty queue may happen */
+	atari_disable_irq(IRQ_MFP_ACIA);
+	del_timer(&atakeyb_rep_timer);
+
+	/* A keyboard int may have come in before we disabled the irq, so
+	 * double-check whether rep_scancode is still != 0 */
+	if (rep_scancode) {
+		init_timer(&atakeyb_rep_timer);
+		atakeyb_rep_timer.expires = jiffies + key_repeat_rate;
+		add_timer(&atakeyb_rep_timer);
+
+		//handle_scancode(rep_scancode, 1);
+		if (atari_input_keyboard_interrupt_hook)
+			atari_input_keyboard_interrupt_hook(rep_scancode, 1);
+	}
+
+	atari_enable_irq(IRQ_MFP_ACIA);
+}
+
+
+/* ++roman: If a keyboard overrun happened, we can't tell in general how much
+ * bytes have been lost and in which state of the packet structure we are now.
+ * This usually causes keyboards bytes to be interpreted as mouse movements
+ * and vice versa, which is very annoying. It seems better to throw away some
+ * bytes (that are usually mouse bytes) than to misinterpret them. Therefor I
+ * introduced the RESYNC state for IKBD data. In this state, the bytes up to
+ * one that really looks like a key event (0x04..0xf2) or the start of a mouse
+ * packet (0xf8..0xfb) are thrown away, but at most 2 bytes. This at least
+ * speeds up the resynchronization of the event structure, even if maybe a
+ * mouse movement is lost. However, nothing is perfect. For bytes 0x01..0x03,
+ * it's really hard to decide whether they're mouse or keyboard bytes. Since
+ * overruns usually occur when moving the Atari mouse rapidly, they're seen as
+ * mouse bytes here. If this is wrong, only a make code of the keyboard gets
+ * lost, which isn't too bad. Loosing a break code would be disastrous,
+ * because then the keyboard repeat strikes...
+ */
+
+static irqreturn_t atari_keyboard_interrupt(int irq, void *dummy)
+{
+	u_char acia_stat;
+	int scancode;
+	int break_flag;
+
+repeat:
+	if (acia.mid_ctrl & ACIA_IRQ)
+		if (atari_MIDI_interrupt_hook)
+			atari_MIDI_interrupt_hook();
+	acia_stat = acia.key_ctrl;
+	/* check out if the interrupt came from this ACIA */
+	if (!((acia_stat | acia.mid_ctrl) & ACIA_IRQ))
+		return IRQ_HANDLED;
+
+	if (acia_stat & ACIA_OVRN) {
+		/* a very fast typist or a slow system, give a warning */
+		/* ...happens often if interrupts were disabled for too long */
+		printk(KERN_DEBUG "Keyboard overrun\n");
+		scancode = acia.key_data;
+		/* Turn off autorepeating in case a break code has been lost */
+		del_timer(&atakeyb_rep_timer);
+		rep_scancode = 0;
+		if (ikbd_self_test)
+			/* During self test, don't do resyncing, just process the code */
+			goto interpret_scancode;
+		else if (IS_SYNC_CODE(scancode)) {
+			/* This code seem already to be the start of a new packet or a
+			 * single scancode */
+			kb_state.state = KEYBOARD;
+			goto interpret_scancode;
+		} else {
+			/* Go to RESYNC state and skip this byte */
+			kb_state.state = RESYNC;
+			kb_state.len = 1;	/* skip max. 1 another byte */
+			goto repeat;
+		}
+	}
+
+	if (acia_stat & ACIA_RDRF) {
+		/* received a character */
+		scancode = acia.key_data;	/* get it or reset the ACIA, I'll get it! */
+		tasklet_schedule(&keyboard_tasklet);
+	interpret_scancode:
+		switch (kb_state.state) {
+		case KEYBOARD:
+			switch (scancode) {
+			case 0xF7:
+				kb_state.state = AMOUSE;
+				kb_state.len = 0;
+				break;
+
+			case 0xF8:
+			case 0xF9:
+			case 0xFA:
+			case 0xFB:
+				kb_state.state = RMOUSE;
+				kb_state.len = 1;
+				kb_state.buf[0] = scancode;
+				break;
+
+			case 0xFC:
+				kb_state.state = CLOCK;
+				kb_state.len = 0;
+				break;
+
+			case 0xFE:
+			case 0xFF:
+				kb_state.state = JOYSTICK;
+				kb_state.len = 1;
+				kb_state.buf[0] = scancode;
+				break;
+
+			case 0xF1:
+				/* during self-test, note that 0xf1 received */
+				if (ikbd_self_test) {
+					++ikbd_self_test;
+					self_test_last_rcv = jiffies;
+					break;
+				}
+				/* FALL THROUGH */
+
+			default:
+				break_flag = scancode & BREAK_MASK;
+				scancode &= ~BREAK_MASK;
+				if (ikbd_self_test) {
+					/* Scancodes sent during the self-test stand for broken
+					 * keys (keys being down). The code *should* be a break
+					 * code, but nevertheless some AT keyboard interfaces send
+					 * make codes instead. Therefore, simply ignore
+					 * break_flag...
+					 */
+					int keyval = plain_map[scancode], keytyp;
+
+					set_bit(scancode, broken_keys);
+					self_test_last_rcv = jiffies;
+					keyval = plain_map[scancode];
+					keytyp = KTYP(keyval) - 0xf0;
+					keyval = KVAL(keyval);
+
+					printk(KERN_WARNING "Key with scancode %d ", scancode);
+					if (keytyp == KT_LATIN || keytyp == KT_LETTER) {
+						if (keyval < ' ')
+							printk("('^%c') ", keyval + '@');
+						else
+							printk("('%c') ", keyval);
+					}
+					printk("is broken -- will be ignored.\n");
+					break;
+				} else if (test_bit(scancode, broken_keys))
+					break;
+
+#if 0	// FIXME; hangs at boot
+				if (break_flag) {
+					del_timer(&atakeyb_rep_timer);
+					rep_scancode = 0;
+				} else {
+					del_timer(&atakeyb_rep_timer);
+					rep_scancode = scancode;
+					atakeyb_rep_timer.expires = jiffies + key_repeat_delay;
+					add_timer(&atakeyb_rep_timer);
+				}
+#endif
+
+				// handle_scancode(scancode, !break_flag);
+				if (atari_input_keyboard_interrupt_hook)
+					atari_input_keyboard_interrupt_hook((unsigned char)scancode, !break_flag);
+				break;
+			}
+			break;
+
+		case AMOUSE:
+			kb_state.buf[kb_state.len++] = scancode;
+			if (kb_state.len == 5) {
+				kb_state.state = KEYBOARD;
+				/* not yet used */
+				/* wake up someone waiting for this */
+			}
+			break;
+
+		case RMOUSE:
+			kb_state.buf[kb_state.len++] = scancode;
+			if (kb_state.len == 3) {
+				kb_state.state = KEYBOARD;
+				if (atari_mouse_interrupt_hook)
+					atari_mouse_interrupt_hook(kb_state.buf);
+			}
+			break;
+
+		case JOYSTICK:
+			kb_state.buf[1] = scancode;
+			kb_state.state = KEYBOARD;
+#ifdef FIXED_ATARI_JOYSTICK
+			atari_joystick_interrupt(kb_state.buf);
+#endif
+			break;
+
+		case CLOCK:
+			kb_state.buf[kb_state.len++] = scancode;
+			if (kb_state.len == 6) {
+				kb_state.state = KEYBOARD;
+				/* wake up someone waiting for this.
+				   But will this ever be used, as Linux keeps its own time.
+				   Perhaps for synchronization purposes? */
+				/* wake_up_interruptible(&clock_wait); */
+			}
+			break;
+
+		case RESYNC:
+			if (kb_state.len <= 0 || IS_SYNC_CODE(scancode)) {
+				kb_state.state = KEYBOARD;
+				goto interpret_scancode;
+			}
+			kb_state.len--;
+			break;
+		}
+	}
+
+#if 0
+	if (acia_stat & ACIA_CTS)
+		/* cannot happen */;
+#endif
+
+	if (acia_stat & (ACIA_FE | ACIA_PE)) {
+		printk("Error in keyboard communication\n");
+	}
+
+	/* handle_scancode() can take a lot of time, so check again if
+	 * some character arrived
+	 */
+	goto repeat;
+}
+
+/*
+ * I write to the keyboard without using interrupts, I poll instead.
+ * This takes for the maximum length string allowed (7) at 7812.5 baud
+ * 8 data 1 start 1 stop bit: 9.0 ms
+ * If this takes too long for normal operation, interrupt driven writing
+ * is the solution. (I made a feeble attempt in that direction but I
+ * kept it simple for now.)
+ */
+void ikbd_write(const char *str, int len)
+{
+	u_char acia_stat;
+
+	if ((len < 1) || (len > 7))
+		panic("ikbd: maximum string length exceeded");
+	while (len) {
+		acia_stat = acia.key_ctrl;
+		if (acia_stat & ACIA_TDRE) {
+			acia.key_data = *str++;
+			len--;
+		}
+	}
+}
+
+/* Reset (without touching the clock) */
+void ikbd_reset(void)
+{
+	static const char cmd[2] = { 0x80, 0x01 };
+
+	ikbd_write(cmd, 2);
+
+	/*
+	 * if all's well code 0xF1 is returned, else the break codes of
+	 * all keys making contact
+	 */
+}
+
+/* Set mouse button action */
+void ikbd_mouse_button_action(int mode)
+{
+	char cmd[2] = { 0x07, mode };
+
+	ikbd_write(cmd, 2);
+}
+
+/* Set relative mouse position reporting */
+void ikbd_mouse_rel_pos(void)
+{
+	static const char cmd[1] = { 0x08 };
+
+	ikbd_write(cmd, 1);
+}
+
+/* Set absolute mouse position reporting */
+void ikbd_mouse_abs_pos(int xmax, int ymax)
+{
+	char cmd[5] = { 0x09, xmax>>8, xmax&0xFF, ymax>>8, ymax&0xFF };
+
+	ikbd_write(cmd, 5);
+}
+
+/* Set mouse keycode mode */
+void ikbd_mouse_kbd_mode(int dx, int dy)
+{
+	char cmd[3] = { 0x0A, dx, dy };
+
+	ikbd_write(cmd, 3);
+}
+
+/* Set mouse threshold */
+void ikbd_mouse_thresh(int x, int y)
+{
+	char cmd[3] = { 0x0B, x, y };
+
+	ikbd_write(cmd, 3);
+}
+
+/* Set mouse scale */
+void ikbd_mouse_scale(int x, int y)
+{
+	char cmd[3] = { 0x0C, x, y };
+
+	ikbd_write(cmd, 3);
+}
+
+/* Interrogate mouse position */
+void ikbd_mouse_pos_get(int *x, int *y)
+{
+	static const char cmd[1] = { 0x0D };
+
+	ikbd_write(cmd, 1);
+
+	/* wait for returning bytes */
+}
+
+/* Load mouse position */
+void ikbd_mouse_pos_set(int x, int y)
+{
+	char cmd[6] = { 0x0E, 0x00, x>>8, x&0xFF, y>>8, y&0xFF };
+
+	ikbd_write(cmd, 6);
+}
+
+/* Set Y=0 at bottom */
+void ikbd_mouse_y0_bot(void)
+{
+	static const char cmd[1] = { 0x0F };
+
+	ikbd_write(cmd, 1);
+}
+
+/* Set Y=0 at top */
+void ikbd_mouse_y0_top(void)
+{
+	static const char cmd[1] = { 0x10 };
+
+	ikbd_write(cmd, 1);
+}
+
+/* Resume */
+void ikbd_resume(void)
+{
+	static const char cmd[1] = { 0x11 };
+
+	ikbd_write(cmd, 1);
+}
+
+/* Disable mouse */
+void ikbd_mouse_disable(void)
+{
+	static const char cmd[1] = { 0x12 };
+
+	ikbd_write(cmd, 1);
+}
+
+/* Pause output */
+void ikbd_pause(void)
+{
+	static const char cmd[1] = { 0x13 };
+
+	ikbd_write(cmd, 1);
+}
+
+/* Set joystick event reporting */
+void ikbd_joystick_event_on(void)
+{
+	static const char cmd[1] = { 0x14 };
+
+	ikbd_write(cmd, 1);
+}
+
+/* Set joystick interrogation mode */
+void ikbd_joystick_event_off(void)
+{
+	static const char cmd[1] = { 0x15 };
+
+	ikbd_write(cmd, 1);
+}
+
+/* Joystick interrogation */
+void ikbd_joystick_get_state(void)
+{
+	static const char cmd[1] = { 0x16 };
+
+	ikbd_write(cmd, 1);
+}
+
+#if 0
+/* This disables all other ikbd activities !!!! */
+/* Set joystick monitoring */
+void ikbd_joystick_monitor(int rate)
+{
+	static const char cmd[2] = { 0x17, rate };
+
+	ikbd_write(cmd, 2);
+
+	kb_state.state = JOYSTICK_MONITOR;
+}
+#endif
+
+/* some joystick routines not in yet (0x18-0x19) */
+
+/* Disable joysticks */
+void ikbd_joystick_disable(void)
+{
+	static const char cmd[1] = { 0x1A };
+
+	ikbd_write(cmd, 1);
+}
+
+/* Time-of-day clock set */
+void ikbd_clock_set(int year, int month, int day, int hour, int minute, int second)
+{
+	char cmd[7] = { 0x1B, year, month, day, hour, minute, second };
+
+	ikbd_write(cmd, 7);
+}
+
+/* Interrogate time-of-day clock */
+void ikbd_clock_get(int *year, int *month, int *day, int *hour, int *minute, int second)
+{
+	static const char cmd[1] = { 0x1C };
+
+	ikbd_write(cmd, 1);
+}
+
+/* Memory load */
+void ikbd_mem_write(int address, int size, char *data)
+{
+	panic("Attempt to write data into keyboard memory");
+}
+
+/* Memory read */
+void ikbd_mem_read(int address, char data[6])
+{
+	char cmd[3] = { 0x21, address>>8, address&0xFF };
+
+	ikbd_write(cmd, 3);
+
+	/* receive data and put it in data */
+}
+
+/* Controller execute */
+void ikbd_exec(int address)
+{
+	char cmd[3] = { 0x22, address>>8, address&0xFF };
+
+	ikbd_write(cmd, 3);
+}
+
+/* Status inquiries (0x87-0x9A) not yet implemented */
+
+/* Set the state of the caps lock led. */
+void atari_kbd_leds(unsigned int leds)
+{
+	char cmd[6] = {32, 0, 4, 1, 254 + ((leds & 4) != 0), 0};
+
+	ikbd_write(cmd, 6);
+}
+
+/*
+ * The original code sometimes left the interrupt line of
+ * the ACIAs low forever. I hope, it is fixed now.
+ *
+ * Martin Rogge, 20 Aug 1995
+ */
+
+static int atari_keyb_done = 0;
+
+int __init atari_keyb_init(void)
+{
+	if (atari_keyb_done)
+		return 0;
+
+	/* setup key map */
+	memcpy(key_maps[0], ataplain_map, sizeof(plain_map));
+
+	kb_state.state = KEYBOARD;
+	kb_state.len = 0;
+
+	request_irq(IRQ_MFP_ACIA, atari_keyboard_interrupt, IRQ_TYPE_SLOW,
+		    "keyboard/mouse/MIDI", atari_keyboard_interrupt);
+
+	atari_turnoff_irq(IRQ_MFP_ACIA);
+	do {
+		/* reset IKBD ACIA */
+		acia.key_ctrl = ACIA_RESET |
+				(atari_switches & ATARI_SWITCH_IKBD) ? ACIA_RHTID : 0;
+		(void)acia.key_ctrl;
+		(void)acia.key_data;
+
+		/* reset MIDI ACIA */
+		acia.mid_ctrl = ACIA_RESET |
+				(atari_switches & ATARI_SWITCH_MIDI) ? ACIA_RHTID : 0;
+		(void)acia.mid_ctrl;
+		(void)acia.mid_data;
+
+		/* divide 500kHz by 64 gives 7812.5 baud */
+		/* 8 data no parity 1 start 1 stop bit */
+		/* receive interrupt enabled */
+		/* RTS low (except if switch selected), transmit interrupt disabled */
+		acia.key_ctrl = (ACIA_DIV64|ACIA_D8N1S|ACIA_RIE) |
+				((atari_switches & ATARI_SWITCH_IKBD) ?
+				 ACIA_RHTID : ACIA_RLTID);
+
+		acia.mid_ctrl = ACIA_DIV16 | ACIA_D8N1S |
+				(atari_switches & ATARI_SWITCH_MIDI) ? ACIA_RHTID : 0;
+
+	/* make sure the interrupt line is up */
+	} while ((mfp.par_dt_reg & 0x10) == 0);
+
+	/* enable ACIA Interrupts */
+	mfp.active_edge &= ~0x10;
+	atari_turnon_irq(IRQ_MFP_ACIA);
+
+	ikbd_self_test = 1;
+	ikbd_reset();
+	/* wait for a period of inactivity (here: 0.25s), then assume the IKBD's
+	 * self-test is finished */
+	self_test_last_rcv = jiffies;
+	while (time_before(jiffies, self_test_last_rcv + HZ/4))
+		barrier();
+	/* if not incremented: no 0xf1 received */
+	if (ikbd_self_test == 1)
+		printk(KERN_ERR "WARNING: keyboard self test failed!\n");
+	ikbd_self_test = 0;
+
+	ikbd_mouse_disable();
+	ikbd_joystick_disable();
+
+#ifdef FIXED_ATARI_JOYSTICK
+	atari_joystick_init();
+#endif
+
+	// flag init done
+	atari_keyb_done = 1;
+	return 0;
+}
+
+
+int atari_kbdrate(struct kbd_repeat *k)
+{
+	if (k->delay > 0) {
+		/* convert from msec to jiffies */
+		key_repeat_delay = (k->delay * HZ + 500) / 1000;
+		if (key_repeat_delay < 1)
+			key_repeat_delay = 1;
+	}
+	if (k->period > 0) {
+		key_repeat_rate = (k->period * HZ + 500) / 1000;
+		if (key_repeat_rate < 1)
+			key_repeat_rate = 1;
+	}
+
+	k->delay  = key_repeat_delay * 1000 / HZ;
+	k->period = key_repeat_rate  * 1000 / HZ;
+
+	return 0;
+}
+
+int atari_kbd_translate(unsigned char keycode, unsigned char *keycodep, char raw_mode)
+{
+#ifdef CONFIG_MAGIC_SYSRQ
+	/* ALT+HELP pressed? */
+	if ((keycode == 98) && ((shift_state & 0xff) == 8))
+		*keycodep = 0xff;
+	else
+#endif
+		*keycodep = keycode;
+	return 1;
+}
diff --git a/arch/m68k/atari/config.c b/arch/m68k/atari/config.c
index ca5cd43..e40e5dc 100644
--- a/arch/m68k/atari/config.c
+++ b/arch/m68k/atari/config.c
@@ -50,70 +50,25 @@
 int atari_rtc_year_offset;
 
 /* local function prototypes */
-static void atari_reset( void );
+static void atari_reset(void);
 static void atari_get_model(char *model);
 static int atari_get_hardware_list(char *buffer);
 
 /* atari specific irq functions */
 extern void atari_init_IRQ (void);
-extern void atari_mksound( unsigned int count, unsigned int ticks );
+extern void atari_mksound(unsigned int count, unsigned int ticks);
 #ifdef CONFIG_HEARTBEAT
-static void atari_heartbeat( int on );
+static void atari_heartbeat(int on);
 #endif
 
 /* atari specific timer functions (in time.c) */
-extern void atari_sched_init(irq_handler_t );
+extern void atari_sched_init(irq_handler_t);
 extern unsigned long atari_gettimeoffset (void);
 extern int atari_mste_hwclk (int, struct rtc_time *);
 extern int atari_tt_hwclk (int, struct rtc_time *);
 extern int atari_mste_set_clock_mmss (unsigned long);
 extern int atari_tt_set_clock_mmss (unsigned long);
 
-/* atari specific debug functions (in debug.c) */
-extern void atari_debug_init(void);
-
-
-/* I've moved hwreg_present() and hwreg_present_bywrite() out into
- * mm/hwtest.c, to avoid having multiple copies of the same routine
- * in the kernel [I wanted them in hp300 and they were already used
- * in the nubus code. NB: I don't have an Atari so this might (just
- * conceivably) break something.
- * I've preserved the #if 0 version of hwreg_present_bywrite() here
- * for posterity.
- *   -- Peter Maydell <pmaydell@chiark.greenend.org.uk>, 05/1998
- */
-
-#if 0
-static int __init
-hwreg_present_bywrite(volatile void *regp, unsigned char val)
-{
-    int		ret;
-    long	save_sp, save_vbr;
-    static long tmp_vectors[3] = { [2] = (long)&&after_test };
-
-    __asm__ __volatile__
-	(	"movec	%/vbr,%2\n\t"	/* save vbr value            */
-                "movec	%4,%/vbr\n\t"	/* set up temporary vectors  */
-		"movel	%/sp,%1\n\t"	/* save sp                   */
-		"moveq	#0,%0\n\t"	/* assume not present        */
-		"moveb	%5,%3@\n\t"	/* write the hardware reg    */
-		"cmpb	%3@,%5\n\t"	/* compare it                */
-		"seq	%0"		/* comes here only if reg    */
-                                        /* is present                */
-		: "=d&" (ret), "=r&" (save_sp), "=r&" (save_vbr)
-		: "a" (regp), "r" (tmp_vectors), "d" (val)
-                );
-  after_test:
-    __asm__ __volatile__
-      (	"movel	%0,%/sp\n\t"		/* restore sp                */
-        "movec	%1,%/vbr"			/* restore vbr               */
-        : : "r" (save_sp), "r" (save_vbr) : "sp"
-	);
-
-    return( ret );
-}
-#endif
-
 
 /* ++roman: This is a more elaborate test for an SCC chip, since the plain
  * Medusa board generates DTACK at the SCC's standard addresses, but a SCC
@@ -123,26 +78,34 @@
  * should be readable without trouble (from channel A!).
  */
 
-static int __init scc_test( volatile char *ctla )
+static int __init scc_test(volatile char *ctla)
 {
-	if (!hwreg_present( ctla ))
-		return( 0 );
+	if (!hwreg_present(ctla))
+		return 0;
 	MFPDELAY();
 
-	*ctla = 2; MFPDELAY();
-	*ctla = 0x40; MFPDELAY();
-
-	*ctla = 2; MFPDELAY();
-	if (*ctla != 0x40) return( 0 );
+	*ctla = 2;
+	MFPDELAY();
+	*ctla = 0x40;
 	MFPDELAY();
 
-	*ctla = 2; MFPDELAY();
-	*ctla = 0x60; MFPDELAY();
+	*ctla = 2;
+	MFPDELAY();
+	if (*ctla != 0x40)
+		return 0;
+	MFPDELAY();
 
-	*ctla = 2; MFPDELAY();
-	if (*ctla != 0x60) return( 0 );
+	*ctla = 2;
+	MFPDELAY();
+	*ctla = 0x60;
+	MFPDELAY();
 
-	return( 1 );
+	*ctla = 2;
+	MFPDELAY();
+	if (*ctla != 0x60)
+		return 0;
+
+	return 1;
 }
 
 
@@ -152,61 +115,66 @@
 
 int __init atari_parse_bootinfo(const struct bi_record *record)
 {
-    int unknown = 0;
-    const u_long *data = record->data;
+	int unknown = 0;
+	const u_long *data = record->data;
 
-    switch (record->tag) {
+	switch (record->tag) {
 	case BI_ATARI_MCH_COOKIE:
-	    atari_mch_cookie = *data;
-	    break;
+		atari_mch_cookie = *data;
+		break;
 	case BI_ATARI_MCH_TYPE:
-	    atari_mch_type = *data;
-	    break;
+		atari_mch_type = *data;
+		break;
 	default:
-	    unknown = 1;
-    }
-    return(unknown);
+		unknown = 1;
+		break;
+	}
+	return unknown;
 }
 
 
 /* Parse the Atari-specific switches= option. */
-void __init atari_switches_setup( const char *str, unsigned len )
+static int __init atari_switches_setup(char *str)
 {
-    char switches[len+1];
-    char *p;
-    int ovsc_shift;
-    char *args = switches;
+	char switches[strlen(str) + 1];
+	char *p;
+	int ovsc_shift;
+	char *args = switches;
 
-    /* copy string to local array, strsep works destructively... */
-    strlcpy( switches, str, sizeof(switches) );
-    atari_switches = 0;
+	if (!MACH_IS_ATARI)
+		return 0;
 
-    /* parse the options */
-    while ((p = strsep(&args, ",")) != NULL) {
-	if (!*p) continue;
-	ovsc_shift = 0;
-	if (strncmp( p, "ov_", 3 ) == 0) {
-	    p += 3;
-	    ovsc_shift = ATARI_SWITCH_OVSC_SHIFT;
-	}
+	/* copy string to local array, strsep works destructively... */
+	strcpy(switches, str);
+	atari_switches = 0;
 
-	if (strcmp( p, "ikbd" ) == 0) {
-	    /* RTS line of IKBD ACIA */
-	    atari_switches |= ATARI_SWITCH_IKBD << ovsc_shift;
+	/* parse the options */
+	while ((p = strsep(&args, ",")) != NULL) {
+		if (!*p)
+			continue;
+		ovsc_shift = 0;
+		if (strncmp(p, "ov_", 3) == 0) {
+			p += 3;
+			ovsc_shift = ATARI_SWITCH_OVSC_SHIFT;
+		}
+
+		if (strcmp(p, "ikbd") == 0) {
+			/* RTS line of IKBD ACIA */
+			atari_switches |= ATARI_SWITCH_IKBD << ovsc_shift;
+		} else if (strcmp(p, "midi") == 0) {
+			/* RTS line of MIDI ACIA */
+			atari_switches |= ATARI_SWITCH_MIDI << ovsc_shift;
+		} else if (strcmp(p, "snd6") == 0) {
+			atari_switches |= ATARI_SWITCH_SND6 << ovsc_shift;
+		} else if (strcmp(p, "snd7") == 0) {
+			atari_switches |= ATARI_SWITCH_SND7 << ovsc_shift;
+		}
 	}
-	else if (strcmp( p, "midi" ) == 0) {
-	    /* RTS line of MIDI ACIA */
-	    atari_switches |= ATARI_SWITCH_MIDI << ovsc_shift;
-	}
-	else if (strcmp( p, "snd6" ) == 0) {
-	    atari_switches |= ATARI_SWITCH_SND6 << ovsc_shift;
-	}
-	else if (strcmp( p, "snd7" ) == 0) {
-	    atari_switches |= ATARI_SWITCH_SND7 << ovsc_shift;
-	}
-    }
+	return 0;
 }
 
+early_param("switches", atari_switches_setup);
+
 
     /*
      *  Setup the Atari configuration info
@@ -214,284 +182,281 @@
 
 void __init config_atari(void)
 {
-    unsigned short tos_version;
+	unsigned short tos_version;
 
-    memset(&atari_hw_present, 0, sizeof(atari_hw_present));
+	memset(&atari_hw_present, 0, sizeof(atari_hw_present));
 
-    atari_debug_init();
+	/* Change size of I/O space from 64KB to 4GB. */
+	ioport_resource.end  = 0xFFFFFFFF;
 
-    ioport_resource.end  = 0xFFFFFFFF;  /* Change size of I/O space from 64KB
-                                           to 4GB. */
-
-    mach_sched_init      = atari_sched_init;
-    mach_init_IRQ        = atari_init_IRQ;
-    mach_get_model	 = atari_get_model;
-    mach_get_hardware_list = atari_get_hardware_list;
-    mach_gettimeoffset   = atari_gettimeoffset;
-    mach_reset           = atari_reset;
-    mach_max_dma_address = 0xffffff;
+	mach_sched_init      = atari_sched_init;
+	mach_init_IRQ        = atari_init_IRQ;
+	mach_get_model	 = atari_get_model;
+	mach_get_hardware_list = atari_get_hardware_list;
+	mach_gettimeoffset   = atari_gettimeoffset;
+	mach_reset           = atari_reset;
+	mach_max_dma_address = 0xffffff;
 #if defined(CONFIG_INPUT_M68K_BEEP) || defined(CONFIG_INPUT_M68K_BEEP_MODULE)
-    mach_beep          = atari_mksound;
+	mach_beep          = atari_mksound;
 #endif
 #ifdef CONFIG_HEARTBEAT
-    mach_heartbeat = atari_heartbeat;
+	mach_heartbeat = atari_heartbeat;
 #endif
 
-    /* Set switches as requested by the user */
-    if (atari_switches & ATARI_SWITCH_IKBD)
-	acia.key_ctrl = ACIA_DIV64 | ACIA_D8N1S | ACIA_RHTID;
-    if (atari_switches & ATARI_SWITCH_MIDI)
-	acia.mid_ctrl = ACIA_DIV16 | ACIA_D8N1S | ACIA_RHTID;
-    if (atari_switches & (ATARI_SWITCH_SND6|ATARI_SWITCH_SND7)) {
-	sound_ym.rd_data_reg_sel = 14;
-	sound_ym.wd_data = sound_ym.rd_data_reg_sel |
-			   ((atari_switches&ATARI_SWITCH_SND6) ? 0x40 : 0) |
-			   ((atari_switches&ATARI_SWITCH_SND7) ? 0x80 : 0);
-    }
+	/* Set switches as requested by the user */
+	if (atari_switches & ATARI_SWITCH_IKBD)
+		acia.key_ctrl = ACIA_DIV64 | ACIA_D8N1S | ACIA_RHTID;
+	if (atari_switches & ATARI_SWITCH_MIDI)
+		acia.mid_ctrl = ACIA_DIV16 | ACIA_D8N1S | ACIA_RHTID;
+	if (atari_switches & (ATARI_SWITCH_SND6|ATARI_SWITCH_SND7)) {
+		sound_ym.rd_data_reg_sel = 14;
+		sound_ym.wd_data = sound_ym.rd_data_reg_sel |
+				   ((atari_switches&ATARI_SWITCH_SND6) ? 0x40 : 0) |
+				   ((atari_switches&ATARI_SWITCH_SND7) ? 0x80 : 0);
+	}
 
-    /* ++bjoern:
-     * Determine hardware present
-     */
+	/* ++bjoern:
+	 * Determine hardware present
+	 */
 
-    printk( "Atari hardware found: " );
-    if (MACH_IS_MEDUSA || MACH_IS_HADES) {
-        /* There's no Atari video hardware on the Medusa, but all the
-         * addresses below generate a DTACK so no bus error occurs! */
-    }
-    else if (hwreg_present( f030_xreg )) {
-	ATARIHW_SET(VIDEL_SHIFTER);
-        printk( "VIDEL " );
-        /* This is a temporary hack: If there is Falcon video
-         * hardware, we assume that the ST-DMA serves SCSI instead of
-         * ACSI. In the future, there should be a better method for
-         * this...
-         */
-	ATARIHW_SET(ST_SCSI);
-        printk( "STDMA-SCSI " );
-    }
-    else if (hwreg_present( tt_palette )) {
-	ATARIHW_SET(TT_SHIFTER);
-        printk( "TT_SHIFTER " );
-    }
-    else if (hwreg_present( &shifter.bas_hi )) {
-        if (hwreg_present( &shifter.bas_lo ) &&
-	    (shifter.bas_lo = 0x0aau, shifter.bas_lo == 0x0aau)) {
-	    ATARIHW_SET(EXTD_SHIFTER);
-            printk( "EXTD_SHIFTER " );
-        }
-        else {
-	    ATARIHW_SET(STND_SHIFTER);
-            printk( "STND_SHIFTER " );
-        }
-    }
-    if (hwreg_present( &mfp.par_dt_reg )) {
-	ATARIHW_SET(ST_MFP);
-        printk( "ST_MFP " );
-    }
-    if (hwreg_present( &tt_mfp.par_dt_reg )) {
-	ATARIHW_SET(TT_MFP);
-        printk( "TT_MFP " );
-    }
-    if (hwreg_present( &tt_scsi_dma.dma_addr_hi )) {
-	ATARIHW_SET(SCSI_DMA);
-        printk( "TT_SCSI_DMA " );
-    }
-    if (!MACH_IS_HADES && hwreg_present( &st_dma.dma_hi )) {
-	ATARIHW_SET(STND_DMA);
-        printk( "STND_DMA " );
-    }
-    if (MACH_IS_MEDUSA || /* The ST-DMA address registers aren't readable
-			   * on all Medusas, so the test below may fail */
-        (hwreg_present( &st_dma.dma_vhi ) &&
-         (st_dma.dma_vhi = 0x55) && (st_dma.dma_hi = 0xaa) &&
-         st_dma.dma_vhi == 0x55 && st_dma.dma_hi == 0xaa &&
-         (st_dma.dma_vhi = 0xaa) && (st_dma.dma_hi = 0x55) &&
-         st_dma.dma_vhi == 0xaa && st_dma.dma_hi == 0x55)) {
-	ATARIHW_SET(EXTD_DMA);
-        printk( "EXTD_DMA " );
-    }
-    if (hwreg_present( &tt_scsi.scsi_data )) {
-	ATARIHW_SET(TT_SCSI);
-        printk( "TT_SCSI " );
-    }
-    if (hwreg_present( &sound_ym.rd_data_reg_sel )) {
-	ATARIHW_SET(YM_2149);
-        printk( "YM2149 " );
-    }
-    if (!MACH_IS_MEDUSA && !MACH_IS_HADES &&
-	hwreg_present( &tt_dmasnd.ctrl )) {
-	ATARIHW_SET(PCM_8BIT);
-        printk( "PCM " );
-    }
-    if (!MACH_IS_HADES && hwreg_present( &falcon_codec.unused5 )) {
-	ATARIHW_SET(CODEC);
-        printk( "CODEC " );
-    }
-    if (hwreg_present( &dsp56k_host_interface.icr )) {
-	ATARIHW_SET(DSP56K);
-        printk( "DSP56K " );
-    }
-    if (hwreg_present( &tt_scc_dma.dma_ctrl ) &&
+	printk("Atari hardware found: ");
+	if (MACH_IS_MEDUSA || MACH_IS_HADES) {
+		/* There's no Atari video hardware on the Medusa, but all the
+		 * addresses below generate a DTACK so no bus error occurs! */
+	} else if (hwreg_present(f030_xreg)) {
+		ATARIHW_SET(VIDEL_SHIFTER);
+		printk("VIDEL ");
+		/* This is a temporary hack: If there is Falcon video
+		 * hardware, we assume that the ST-DMA serves SCSI instead of
+		 * ACSI. In the future, there should be a better method for
+		 * this...
+		 */
+		ATARIHW_SET(ST_SCSI);
+		printk("STDMA-SCSI ");
+	} else if (hwreg_present(tt_palette)) {
+		ATARIHW_SET(TT_SHIFTER);
+		printk("TT_SHIFTER ");
+	} else if (hwreg_present(&shifter.bas_hi)) {
+		if (hwreg_present(&shifter.bas_lo) &&
+		    (shifter.bas_lo = 0x0aau, shifter.bas_lo == 0x0aau)) {
+			ATARIHW_SET(EXTD_SHIFTER);
+			printk("EXTD_SHIFTER ");
+		} else {
+			ATARIHW_SET(STND_SHIFTER);
+			printk("STND_SHIFTER ");
+		}
+	}
+	if (hwreg_present(&mfp.par_dt_reg)) {
+		ATARIHW_SET(ST_MFP);
+		printk("ST_MFP ");
+	}
+	if (hwreg_present(&tt_mfp.par_dt_reg)) {
+		ATARIHW_SET(TT_MFP);
+		printk("TT_MFP ");
+	}
+	if (hwreg_present(&tt_scsi_dma.dma_addr_hi)) {
+		ATARIHW_SET(SCSI_DMA);
+		printk("TT_SCSI_DMA ");
+	}
+	if (!MACH_IS_HADES && hwreg_present(&st_dma.dma_hi)) {
+		ATARIHW_SET(STND_DMA);
+		printk("STND_DMA ");
+	}
+	/*
+	 * The ST-DMA address registers aren't readable
+	 * on all Medusas, so the test below may fail
+	 */
+	if (MACH_IS_MEDUSA ||
+	    (hwreg_present(&st_dma.dma_vhi) &&
+	     (st_dma.dma_vhi = 0x55) && (st_dma.dma_hi = 0xaa) &&
+	     st_dma.dma_vhi == 0x55 && st_dma.dma_hi == 0xaa &&
+	     (st_dma.dma_vhi = 0xaa) && (st_dma.dma_hi = 0x55) &&
+	     st_dma.dma_vhi == 0xaa && st_dma.dma_hi == 0x55)) {
+		ATARIHW_SET(EXTD_DMA);
+		printk("EXTD_DMA ");
+	}
+	if (hwreg_present(&tt_scsi.scsi_data)) {
+		ATARIHW_SET(TT_SCSI);
+		printk("TT_SCSI ");
+	}
+	if (hwreg_present(&sound_ym.rd_data_reg_sel)) {
+		ATARIHW_SET(YM_2149);
+		printk("YM2149 ");
+	}
+	if (!MACH_IS_MEDUSA && !MACH_IS_HADES &&
+		hwreg_present(&tt_dmasnd.ctrl)) {
+		ATARIHW_SET(PCM_8BIT);
+		printk("PCM ");
+	}
+	if (!MACH_IS_HADES && hwreg_present(&falcon_codec.unused5)) {
+		ATARIHW_SET(CODEC);
+		printk("CODEC ");
+	}
+	if (hwreg_present(&dsp56k_host_interface.icr)) {
+		ATARIHW_SET(DSP56K);
+		printk("DSP56K ");
+	}
+	if (hwreg_present(&tt_scc_dma.dma_ctrl) &&
 #if 0
-	/* This test sucks! Who knows some better? */
-	(tt_scc_dma.dma_ctrl = 0x01, (tt_scc_dma.dma_ctrl & 1) == 1) &&
-	(tt_scc_dma.dma_ctrl = 0x00, (tt_scc_dma.dma_ctrl & 1) == 0)
+	    /* This test sucks! Who knows some better? */
+	    (tt_scc_dma.dma_ctrl = 0x01, (tt_scc_dma.dma_ctrl & 1) == 1) &&
+	    (tt_scc_dma.dma_ctrl = 0x00, (tt_scc_dma.dma_ctrl & 1) == 0)
 #else
-	!MACH_IS_MEDUSA && !MACH_IS_HADES
+	    !MACH_IS_MEDUSA && !MACH_IS_HADES
 #endif
-	) {
-	ATARIHW_SET(SCC_DMA);
-        printk( "SCC_DMA " );
-    }
-    if (scc_test( &scc.cha_a_ctrl )) {
-	ATARIHW_SET(SCC);
-        printk( "SCC " );
-    }
-    if (scc_test( &st_escc.cha_b_ctrl )) {
-	ATARIHW_SET( ST_ESCC );
-	printk( "ST_ESCC " );
-    }
-    if (MACH_IS_HADES)
-    {
-        ATARIHW_SET( VME );
-        printk( "VME " );
-    }
-    else if (hwreg_present( &tt_scu.sys_mask )) {
-	ATARIHW_SET(SCU);
-	/* Assume a VME bus if there's a SCU */
-	ATARIHW_SET( VME );
-        printk( "VME SCU " );
-    }
-    if (hwreg_present( (void *)(0xffff9210) )) {
-	ATARIHW_SET(ANALOG_JOY);
-        printk( "ANALOG_JOY " );
-    }
-    if (!MACH_IS_HADES && hwreg_present( blitter.halftone )) {
-	ATARIHW_SET(BLITTER);
-        printk( "BLITTER " );
-    }
-    if (hwreg_present((void *)0xfff00039)) {
-	ATARIHW_SET(IDE);
-        printk( "IDE " );
-    }
+	    ) {
+		ATARIHW_SET(SCC_DMA);
+		printk("SCC_DMA ");
+	}
+	if (scc_test(&scc.cha_a_ctrl)) {
+		ATARIHW_SET(SCC);
+		printk("SCC ");
+	}
+	if (scc_test(&st_escc.cha_b_ctrl)) {
+		ATARIHW_SET(ST_ESCC);
+		printk("ST_ESCC ");
+	}
+	if (MACH_IS_HADES) {
+		ATARIHW_SET(VME);
+		printk("VME ");
+	} else if (hwreg_present(&tt_scu.sys_mask)) {
+		ATARIHW_SET(SCU);
+		/* Assume a VME bus if there's a SCU */
+		ATARIHW_SET(VME);
+		printk("VME SCU ");
+	}
+	if (hwreg_present((void *)(0xffff9210))) {
+		ATARIHW_SET(ANALOG_JOY);
+		printk("ANALOG_JOY ");
+	}
+	if (!MACH_IS_HADES && hwreg_present(blitter.halftone)) {
+		ATARIHW_SET(BLITTER);
+		printk("BLITTER ");
+	}
+	if (hwreg_present((void *)0xfff00039)) {
+		ATARIHW_SET(IDE);
+		printk("IDE ");
+	}
 #if 1 /* This maybe wrong */
-    if (!MACH_IS_MEDUSA && !MACH_IS_HADES &&
-	hwreg_present( &tt_microwire.data ) &&
-	hwreg_present( &tt_microwire.mask ) &&
-	(tt_microwire.mask = 0x7ff,
-	 udelay(1),
-	 tt_microwire.data = MW_LM1992_PSG_HIGH | MW_LM1992_ADDR,
-	 udelay(1),
-	 tt_microwire.data != 0)) {
-	ATARIHW_SET(MICROWIRE);
-	while (tt_microwire.mask != 0x7ff) ;
-        printk( "MICROWIRE " );
-    }
+	if (!MACH_IS_MEDUSA && !MACH_IS_HADES &&
+	    hwreg_present(&tt_microwire.data) &&
+	    hwreg_present(&tt_microwire.mask) &&
+	    (tt_microwire.mask = 0x7ff,
+	     udelay(1),
+	     tt_microwire.data = MW_LM1992_PSG_HIGH | MW_LM1992_ADDR,
+	     udelay(1),
+	     tt_microwire.data != 0)) {
+		ATARIHW_SET(MICROWIRE);
+		while (tt_microwire.mask != 0x7ff)
+			;
+		printk("MICROWIRE ");
+	}
 #endif
-    if (hwreg_present( &tt_rtc.regsel )) {
-	ATARIHW_SET(TT_CLK);
-        printk( "TT_CLK " );
-        mach_hwclk = atari_tt_hwclk;
-        mach_set_clock_mmss = atari_tt_set_clock_mmss;
-    }
-    if (!MACH_IS_HADES && hwreg_present( &mste_rtc.sec_ones)) {
-	ATARIHW_SET(MSTE_CLK);
-        printk( "MSTE_CLK ");
-        mach_hwclk = atari_mste_hwclk;
-        mach_set_clock_mmss = atari_mste_set_clock_mmss;
-    }
-    if (!MACH_IS_MEDUSA && !MACH_IS_HADES &&
-	hwreg_present( &dma_wd.fdc_speed ) &&
-	hwreg_write( &dma_wd.fdc_speed, 0 )) {
-	    ATARIHW_SET(FDCSPEED);
-	    printk( "FDC_SPEED ");
-    }
-    if (!MACH_IS_HADES && !ATARIHW_PRESENT(ST_SCSI)) {
-	ATARIHW_SET(ACSI);
-        printk( "ACSI " );
-    }
-    printk("\n");
+	if (hwreg_present(&tt_rtc.regsel)) {
+		ATARIHW_SET(TT_CLK);
+		printk("TT_CLK ");
+		mach_hwclk = atari_tt_hwclk;
+		mach_set_clock_mmss = atari_tt_set_clock_mmss;
+	}
+	if (!MACH_IS_HADES && hwreg_present(&mste_rtc.sec_ones)) {
+		ATARIHW_SET(MSTE_CLK);
+		printk("MSTE_CLK ");
+		mach_hwclk = atari_mste_hwclk;
+		mach_set_clock_mmss = atari_mste_set_clock_mmss;
+	}
+	if (!MACH_IS_MEDUSA && !MACH_IS_HADES &&
+	    hwreg_present(&dma_wd.fdc_speed) &&
+	    hwreg_write(&dma_wd.fdc_speed, 0)) {
+		ATARIHW_SET(FDCSPEED);
+		printk("FDC_SPEED ");
+	}
+	if (!MACH_IS_HADES && !ATARIHW_PRESENT(ST_SCSI)) {
+		ATARIHW_SET(ACSI);
+		printk("ACSI ");
+	}
+	printk("\n");
 
-    if (CPU_IS_040_OR_060)
-        /* Now it seems to be safe to turn of the tt0 transparent
-         * translation (the one that must not be turned off in
-         * head.S...)
-         */
-        __asm__ volatile ("moveq #0,%/d0\n\t"
-                          ".chip 68040\n\t"
-			  "movec %%d0,%%itt0\n\t"
-			  "movec %%d0,%%dtt0\n\t"
-			  ".chip 68k"
-						  : /* no outputs */
-						  : /* no inputs */
-						  : "d0");
+	if (CPU_IS_040_OR_060)
+		/* Now it seems to be safe to turn of the tt0 transparent
+		 * translation (the one that must not be turned off in
+		 * head.S...)
+		 */
+		asm volatile ("\n"
+			"	moveq	#0,%%d0\n"
+			"	.chip	68040\n"
+			"	movec	%%d0,%%itt0\n"
+			"	movec	%%d0,%%dtt0\n"
+			"	.chip	68k"
+			: /* no outputs */
+			: /* no inputs */
+			: "d0");
 
-    /* allocator for memory that must reside in st-ram */
-    atari_stram_init ();
+	/* allocator for memory that must reside in st-ram */
+	atari_stram_init();
 
-    /* Set up a mapping for the VMEbus address region:
-     *
-     * VME is either at phys. 0xfexxxxxx (TT) or 0xa00000..0xdfffff
-     * (MegaSTE) In both cases, the whole 16 MB chunk is mapped at
-     * 0xfe000000 virt., because this can be done with a single
-     * transparent translation. On the 68040, lots of often unused
-     * page tables would be needed otherwise. On a MegaSTE or similar,
-     * the highest byte is stripped off by hardware due to the 24 bit
-     * design of the bus.
-     */
+	/* Set up a mapping for the VMEbus address region:
+	 *
+	 * VME is either at phys. 0xfexxxxxx (TT) or 0xa00000..0xdfffff
+	 * (MegaSTE) In both cases, the whole 16 MB chunk is mapped at
+	 * 0xfe000000 virt., because this can be done with a single
+	 * transparent translation. On the 68040, lots of often unused
+	 * page tables would be needed otherwise. On a MegaSTE or similar,
+	 * the highest byte is stripped off by hardware due to the 24 bit
+	 * design of the bus.
+	 */
 
-    if (CPU_IS_020_OR_030) {
-        unsigned long	tt1_val;
-        tt1_val = 0xfe008543;	/* Translate 0xfexxxxxx, enable, cache
-                                 * inhibit, read and write, FDC mask = 3,
-                                 * FDC val = 4 -> Supervisor only */
-        __asm__ __volatile__ ( ".chip 68030\n\t"
-				"pmove	%0@,%/tt1\n\t"
-				".chip 68k"
-				: : "a" (&tt1_val) );
-    }
-    else {
-        __asm__ __volatile__
-            ( "movel %0,%/d0\n\t"
-	      ".chip 68040\n\t"
-	      "movec %%d0,%%itt1\n\t"
-	      "movec %%d0,%%dtt1\n\t"
-	      ".chip 68k"
-              :
-              : "g" (0xfe00a040)	/* Translate 0xfexxxxxx, enable,
-                                         * supervisor only, non-cacheable/
-                                         * serialized, writable */
-              : "d0" );
+	if (CPU_IS_020_OR_030) {
+		unsigned long tt1_val;
+		tt1_val = 0xfe008543;	/* Translate 0xfexxxxxx, enable, cache
+					 * inhibit, read and write, FDC mask = 3,
+					 * FDC val = 4 -> Supervisor only */
+		asm volatile ("\n"
+			"	.chip	68030\n"
+			"	pmove	%0@,%/tt1\n"
+			"	.chip	68k"
+			: : "a" (&tt1_val));
+	} else {
+	        asm volatile ("\n"
+			"	.chip	68040\n"
+			"	movec	%0,%%itt1\n"
+			"	movec	%0,%%dtt1\n"
+			"	.chip	68k"
+			:
+			: "d" (0xfe00a040));	/* Translate 0xfexxxxxx, enable,
+						 * supervisor only, non-cacheable/
+						 * serialized, writable */
 
-    }
+	}
 
-    /* Fetch tos version at Physical 2 */
-    /* We my not be able to access this address if the kernel is
-       loaded to st ram, since the first page is unmapped.  On the
-       Medusa this is always the case and there is nothing we can do
-       about this, so we just assume the smaller offset.  For the TT
-       we use the fact that in head.S we have set up a mapping
-       0xFFxxxxxx -> 0x00xxxxxx, so that the first 16MB is accessible
-       in the last 16MB of the address space. */
-    tos_version = (MACH_IS_MEDUSA || MACH_IS_HADES) ?
-		  0xfff : *(unsigned short *)0xff000002;
-    atari_rtc_year_offset = (tos_version < 0x306) ? 70 : 68;
+	/* Fetch tos version at Physical 2 */
+	/*
+	 * We my not be able to access this address if the kernel is
+	 * loaded to st ram, since the first page is unmapped.  On the
+	 * Medusa this is always the case and there is nothing we can do
+	 * about this, so we just assume the smaller offset.  For the TT
+	 * we use the fact that in head.S we have set up a mapping
+	 * 0xFFxxxxxx -> 0x00xxxxxx, so that the first 16MB is accessible
+	 * in the last 16MB of the address space.
+	 */
+	tos_version = (MACH_IS_MEDUSA || MACH_IS_HADES) ?
+			0xfff : *(unsigned short *)0xff000002;
+	atari_rtc_year_offset = (tos_version < 0x306) ? 70 : 68;
 }
 
 #ifdef CONFIG_HEARTBEAT
-static void atari_heartbeat( int on )
+static void atari_heartbeat(int on)
 {
-    unsigned char tmp;
-    unsigned long flags;
+	unsigned char tmp;
+	unsigned long flags;
 
-    if (atari_dont_touch_floppy_select)
-	return;
+	if (atari_dont_touch_floppy_select)
+		return;
 
-    local_irq_save(flags);
-    sound_ym.rd_data_reg_sel = 14; /* Select PSG Port A */
-    tmp = sound_ym.rd_data_reg_sel;
-    sound_ym.wd_data = on ? (tmp & ~0x02) : (tmp | 0x02);
-    local_irq_restore(flags);
+	local_irq_save(flags);
+	sound_ym.rd_data_reg_sel = 14;	/* Select PSG Port A */
+	tmp = sound_ym.rd_data_reg_sel;
+	sound_ym.wd_data = on ? (tmp & ~0x02) : (tmp | 0x02);
+	local_irq_restore(flags);
 }
 #endif
 
@@ -526,180 +491,171 @@
 
 /* ++andreas: no need for complicated code, just depend on prefetch */
 
-static void atari_reset (void)
+static void atari_reset(void)
 {
-    long tc_val = 0;
-    long reset_addr;
+	long tc_val = 0;
+	long reset_addr;
 
-    /* On the Medusa, phys. 0x4 may contain garbage because it's no
-       ROM.  See above for explanation why we cannot use PTOV(4). */
-    reset_addr = MACH_IS_HADES ? 0x7fe00030 :
-                 MACH_IS_MEDUSA || MACH_IS_AB40 ? 0xe00030 :
-		 *(unsigned long *) 0xff000004;
+	/*
+	 * On the Medusa, phys. 0x4 may contain garbage because it's no
+	 * ROM.  See above for explanation why we cannot use PTOV(4).
+	 */
+	reset_addr = MACH_IS_HADES ? 0x7fe00030 :
+		     MACH_IS_MEDUSA || MACH_IS_AB40 ? 0xe00030 :
+		     *(unsigned long *) 0xff000004;
 
-    /* reset ACIA for switch off OverScan, if it's active */
-    if (atari_switches & ATARI_SWITCH_OVSC_IKBD)
-	acia.key_ctrl = ACIA_RESET;
-    if (atari_switches & ATARI_SWITCH_OVSC_MIDI)
-	acia.mid_ctrl = ACIA_RESET;
+	/* reset ACIA for switch off OverScan, if it's active */
+	if (atari_switches & ATARI_SWITCH_OVSC_IKBD)
+		acia.key_ctrl = ACIA_RESET;
+	if (atari_switches & ATARI_SWITCH_OVSC_MIDI)
+		acia.mid_ctrl = ACIA_RESET;
 
-    /* processor independent: turn off interrupts and reset the VBR;
-     * the caches must be left enabled, else prefetching the final jump
-     * instruction doesn't work. */
-    local_irq_disable();
-    __asm__ __volatile__
-	("moveq	#0,%/d0\n\t"
-	 "movec	%/d0,%/vbr"
-	 : : : "d0" );
+	/* processor independent: turn off interrupts and reset the VBR;
+	 * the caches must be left enabled, else prefetching the final jump
+	 * instruction doesn't work.
+	 */
+	local_irq_disable();
+	asm volatile ("movec	%0,%%vbr"
+			: : "d" (0));
 
-    if (CPU_IS_040_OR_060) {
-        unsigned long jmp_addr040 = virt_to_phys(&&jmp_addr_label040);
-	if (CPU_IS_060) {
-	    /* 68060: clear PCR to turn off superscalar operation */
-	    __asm__ __volatile__
-		("moveq	#0,%/d0\n\t"
-		 ".chip 68060\n\t"
-		 "movec %%d0,%%pcr\n\t"
-		 ".chip 68k"
-		 : : : "d0" );
-	}
+	if (CPU_IS_040_OR_060) {
+		unsigned long jmp_addr040 = virt_to_phys(&&jmp_addr_label040);
+		if (CPU_IS_060) {
+			/* 68060: clear PCR to turn off superscalar operation */
+			asm volatile ("\n"
+				"	.chip 68060\n"
+				"	movec %0,%%pcr\n"
+				"	.chip 68k"
+				: : "d" (0));
+		}
 
-        __asm__ __volatile__
-            ("movel    %0,%/d0\n\t"
-             "andl     #0xff000000,%/d0\n\t"
-             "orw      #0xe020,%/d0\n\t"   /* map 16 MB, enable, cacheable */
-             ".chip 68040\n\t"
-	     "movec    %%d0,%%itt0\n\t"
-             "movec    %%d0,%%dtt0\n\t"
-	     ".chip 68k\n\t"
-             "jmp   %0@\n\t"
-             : /* no outputs */
-             : "a" (jmp_addr040)
-             : "d0" );
-      jmp_addr_label040:
-        __asm__ __volatile__
-          ("moveq #0,%/d0\n\t"
-	   "nop\n\t"
-	   ".chip 68040\n\t"
-	   "cinva %%bc\n\t"
-	   "nop\n\t"
-	   "pflusha\n\t"
-	   "nop\n\t"
-	   "movec %%d0,%%tc\n\t"
-	   "nop\n\t"
-	   /* the following setup of transparent translations is needed on the
-	    * Afterburner040 to successfully reboot. Other machines shouldn't
-	    * care about a different tt regs setup, they also didn't care in
-	    * the past that the regs weren't turned off. */
-	   "movel #0xffc000,%%d0\n\t" /* whole insn space cacheable */
-	   "movec %%d0,%%itt0\n\t"
-	   "movec %%d0,%%itt1\n\t"
-	   "orw   #0x40,%/d0\n\t" /* whole data space non-cacheable/ser. */
-	   "movec %%d0,%%dtt0\n\t"
-	   "movec %%d0,%%dtt1\n\t"
-	   ".chip 68k\n\t"
-           "jmp %0@"
-           : /* no outputs */
-           : "a" (reset_addr)
-           : "d0");
-    }
-    else
-        __asm__ __volatile__
-            ("pmove %0@,%/tc\n\t"
-             "jmp %1@"
-             : /* no outputs */
-             : "a" (&tc_val), "a" (reset_addr));
+		asm volatile ("\n"
+			"	move.l	%0,%%d0\n"
+			"	and.l	#0xff000000,%%d0\n"
+			"	or.w	#0xe020,%%d0\n"   /* map 16 MB, enable, cacheable */
+			"	.chip	68040\n"
+			"	movec	%%d0,%%itt0\n"
+			"	movec	%%d0,%%dtt0\n"
+			"	.chip	68k\n"
+			"	jmp	%0@"
+			: : "a" (jmp_addr040)
+			: "d0");
+	jmp_addr_label040:
+		asm volatile ("\n"
+			"	moveq	#0,%%d0\n"
+			"	nop\n"
+			"	.chip	68040\n"
+			"	cinva	%%bc\n"
+			"	nop\n"
+			"	pflusha\n"
+			"	nop\n"
+			"	movec	%%d0,%%tc\n"
+			"	nop\n"
+			/* the following setup of transparent translations is needed on the
+			 * Afterburner040 to successfully reboot. Other machines shouldn't
+			 * care about a different tt regs setup, they also didn't care in
+			 * the past that the regs weren't turned off. */
+			"	move.l	#0xffc000,%%d0\n" /* whole insn space cacheable */
+			"	movec	%%d0,%%itt0\n"
+			"	movec	%%d0,%%itt1\n"
+			"	or.w	#0x40,%/d0\n" /* whole data space non-cacheable/ser. */
+			"	movec	%%d0,%%dtt0\n"
+			"	movec	%%d0,%%dtt1\n"
+			"	.chip	68k\n"
+			"	jmp	%0@"
+			: /* no outputs */
+			: "a" (reset_addr)
+			: "d0");
+	} else
+		asm volatile ("\n"
+			"	pmove	%0@,%%tc\n"
+			"	jmp	%1@"
+			: /* no outputs */
+			: "a" (&tc_val), "a" (reset_addr));
 }
 
 
 static void atari_get_model(char *model)
 {
-    strcpy(model, "Atari ");
-    switch (atari_mch_cookie >> 16) {
+	strcpy(model, "Atari ");
+	switch (atari_mch_cookie >> 16) {
 	case ATARI_MCH_ST:
-	    if (ATARIHW_PRESENT(MSTE_CLK))
-		strcat (model, "Mega ST");
-	    else
-		strcat (model, "ST");
-	    break;
+		if (ATARIHW_PRESENT(MSTE_CLK))
+			strcat(model, "Mega ST");
+		else
+			strcat(model, "ST");
+		break;
 	case ATARI_MCH_STE:
-	    if (MACH_IS_MSTE)
-		strcat (model, "Mega STE");
-	    else
-		strcat (model, "STE");
-	    break;
+		if (MACH_IS_MSTE)
+			strcat(model, "Mega STE");
+		else
+			strcat(model, "STE");
+		break;
 	case ATARI_MCH_TT:
-	    if (MACH_IS_MEDUSA)
-		/* Medusa has TT _MCH cookie */
-		strcat (model, "Medusa");
-	    else if (MACH_IS_HADES)
-		strcat(model, "Hades");
-	    else
-		strcat (model, "TT");
-	    break;
+		if (MACH_IS_MEDUSA)
+			/* Medusa has TT _MCH cookie */
+			strcat(model, "Medusa");
+		else if (MACH_IS_HADES)
+			strcat(model, "Hades");
+		else
+			strcat(model, "TT");
+		break;
 	case ATARI_MCH_FALCON:
-	    strcat (model, "Falcon");
-	    if (MACH_IS_AB40)
-		strcat (model, " (with Afterburner040)");
-	    break;
+		strcat(model, "Falcon");
+		if (MACH_IS_AB40)
+			strcat(model, " (with Afterburner040)");
+		break;
 	default:
-	    sprintf (model + strlen (model), "(unknown mach cookie 0x%lx)",
-		     atari_mch_cookie);
-	    break;
-    }
+		sprintf(model + strlen(model), "(unknown mach cookie 0x%lx)",
+			atari_mch_cookie);
+		break;
+	}
 }
 
 
 static int atari_get_hardware_list(char *buffer)
 {
-    int len = 0, i;
+	int len = 0, i;
 
-    for (i = 0; i < m68k_num_memory; i++)
-	len += sprintf (buffer+len, "\t%3ld MB at 0x%08lx (%s)\n",
-			m68k_memory[i].size >> 20, m68k_memory[i].addr,
-			(m68k_memory[i].addr & 0xff000000 ?
-			 "alternate RAM" : "ST-RAM"));
+	for (i = 0; i < m68k_num_memory; i++)
+		len += sprintf(buffer+len, "\t%3ld MB at 0x%08lx (%s)\n",
+				m68k_memory[i].size >> 20, m68k_memory[i].addr,
+				(m68k_memory[i].addr & 0xff000000 ?
+				 "alternate RAM" : "ST-RAM"));
 
-#define ATARIHW_ANNOUNCE(name,str)				\
-    if (ATARIHW_PRESENT(name))			\
-	len += sprintf (buffer + len, "\t%s\n", str)
+#define ATARIHW_ANNOUNCE(name, str)			\
+	if (ATARIHW_PRESENT(name))			\
+		len += sprintf(buffer + len, "\t%s\n", str)
 
-    len += sprintf (buffer + len, "Detected hardware:\n");
-    ATARIHW_ANNOUNCE(STND_SHIFTER, "ST Shifter");
-    ATARIHW_ANNOUNCE(EXTD_SHIFTER, "STe Shifter");
-    ATARIHW_ANNOUNCE(TT_SHIFTER, "TT Shifter");
-    ATARIHW_ANNOUNCE(VIDEL_SHIFTER, "Falcon Shifter");
-    ATARIHW_ANNOUNCE(YM_2149, "Programmable Sound Generator");
-    ATARIHW_ANNOUNCE(PCM_8BIT, "PCM 8 Bit Sound");
-    ATARIHW_ANNOUNCE(CODEC, "CODEC Sound");
-    ATARIHW_ANNOUNCE(TT_SCSI, "SCSI Controller NCR5380 (TT style)");
-    ATARIHW_ANNOUNCE(ST_SCSI, "SCSI Controller NCR5380 (Falcon style)");
-    ATARIHW_ANNOUNCE(ACSI, "ACSI Interface");
-    ATARIHW_ANNOUNCE(IDE, "IDE Interface");
-    ATARIHW_ANNOUNCE(FDCSPEED, "8/16 Mhz Switch for FDC");
-    ATARIHW_ANNOUNCE(ST_MFP, "Multi Function Peripheral MFP 68901");
-    ATARIHW_ANNOUNCE(TT_MFP, "Second Multi Function Peripheral MFP 68901");
-    ATARIHW_ANNOUNCE(SCC, "Serial Communications Controller SCC 8530");
-    ATARIHW_ANNOUNCE(ST_ESCC, "Extended Serial Communications Controller SCC 85230");
-    ATARIHW_ANNOUNCE(ANALOG_JOY, "Paddle Interface");
-    ATARIHW_ANNOUNCE(MICROWIRE, "MICROWIRE(tm) Interface");
-    ATARIHW_ANNOUNCE(STND_DMA, "DMA Controller (24 bit)");
-    ATARIHW_ANNOUNCE(EXTD_DMA, "DMA Controller (32 bit)");
-    ATARIHW_ANNOUNCE(SCSI_DMA, "DMA Controller for NCR5380");
-    ATARIHW_ANNOUNCE(SCC_DMA, "DMA Controller for SCC");
-    ATARIHW_ANNOUNCE(TT_CLK, "Clock Chip MC146818A");
-    ATARIHW_ANNOUNCE(MSTE_CLK, "Clock Chip RP5C15");
-    ATARIHW_ANNOUNCE(SCU, "System Control Unit");
-    ATARIHW_ANNOUNCE(BLITTER, "Blitter");
-    ATARIHW_ANNOUNCE(VME, "VME Bus");
-    ATARIHW_ANNOUNCE(DSP56K, "DSP56001 processor");
+	len += sprintf(buffer + len, "Detected hardware:\n");
+	ATARIHW_ANNOUNCE(STND_SHIFTER, "ST Shifter");
+	ATARIHW_ANNOUNCE(EXTD_SHIFTER, "STe Shifter");
+	ATARIHW_ANNOUNCE(TT_SHIFTER, "TT Shifter");
+	ATARIHW_ANNOUNCE(VIDEL_SHIFTER, "Falcon Shifter");
+	ATARIHW_ANNOUNCE(YM_2149, "Programmable Sound Generator");
+	ATARIHW_ANNOUNCE(PCM_8BIT, "PCM 8 Bit Sound");
+	ATARIHW_ANNOUNCE(CODEC, "CODEC Sound");
+	ATARIHW_ANNOUNCE(TT_SCSI, "SCSI Controller NCR5380 (TT style)");
+	ATARIHW_ANNOUNCE(ST_SCSI, "SCSI Controller NCR5380 (Falcon style)");
+	ATARIHW_ANNOUNCE(ACSI, "ACSI Interface");
+	ATARIHW_ANNOUNCE(IDE, "IDE Interface");
+	ATARIHW_ANNOUNCE(FDCSPEED, "8/16 Mhz Switch for FDC");
+	ATARIHW_ANNOUNCE(ST_MFP, "Multi Function Peripheral MFP 68901");
+	ATARIHW_ANNOUNCE(TT_MFP, "Second Multi Function Peripheral MFP 68901");
+	ATARIHW_ANNOUNCE(SCC, "Serial Communications Controller SCC 8530");
+	ATARIHW_ANNOUNCE(ST_ESCC, "Extended Serial Communications Controller SCC 85230");
+	ATARIHW_ANNOUNCE(ANALOG_JOY, "Paddle Interface");
+	ATARIHW_ANNOUNCE(MICROWIRE, "MICROWIRE(tm) Interface");
+	ATARIHW_ANNOUNCE(STND_DMA, "DMA Controller (24 bit)");
+	ATARIHW_ANNOUNCE(EXTD_DMA, "DMA Controller (32 bit)");
+	ATARIHW_ANNOUNCE(SCSI_DMA, "DMA Controller for NCR5380");
+	ATARIHW_ANNOUNCE(SCC_DMA, "DMA Controller for SCC");
+	ATARIHW_ANNOUNCE(TT_CLK, "Clock Chip MC146818A");
+	ATARIHW_ANNOUNCE(MSTE_CLK, "Clock Chip RP5C15");
+	ATARIHW_ANNOUNCE(SCU, "System Control Unit");
+	ATARIHW_ANNOUNCE(BLITTER, "Blitter");
+	ATARIHW_ANNOUNCE(VME, "VME Bus");
+	ATARIHW_ANNOUNCE(DSP56K, "DSP56001 processor");
 
-    return(len);
+	return len;
 }
-
-/*
- * Local variables:
- *  c-indent-level: 4
- *  tab-width: 8
- * End:
- */
diff --git a/arch/m68k/atari/debug.c b/arch/m68k/atari/debug.c
index 4ae0100..fbeed8c 100644
--- a/arch/m68k/atari/debug.c
+++ b/arch/m68k/atari/debug.c
@@ -19,8 +19,6 @@
 #include <asm/atarihw.h>
 #include <asm/atariints.h>
 
-extern char m68k_debug_device[];
-
 /* Flag that Modem1 port is already initialized and used */
 int atari_MFP_init_done;
 /* Flag that Modem1 port is already initialized and used */
@@ -30,317 +28,317 @@
 int atari_SCC_reset_done;
 
 static struct console atari_console_driver = {
-	.name =		"debug",
-	.flags =	CON_PRINTBUFFER,
-	.index =	-1,
+	.name	= "debug",
+	.flags	= CON_PRINTBUFFER,
+	.index	= -1,
 };
 
 
-static inline void ata_mfp_out (char c)
+static inline void ata_mfp_out(char c)
 {
-    while (!(mfp.trn_stat & 0x80)) /* wait for tx buf empty */
-	barrier ();
-    mfp.usart_dta = c;
+	while (!(mfp.trn_stat & 0x80))	/* wait for tx buf empty */
+		barrier();
+	mfp.usart_dta = c;
 }
 
-void atari_mfp_console_write (struct console *co, const char *str,
-			      unsigned int count)
+void atari_mfp_console_write(struct console *co, const char *str,
+			     unsigned int count)
 {
-    while (count--) {
-	if (*str == '\n')
-	    ata_mfp_out( '\r' );
-	ata_mfp_out( *str++ );
-    }
-}
-
-static inline void ata_scc_out (char c)
-{
-    do {
-	MFPDELAY();
-    } while (!(scc.cha_b_ctrl & 0x04)); /* wait for tx buf empty */
-    MFPDELAY();
-    scc.cha_b_data = c;
-}
-
-void atari_scc_console_write (struct console *co, const char *str,
-			      unsigned int count)
-{
-    while (count--) {
-	if (*str == '\n')
-	    ata_scc_out( '\r' );
-	ata_scc_out( *str++ );
-    }
-}
-
-static inline void ata_midi_out (char c)
-{
-    while (!(acia.mid_ctrl & ACIA_TDRE)) /* wait for tx buf empty */
-	barrier ();
-    acia.mid_data = c;
-}
-
-void atari_midi_console_write (struct console *co, const char *str,
-			       unsigned int count)
-{
-    while (count--) {
-	if (*str == '\n')
-	    ata_midi_out( '\r' );
-	ata_midi_out( *str++ );
-    }
-}
-
-static int ata_par_out (char c)
-{
-    unsigned char tmp;
-    /* This a some-seconds timeout in case no printer is connected */
-    unsigned long i = loops_per_jiffy > 1 ? loops_per_jiffy : 10000000/HZ;
-
-    while( (mfp.par_dt_reg & 1) && --i ) /* wait for BUSY == L */
-	;
-    if (!i) return( 0 );
-
-    sound_ym.rd_data_reg_sel = 15;  /* select port B */
-    sound_ym.wd_data = c;           /* put char onto port */
-    sound_ym.rd_data_reg_sel = 14;  /* select port A */
-    tmp = sound_ym.rd_data_reg_sel;
-    sound_ym.wd_data = tmp & ~0x20; /* set strobe L */
-    MFPDELAY();                     /* wait a bit */
-    sound_ym.wd_data = tmp | 0x20;  /* set strobe H */
-    return( 1 );
-}
-
-static void atari_par_console_write (struct console *co, const char *str,
-				     unsigned int count)
-{
-    static int printer_present = 1;
-
-    if (!printer_present)
-	return;
-
-    while (count--) {
-	if (*str == '\n')
-	    if (!ata_par_out( '\r' )) {
-		printer_present = 0;
-		return;
-	    }
-	if (!ata_par_out( *str++ )) {
-	    printer_present = 0;
-	    return;
+	while (count--) {
+		if (*str == '\n')
+			ata_mfp_out('\r');
+		ata_mfp_out(*str++);
 	}
-    }
+}
+
+static inline void ata_scc_out(char c)
+{
+	do {
+		MFPDELAY();
+	} while (!(scc.cha_b_ctrl & 0x04)); /* wait for tx buf empty */
+	MFPDELAY();
+	scc.cha_b_data = c;
+}
+
+void atari_scc_console_write(struct console *co, const char *str,
+			     unsigned int count)
+{
+	while (count--) {
+		if (*str == '\n')
+			ata_scc_out('\r');
+		ata_scc_out(*str++);
+	}
+}
+
+static inline void ata_midi_out(char c)
+{
+	while (!(acia.mid_ctrl & ACIA_TDRE))	/* wait for tx buf empty */
+		barrier();
+	acia.mid_data = c;
+}
+
+void atari_midi_console_write(struct console *co, const char *str,
+			      unsigned int count)
+{
+	while (count--) {
+		if (*str == '\n')
+			ata_midi_out('\r');
+		ata_midi_out(*str++);
+	}
+}
+
+static int ata_par_out(char c)
+{
+	unsigned char tmp;
+	/* This a some-seconds timeout in case no printer is connected */
+	unsigned long i = loops_per_jiffy > 1 ? loops_per_jiffy : 10000000/HZ;
+
+	while ((mfp.par_dt_reg & 1) && --i) /* wait for BUSY == L */
+		;
+	if (!i)
+		return 0;
+
+	sound_ym.rd_data_reg_sel = 15;	/* select port B */
+	sound_ym.wd_data = c;		/* put char onto port */
+	sound_ym.rd_data_reg_sel = 14;	/* select port A */
+	tmp = sound_ym.rd_data_reg_sel;
+	sound_ym.wd_data = tmp & ~0x20;	/* set strobe L */
+	MFPDELAY();			/* wait a bit */
+	sound_ym.wd_data = tmp | 0x20;	/* set strobe H */
+	return 1;
+}
+
+static void atari_par_console_write(struct console *co, const char *str,
+				    unsigned int count)
+{
+	static int printer_present = 1;
+
+	if (!printer_present)
+		return;
+
+	while (count--) {
+		if (*str == '\n') {
+			if (!ata_par_out('\r')) {
+				printer_present = 0;
+				return;
+			}
+		}
+		if (!ata_par_out(*str++)) {
+			printer_present = 0;
+			return;
+		}
+	}
 }
 
 #ifdef CONFIG_SERIAL_CONSOLE
 int atari_mfp_console_wait_key(struct console *co)
 {
-    while( !(mfp.rcv_stat & 0x80) ) /* wait for rx buf filled */
-	barrier();
-    return( mfp.usart_dta );
+	while (!(mfp.rcv_stat & 0x80))	/* wait for rx buf filled */
+		barrier();
+	return mfp.usart_dta;
 }
 
 int atari_scc_console_wait_key(struct console *co)
 {
-    do {
+	do {
+		MFPDELAY();
+	} while (!(scc.cha_b_ctrl & 0x01)); /* wait for rx buf filled */
 	MFPDELAY();
-    } while( !(scc.cha_b_ctrl & 0x01) ); /* wait for rx buf filled */
-    MFPDELAY();
-    return( scc.cha_b_data );
+	return scc.cha_b_data;
 }
 
 int atari_midi_console_wait_key(struct console *co)
 {
-    while( !(acia.mid_ctrl & ACIA_RDRF) ) /* wait for rx buf filled */
-	barrier();
-    return( acia.mid_data );
+	while (!(acia.mid_ctrl & ACIA_RDRF)) /* wait for rx buf filled */
+		barrier();
+	return acia.mid_data;
 }
 #endif
 
-/* The following two functions do a quick'n'dirty initialization of the MFP or
+/*
+ * The following two functions do a quick'n'dirty initialization of the MFP or
  * SCC serial ports. They're used by the debugging interface, kgdb, and the
- * serial console code. */
+ * serial console code.
+ */
 #ifndef CONFIG_SERIAL_CONSOLE
-static void __init atari_init_mfp_port( int cflag )
+static void __init atari_init_mfp_port(int cflag)
 #else
-void atari_init_mfp_port( int cflag )
+void atari_init_mfp_port(int cflag)
 #endif
 {
-    /* timer values for 1200...115200 bps; > 38400 select 110, 134, or 150
-     * bps, resp., and work only correct if there's a RSVE or RSSPEED */
-    static int baud_table[9] = { 16, 11, 8, 4, 2, 1, 175, 143, 128 };
-    int baud = cflag & CBAUD;
-    int parity = (cflag & PARENB) ? ((cflag & PARODD) ? 0x04 : 0x06) : 0;
-    int csize = ((cflag & CSIZE) == CS7) ? 0x20 : 0x00;
+	/*
+	 * timer values for 1200...115200 bps; > 38400 select 110, 134, or 150
+	 * bps, resp., and work only correct if there's a RSVE or RSSPEED
+	 */
+	static int baud_table[9] = { 16, 11, 8, 4, 2, 1, 175, 143, 128 };
+	int baud = cflag & CBAUD;
+	int parity = (cflag & PARENB) ? ((cflag & PARODD) ? 0x04 : 0x06) : 0;
+	int csize = ((cflag & CSIZE) == CS7) ? 0x20 : 0x00;
 
-    if (cflag & CBAUDEX)
-	baud += B38400;
-    if (baud < B1200 || baud > B38400+2)
-	baud = B9600; /* use default 9600bps for non-implemented rates */
-    baud -= B1200; /* baud_table[] starts at 1200bps */
+	if (cflag & CBAUDEX)
+		baud += B38400;
+	if (baud < B1200 || baud > B38400+2)
+		baud = B9600;		/* use default 9600bps for non-implemented rates */
+	baud -= B1200;			/* baud_table[] starts at 1200bps */
 
-    mfp.trn_stat &= ~0x01; /* disable TX */
-    mfp.usart_ctr = parity | csize | 0x88; /* 1:16 clk mode, 1 stop bit */
-    mfp.tim_ct_cd &= 0x70;  /* stop timer D */
-    mfp.tim_dt_d = baud_table[baud];
-    mfp.tim_ct_cd |= 0x01;  /* start timer D, 1:4 */
-    mfp.trn_stat |= 0x01;  /* enable TX */
+	mfp.trn_stat &= ~0x01;		/* disable TX */
+	mfp.usart_ctr = parity | csize | 0x88; /* 1:16 clk mode, 1 stop bit */
+	mfp.tim_ct_cd &= 0x70;		/* stop timer D */
+	mfp.tim_dt_d = baud_table[baud];
+	mfp.tim_ct_cd |= 0x01;		/* start timer D, 1:4 */
+	mfp.trn_stat |= 0x01;		/* enable TX */
 
-    atari_MFP_init_done = 1;
+	atari_MFP_init_done = 1;
 }
 
-#define SCC_WRITE(reg,val)				\
-    do {						\
-	scc.cha_b_ctrl = (reg);				\
-	MFPDELAY();					\
-	scc.cha_b_ctrl = (val);				\
-	MFPDELAY();					\
-    } while(0)
+#define SCC_WRITE(reg, val)				\
+	do {						\
+		scc.cha_b_ctrl = (reg);			\
+		MFPDELAY();				\
+		scc.cha_b_ctrl = (val);			\
+		MFPDELAY();				\
+	} while (0)
 
 /* loops_per_jiffy isn't initialized yet, so we can't use udelay(). This does a
  * delay of ~ 60us. */
-#define LONG_DELAY()				\
-    do {					\
-	int i;					\
-	for( i = 100; i > 0; --i )		\
-	    MFPDELAY();				\
-    } while(0)
+#define LONG_DELAY()					\
+	do {						\
+		int i;					\
+		for (i = 100; i > 0; --i)		\
+			MFPDELAY();			\
+	} while (0)
 
 #ifndef CONFIG_SERIAL_CONSOLE
-static void __init atari_init_scc_port( int cflag )
+static void __init atari_init_scc_port(int cflag)
 #else
-void atari_init_scc_port( int cflag )
+void atari_init_scc_port(int cflag)
 #endif
 {
-    extern int atari_SCC_reset_done;
-    static int clksrc_table[9] =
-	/* reg 11: 0x50 = BRG, 0x00 = RTxC, 0x28 = TRxC */
-	{ 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x00, 0x00 };
-    static int brgsrc_table[9] =
-	/* reg 14: 0 = RTxC, 2 = PCLK */
-	{ 2, 2, 2, 2, 2, 2, 0, 2, 2 };
-    static int clkmode_table[9] =
-	/* reg 4: 0x40 = x16, 0x80 = x32, 0xc0 = x64 */
-	{ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0xc0, 0x80 };
-    static int div_table[9] =
-	/* reg12 (BRG low) */
-	{ 208, 138, 103, 50, 24, 11, 1, 0, 0 };
+	extern int atari_SCC_reset_done;
+	static int clksrc_table[9] =
+		/* reg 11: 0x50 = BRG, 0x00 = RTxC, 0x28 = TRxC */
+		{ 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x00, 0x00 };
+	static int brgsrc_table[9] =
+		/* reg 14: 0 = RTxC, 2 = PCLK */
+		{ 2, 2, 2, 2, 2, 2, 0, 2, 2 };
+	static int clkmode_table[9] =
+		/* reg 4: 0x40 = x16, 0x80 = x32, 0xc0 = x64 */
+		{ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0xc0, 0x80 };
+	static int div_table[9] =
+		/* reg12 (BRG low) */
+		{ 208, 138, 103, 50, 24, 11, 1, 0, 0 };
 
-    int baud = cflag & CBAUD;
-    int clksrc, clkmode, div, reg3, reg5;
+	int baud = cflag & CBAUD;
+	int clksrc, clkmode, div, reg3, reg5;
 
-    if (cflag & CBAUDEX)
-	baud += B38400;
-    if (baud < B1200 || baud > B38400+2)
-	baud = B9600; /* use default 9600bps for non-implemented rates */
-    baud -= B1200; /* tables starts at 1200bps */
+	if (cflag & CBAUDEX)
+		baud += B38400;
+	if (baud < B1200 || baud > B38400+2)
+		baud = B9600;		/* use default 9600bps for non-implemented rates */
+	baud -= B1200;			/* tables starts at 1200bps */
 
-    clksrc  = clksrc_table[baud];
-    clkmode = clkmode_table[baud];
-    div     = div_table[baud];
-    if (ATARIHW_PRESENT(TT_MFP) && baud >= 6) {
-	/* special treatment for TT, where rates >= 38400 are done via TRxC */
-	clksrc = 0x28; /* TRxC */
-	clkmode = baud == 6 ? 0xc0 :
-		  baud == 7 ? 0x80 : /* really 76800bps */
-			      0x40;  /* really 153600bps */
-	div = 0;
-    }
+	clksrc  = clksrc_table[baud];
+	clkmode = clkmode_table[baud];
+	div     = div_table[baud];
+	if (ATARIHW_PRESENT(TT_MFP) && baud >= 6) {
+		/* special treatment for TT, where rates >= 38400 are done via TRxC */
+		clksrc = 0x28;		/* TRxC */
+		clkmode = baud == 6 ? 0xc0 :
+			  baud == 7 ? 0x80 : /* really 76800bps */
+				      0x40;  /* really 153600bps */
+		div = 0;
+	}
 
-    reg3 = (cflag & CSIZE) == CS8 ? 0xc0 : 0x40;
-    reg5 = (cflag & CSIZE) == CS8 ? 0x60 : 0x20 | 0x82 /* assert DTR/RTS */;
+	reg3 = (cflag & CSIZE) == CS8 ? 0xc0 : 0x40;
+	reg5 = (cflag & CSIZE) == CS8 ? 0x60 : 0x20 | 0x82 /* assert DTR/RTS */;
 
-    (void)scc.cha_b_ctrl;	/* reset reg pointer */
-    SCC_WRITE( 9, 0xc0 );	/* reset */
-    LONG_DELAY();		/* extra delay after WR9 access */
-    SCC_WRITE( 4, (cflag & PARENB) ? ((cflag & PARODD) ? 0x01 : 0x03) : 0 |
-		  0x04 /* 1 stopbit */ |
-		  clkmode );
-    SCC_WRITE( 3, reg3 );
-    SCC_WRITE( 5, reg5 );
-    SCC_WRITE( 9, 0 );		/* no interrupts */
-    LONG_DELAY();		/* extra delay after WR9 access */
-    SCC_WRITE( 10, 0 );		/* NRZ mode */
-    SCC_WRITE( 11, clksrc );	/* main clock source */
-    SCC_WRITE( 12, div );	/* BRG value */
-    SCC_WRITE( 13, 0 );		/* BRG high byte */
-    SCC_WRITE( 14, brgsrc_table[baud] );
-    SCC_WRITE( 14, brgsrc_table[baud] | (div ? 1 : 0) );
-    SCC_WRITE( 3, reg3 | 1 );
-    SCC_WRITE( 5, reg5 | 8 );
+	(void)scc.cha_b_ctrl;		/* reset reg pointer */
+	SCC_WRITE(9, 0xc0);		/* reset */
+	LONG_DELAY();			/* extra delay after WR9 access */
+	SCC_WRITE(4, (cflag & PARENB) ? ((cflag & PARODD) ? 0x01 : 0x03)
+				      : 0 | 0x04 /* 1 stopbit */ | clkmode);
+	SCC_WRITE(3, reg3);
+	SCC_WRITE(5, reg5);
+	SCC_WRITE(9, 0);		/* no interrupts */
+	LONG_DELAY();			/* extra delay after WR9 access */
+	SCC_WRITE(10, 0);		/* NRZ mode */
+	SCC_WRITE(11, clksrc);		/* main clock source */
+	SCC_WRITE(12, div);		/* BRG value */
+	SCC_WRITE(13, 0);		/* BRG high byte */
+	SCC_WRITE(14, brgsrc_table[baud]);
+	SCC_WRITE(14, brgsrc_table[baud] | (div ? 1 : 0));
+	SCC_WRITE(3, reg3 | 1);
+	SCC_WRITE(5, reg5 | 8);
 
-    atari_SCC_reset_done = 1;
-    atari_SCC_init_done = 1;
+	atari_SCC_reset_done = 1;
+	atari_SCC_init_done = 1;
 }
 
 #ifndef CONFIG_SERIAL_CONSOLE
-static void __init atari_init_midi_port( int cflag )
+static void __init atari_init_midi_port(int cflag)
 #else
-void atari_init_midi_port( int cflag )
+void atari_init_midi_port(int cflag)
 #endif
 {
-    int baud = cflag & CBAUD;
-    int csize = ((cflag & CSIZE) == CS8) ? 0x10 : 0x00;
-    /* warning 7N1 isn't possible! (instead 7O2 is used...) */
-    int parity = (cflag & PARENB) ? ((cflag & PARODD) ? 0x0c : 0x08) : 0x04;
-    int div;
+	int baud = cflag & CBAUD;
+	int csize = ((cflag & CSIZE) == CS8) ? 0x10 : 0x00;
+	/* warning 7N1 isn't possible! (instead 7O2 is used...) */
+	int parity = (cflag & PARENB) ? ((cflag & PARODD) ? 0x0c : 0x08) : 0x04;
+	int div;
 
-    /* 4800 selects 7812.5, 115200 selects 500000, all other (incl. 9600 as
-     * default) the standard MIDI speed 31250. */
-    if (cflag & CBAUDEX)
-	baud += B38400;
-    if (baud == B4800)
-	div = ACIA_DIV64; /* really 7812.5 bps */
-    else if (baud == B38400+2 /* 115200 */)
-	div = ACIA_DIV1; /* really 500 kbps (does that work??) */
-    else
-	div = ACIA_DIV16; /* 31250 bps, standard for MIDI */
+	/* 4800 selects 7812.5, 115200 selects 500000, all other (incl. 9600 as
+	 * default) the standard MIDI speed 31250. */
+	if (cflag & CBAUDEX)
+		baud += B38400;
+	if (baud == B4800)
+		div = ACIA_DIV64;	/* really 7812.5 bps */
+	else if (baud == B38400+2 /* 115200 */)
+		div = ACIA_DIV1;	/* really 500 kbps (does that work??) */
+	else
+		div = ACIA_DIV16;	/* 31250 bps, standard for MIDI */
 
-    /* RTS low, ints disabled */
-    acia.mid_ctrl = div | csize | parity |
+	/* RTS low, ints disabled */
+	acia.mid_ctrl = div | csize | parity |
 		    ((atari_switches & ATARI_SWITCH_MIDI) ?
 		     ACIA_RHTID : ACIA_RLTID);
 }
 
-void __init atari_debug_init(void)
+static int __init atari_debug_setup(char *arg)
 {
-    if (!strcmp( m68k_debug_device, "ser" )) {
-	/* defaults to ser2 for a Falcon and ser1 otherwise */
-	strcpy( m68k_debug_device, MACH_IS_FALCON ? "ser2" : "ser1" );
+	if (!MACH_IS_ATARI)
+		return 0;
 
-    }
+	if (!strcmp(arg, "ser"))
+		/* defaults to ser2 for a Falcon and ser1 otherwise */
+		arg = MACH_IS_FALCON ? "ser2" : "ser1";
 
-    if (!strcmp( m68k_debug_device, "ser1" )) {
-	/* ST-MFP Modem1 serial port */
-	atari_init_mfp_port( B9600|CS8 );
-	atari_console_driver.write = atari_mfp_console_write;
-    }
-    else if (!strcmp( m68k_debug_device, "ser2" )) {
-	/* SCC Modem2 serial port */
-	atari_init_scc_port( B9600|CS8 );
-	atari_console_driver.write = atari_scc_console_write;
-    }
-    else if (!strcmp( m68k_debug_device, "midi" )) {
-	/* MIDI port */
-	atari_init_midi_port( B9600|CS8 );
-	atari_console_driver.write = atari_midi_console_write;
-    }
-    else if (!strcmp( m68k_debug_device, "par" )) {
-	/* parallel printer */
-	atari_turnoff_irq( IRQ_MFP_BUSY ); /* avoid ints */
-	sound_ym.rd_data_reg_sel = 7;  /* select mixer control */
-	sound_ym.wd_data = 0xff;       /* sound off, ports are output */
-	sound_ym.rd_data_reg_sel = 15; /* select port B */
-	sound_ym.wd_data = 0;          /* no char */
-	sound_ym.rd_data_reg_sel = 14; /* select port A */
-	sound_ym.wd_data = sound_ym.rd_data_reg_sel | 0x20; /* strobe H */
-	atari_console_driver.write = atari_par_console_write;
-    }
-    if (atari_console_driver.write)
-	register_console(&atari_console_driver);
+	if (!strcmp(arg, "ser1")) {
+		/* ST-MFP Modem1 serial port */
+		atari_init_mfp_port(B9600|CS8);
+		atari_console_driver.write = atari_mfp_console_write;
+	} else if (!strcmp(arg, "ser2")) {
+		/* SCC Modem2 serial port */
+		atari_init_scc_port(B9600|CS8);
+		atari_console_driver.write = atari_scc_console_write;
+	} else if (!strcmp(arg, "midi")) {
+		/* MIDI port */
+		atari_init_midi_port(B9600|CS8);
+		atari_console_driver.write = atari_midi_console_write;
+	} else if (!strcmp(arg, "par")) {
+		/* parallel printer */
+		atari_turnoff_irq(IRQ_MFP_BUSY); /* avoid ints */
+		sound_ym.rd_data_reg_sel = 7;	/* select mixer control */
+		sound_ym.wd_data = 0xff;	/* sound off, ports are output */
+		sound_ym.rd_data_reg_sel = 15;	/* select port B */
+		sound_ym.wd_data = 0;		/* no char */
+		sound_ym.rd_data_reg_sel = 14;	/* select port A */
+		sound_ym.wd_data = sound_ym.rd_data_reg_sel | 0x20; /* strobe H */
+		atari_console_driver.write = atari_par_console_write;
+	}
+	if (atari_console_driver.write)
+		register_console(&atari_console_driver);
+
+	return 0;
 }
 
-/*
- * Local variables:
- *  c-indent-level: 4
- *  tab-width: 8
- * End:
- */
+early_param("debug", atari_debug_setup);
diff --git a/arch/m68k/kernel/entry.S b/arch/m68k/kernel/entry.S
index 222ce42..e162ee68 100644
--- a/arch/m68k/kernel/entry.S
+++ b/arch/m68k/kernel/entry.S
@@ -692,7 +692,7 @@
 	.long sys_tgkill	/* 265 */
 	.long sys_utimes
 	.long sys_fadvise64_64
-	.long sys_mbind	
+	.long sys_mbind
 	.long sys_get_mempolicy
 	.long sys_set_mempolicy	/* 270 */
 	.long sys_mq_open
diff --git a/arch/m68k/kernel/head.S b/arch/m68k/kernel/head.S
index 6739e87..05741f2 100644
--- a/arch/m68k/kernel/head.S
+++ b/arch/m68k/kernel/head.S
@@ -3195,7 +3195,7 @@
 	jbra	L(serial_putc_done)
 3:
 #endif
-	
+
 L(serial_putc_done):
 func_return	serial_putc
 
diff --git a/arch/m68k/kernel/setup.c b/arch/m68k/kernel/setup.c
index 42b8fd0..6103193 100644
--- a/arch/m68k/kernel/setup.c
+++ b/arch/m68k/kernel/setup.c
@@ -71,9 +71,6 @@
 
 static char m68k_command_line[CL_SIZE];
 
-char m68k_debug_device[6] = "";
-EXPORT_SYMBOL(m68k_debug_device);
-
 void (*mach_sched_init) (irq_handler_t handler) __initdata = NULL;
 /* machine dependent irq functions */
 void (*mach_init_IRQ) (void) __initdata = NULL;
@@ -133,78 +130,78 @@
 extern void config_q40(void);
 extern void config_sun3x(void);
 
-extern void mac_debugging_short (int, short);
-extern void mac_debugging_long  (int, long);
-
 #define MASK_256K 0xfffc0000
 
 extern void paging_init(void);
 
 static void __init m68k_parse_bootinfo(const struct bi_record *record)
 {
-    while (record->tag != BI_LAST) {
-	int unknown = 0;
-	const unsigned long *data = record->data;
-	switch (record->tag) {
-	    case BI_MACHTYPE:
-	    case BI_CPUTYPE:
-	    case BI_FPUTYPE:
-	    case BI_MMUTYPE:
-		/* Already set up by head.S */
-		break;
+	while (record->tag != BI_LAST) {
+		int unknown = 0;
+		const unsigned long *data = record->data;
 
-	    case BI_MEMCHUNK:
-		if (m68k_num_memory < NUM_MEMINFO) {
-		    m68k_memory[m68k_num_memory].addr = data[0];
-		    m68k_memory[m68k_num_memory].size = data[1];
-		    m68k_num_memory++;
-		} else
-		    printk("m68k_parse_bootinfo: too many memory chunks\n");
-		break;
+		switch (record->tag) {
+		case BI_MACHTYPE:
+		case BI_CPUTYPE:
+		case BI_FPUTYPE:
+		case BI_MMUTYPE:
+			/* Already set up by head.S */
+			break;
 
-	    case BI_RAMDISK:
-		m68k_ramdisk.addr = data[0];
-		m68k_ramdisk.size = data[1];
-		break;
+		case BI_MEMCHUNK:
+			if (m68k_num_memory < NUM_MEMINFO) {
+				m68k_memory[m68k_num_memory].addr = data[0];
+				m68k_memory[m68k_num_memory].size = data[1];
+				m68k_num_memory++;
+			} else
+				printk("m68k_parse_bootinfo: too many memory chunks\n");
+			break;
 
-	    case BI_COMMAND_LINE:
-		strlcpy(m68k_command_line, (const char *)data, sizeof(m68k_command_line));
-		break;
+		case BI_RAMDISK:
+			m68k_ramdisk.addr = data[0];
+			m68k_ramdisk.size = data[1];
+			break;
 
-	    default:
-		if (MACH_IS_AMIGA)
-		    unknown = amiga_parse_bootinfo(record);
-		else if (MACH_IS_ATARI)
-		    unknown = atari_parse_bootinfo(record);
-		else if (MACH_IS_MAC)
-		    unknown = mac_parse_bootinfo(record);
-		else if (MACH_IS_Q40)
-		    unknown = q40_parse_bootinfo(record);
-		else if (MACH_IS_BVME6000)
-		    unknown = bvme6000_parse_bootinfo(record);
-		else if (MACH_IS_MVME16x)
-		    unknown = mvme16x_parse_bootinfo(record);
-		else if (MACH_IS_MVME147)
-		    unknown = mvme147_parse_bootinfo(record);
-		else if (MACH_IS_HP300)
-		    unknown = hp300_parse_bootinfo(record);
-		else
-		    unknown = 1;
+		case BI_COMMAND_LINE:
+			strlcpy(m68k_command_line, (const char *)data,
+				sizeof(m68k_command_line));
+			break;
+
+		default:
+			if (MACH_IS_AMIGA)
+				unknown = amiga_parse_bootinfo(record);
+			else if (MACH_IS_ATARI)
+				unknown = atari_parse_bootinfo(record);
+			else if (MACH_IS_MAC)
+				unknown = mac_parse_bootinfo(record);
+			else if (MACH_IS_Q40)
+				unknown = q40_parse_bootinfo(record);
+			else if (MACH_IS_BVME6000)
+				unknown = bvme6000_parse_bootinfo(record);
+			else if (MACH_IS_MVME16x)
+				unknown = mvme16x_parse_bootinfo(record);
+			else if (MACH_IS_MVME147)
+				unknown = mvme147_parse_bootinfo(record);
+			else if (MACH_IS_HP300)
+				unknown = hp300_parse_bootinfo(record);
+			else
+				unknown = 1;
+		}
+		if (unknown)
+			printk("m68k_parse_bootinfo: unknown tag 0x%04x ignored\n",
+			       record->tag);
+		record = (struct bi_record *)((unsigned long)record +
+					      record->size);
 	}
-	if (unknown)
-	    printk("m68k_parse_bootinfo: unknown tag 0x%04x ignored\n",
-		   record->tag);
-	record = (struct bi_record *)((unsigned long)record+record->size);
-    }
 
-    m68k_realnum_memory = m68k_num_memory;
+	m68k_realnum_memory = m68k_num_memory;
 #ifdef CONFIG_SINGLE_MEMORY_CHUNK
-    if (m68k_num_memory > 1) {
-	printk("Ignoring last %i chunks of physical memory\n",
-	       (m68k_num_memory - 1));
-	m68k_num_memory = 1;
-    }
-    m68k_memoffset = m68k_memory[0].addr-PAGE_OFFSET;
+	if (m68k_num_memory > 1) {
+		printk("Ignoring last %i chunks of physical memory\n",
+		       (m68k_num_memory - 1));
+		m68k_num_memory = 1;
+	}
+	m68k_memoffset = m68k_memory[0].addr-PAGE_OFFSET;
 #endif
 }
 
@@ -215,7 +212,6 @@
 	unsigned long endmem, startmem;
 #endif
 	int i;
-	char *p, *q;
 
 	/* The bootinfo is located right after the kernel bss */
 	m68k_parse_bootinfo((const struct bi_record *)&_end);
@@ -234,7 +230,7 @@
 	/* clear the fpu if we have one */
 	if (m68k_fputype & (FPU_68881|FPU_68882|FPU_68040|FPU_68060)) {
 		volatile int zero = 0;
-		asm __volatile__ ("frestore %0" : : "m" (zero));
+		asm volatile ("frestore %0" : : "m" (zero));
 	}
 #endif
 
@@ -258,37 +254,7 @@
 	*cmdline_p = m68k_command_line;
 	memcpy(boot_command_line, *cmdline_p, CL_SIZE);
 
-	/* Parse the command line for arch-specific options.
-	 * For the m68k, this is currently only "debug=xxx" to enable printing
-	 * certain kernel messages to some machine-specific device.
-	 */
-	for( p = *cmdline_p; p && *p; ) {
-	    i = 0;
-	    if (!strncmp( p, "debug=", 6 )) {
-		strlcpy( m68k_debug_device, p+6, sizeof(m68k_debug_device) );
-		if ((q = strchr( m68k_debug_device, ' ' ))) *q = 0;
-		i = 1;
-	    }
-#ifdef CONFIG_ATARI
-	    /* This option must be parsed very early */
-	    if (!strncmp( p, "switches=", 9 )) {
-		extern void atari_switches_setup( const char *, int );
-		atari_switches_setup( p+9, (q = strchr( p+9, ' ' )) ?
-				           (q - (p+9)) : strlen(p+9) );
-		i = 1;
-	    }
-#endif
-
-	    if (i) {
-		/* option processed, delete it */
-		if ((q = strchr( p, ' ' )))
-		    strcpy( p, q+1 );
-		else
-		    *p = 0;
-	    } else {
-		if ((p = strchr( p, ' ' ))) ++p;
-	    }
-	}
+	parse_early_param();
 
 #ifdef CONFIG_DUMMY_CONSOLE
 	conswitchp = &dummy_con;
@@ -296,62 +262,62 @@
 
 	switch (m68k_machtype) {
 #ifdef CONFIG_AMIGA
-	    case MACH_AMIGA:
+	case MACH_AMIGA:
 		config_amiga();
 		break;
 #endif
 #ifdef CONFIG_ATARI
-	    case MACH_ATARI:
+	case MACH_ATARI:
 		config_atari();
 		break;
 #endif
 #ifdef CONFIG_MAC
-	    case MACH_MAC:
+	case MACH_MAC:
 		config_mac();
 		break;
 #endif
 #ifdef CONFIG_SUN3
-	    case MACH_SUN3:
+	case MACH_SUN3:
 		config_sun3();
 		break;
 #endif
 #ifdef CONFIG_APOLLO
-	    case MACH_APOLLO:
+	case MACH_APOLLO:
 		config_apollo();
 		break;
 #endif
 #ifdef CONFIG_MVME147
-	    case MACH_MVME147:
+	case MACH_MVME147:
 		config_mvme147();
 		break;
 #endif
 #ifdef CONFIG_MVME16x
-	    case MACH_MVME16x:
+	case MACH_MVME16x:
 		config_mvme16x();
 		break;
 #endif
 #ifdef CONFIG_BVME6000
-	    case MACH_BVME6000:
+	case MACH_BVME6000:
 		config_bvme6000();
 		break;
 #endif
 #ifdef CONFIG_HP300
-	    case MACH_HP300:
+	case MACH_HP300:
 		config_hp300();
 		break;
 #endif
 #ifdef CONFIG_Q40
-	    case MACH_Q40:
-	        config_q40();
+	case MACH_Q40:
+		config_q40();
 		break;
 #endif
 #ifdef CONFIG_SUN3X
-	    case MACH_SUN3X:
+	case MACH_SUN3X:
 		config_sun3x();
 		break;
 #endif
-	    default:
-		panic ("No configuration setup");
+	default:
+		panic("No configuration setup");
 	}
 
 #ifndef CONFIG_SUN3
@@ -380,7 +346,7 @@
 		reserve_bootmem(m68k_ramdisk.addr, m68k_ramdisk.size);
 		initrd_start = (unsigned long)phys_to_virt(m68k_ramdisk.addr);
 		initrd_end = initrd_start + m68k_ramdisk.size;
-		printk ("initrd: %08lx - %08lx\n", initrd_start, initrd_end);
+		printk("initrd: %08lx - %08lx\n", initrd_start, initrd_end);
 	}
 #endif
 
@@ -402,18 +368,18 @@
 #if defined(CONFIG_ISA) && defined(MULTI_ISA)
 #if defined(CONFIG_Q40)
 	if (MACH_IS_Q40) {
-	    isa_type = Q40_ISA;
-	    isa_sex = 0;
+		isa_type = Q40_ISA;
+		isa_sex = 0;
 	}
 #elif defined(CONFIG_GG2)
-	if (MACH_IS_AMIGA && AMIGAHW_PRESENT(GG2_ISA)){
-	    isa_type = GG2_ISA;
-	    isa_sex = 0;
+	if (MACH_IS_AMIGA && AMIGAHW_PRESENT(GG2_ISA)) {
+		isa_type = GG2_ISA;
+		isa_sex = 0;
 	}
 #elif defined(CONFIG_AMIGA_PCMCIA)
-	if (MACH_IS_AMIGA && AMIGAHW_PRESENT(PCMCIA)){
-	    isa_type = AG_ISA;
-	    isa_sex = 1;
+	if (MACH_IS_AMIGA && AMIGAHW_PRESENT(PCMCIA)) {
+		isa_type = AG_ISA;
+		isa_sex = 1;
 	}
 #endif
 #endif
@@ -421,66 +387,66 @@
 
 static int show_cpuinfo(struct seq_file *m, void *v)
 {
-    const char *cpu, *mmu, *fpu;
-    unsigned long clockfreq, clockfactor;
+	const char *cpu, *mmu, *fpu;
+	unsigned long clockfreq, clockfactor;
 
 #define LOOP_CYCLES_68020	(8)
 #define LOOP_CYCLES_68030	(8)
 #define LOOP_CYCLES_68040	(3)
 #define LOOP_CYCLES_68060	(1)
 
-    if (CPU_IS_020) {
-	cpu = "68020";
-	clockfactor = LOOP_CYCLES_68020;
-    } else if (CPU_IS_030) {
-	cpu = "68030";
-	clockfactor = LOOP_CYCLES_68030;
-    } else if (CPU_IS_040) {
-	cpu = "68040";
-	clockfactor = LOOP_CYCLES_68040;
-    } else if (CPU_IS_060) {
-	cpu = "68060";
-	clockfactor = LOOP_CYCLES_68060;
-    } else {
-	cpu = "680x0";
-	clockfactor = 0;
-    }
+	if (CPU_IS_020) {
+		cpu = "68020";
+		clockfactor = LOOP_CYCLES_68020;
+	} else if (CPU_IS_030) {
+		cpu = "68030";
+		clockfactor = LOOP_CYCLES_68030;
+	} else if (CPU_IS_040) {
+		cpu = "68040";
+		clockfactor = LOOP_CYCLES_68040;
+	} else if (CPU_IS_060) {
+		cpu = "68060";
+		clockfactor = LOOP_CYCLES_68060;
+	} else {
+		cpu = "680x0";
+		clockfactor = 0;
+	}
 
 #ifdef CONFIG_M68KFPU_EMU_ONLY
-    fpu="none(soft float)";
+	fpu = "none(soft float)";
 #else
-    if (m68k_fputype & FPU_68881)
-	fpu = "68881";
-    else if (m68k_fputype & FPU_68882)
-	fpu = "68882";
-    else if (m68k_fputype & FPU_68040)
-	fpu = "68040";
-    else if (m68k_fputype & FPU_68060)
-	fpu = "68060";
-    else if (m68k_fputype & FPU_SUNFPA)
-	fpu = "Sun FPA";
-    else
-	fpu = "none";
+	if (m68k_fputype & FPU_68881)
+		fpu = "68881";
+	else if (m68k_fputype & FPU_68882)
+		fpu = "68882";
+	else if (m68k_fputype & FPU_68040)
+		fpu = "68040";
+	else if (m68k_fputype & FPU_68060)
+		fpu = "68060";
+	else if (m68k_fputype & FPU_SUNFPA)
+		fpu = "Sun FPA";
+	else
+		fpu = "none";
 #endif
 
-    if (m68k_mmutype & MMU_68851)
-	mmu = "68851";
-    else if (m68k_mmutype & MMU_68030)
-	mmu = "68030";
-    else if (m68k_mmutype & MMU_68040)
-	mmu = "68040";
-    else if (m68k_mmutype & MMU_68060)
-	mmu = "68060";
-    else if (m68k_mmutype & MMU_SUN3)
-	mmu = "Sun-3";
-    else if (m68k_mmutype & MMU_APOLLO)
-	mmu = "Apollo";
-    else
-	mmu = "unknown";
+	if (m68k_mmutype & MMU_68851)
+		mmu = "68851";
+	else if (m68k_mmutype & MMU_68030)
+		mmu = "68030";
+	else if (m68k_mmutype & MMU_68040)
+		mmu = "68040";
+	else if (m68k_mmutype & MMU_68060)
+		mmu = "68060";
+	else if (m68k_mmutype & MMU_SUN3)
+		mmu = "Sun-3";
+	else if (m68k_mmutype & MMU_APOLLO)
+		mmu = "Apollo";
+	else
+		mmu = "unknown";
 
-    clockfreq = loops_per_jiffy*HZ*clockfactor;
+	clockfreq = loops_per_jiffy * HZ * clockfactor;
 
-    seq_printf(m, "CPU:\t\t%s\n"
+	seq_printf(m, "CPU:\t\t%s\n"
 		   "MMU:\t\t%s\n"
 		   "FPU:\t\t%s\n"
 		   "Clocking:\t%lu.%1luMHz\n"
@@ -490,7 +456,7 @@
 		   clockfreq/1000000,(clockfreq/100000)%10,
 		   loops_per_jiffy/(500000/HZ),(loops_per_jiffy/(5000/HZ))%100,
 		   loops_per_jiffy);
-    return 0;
+	return 0;
 }
 
 static void *c_start(struct seq_file *m, loff_t *pos)
@@ -506,44 +472,54 @@
 {
 }
 struct seq_operations cpuinfo_op = {
-	.start =	c_start,
-	.next =		c_next,
-	.stop =		c_stop,
-	.show =		show_cpuinfo,
+	.start	= c_start,
+	.next	= c_next,
+	.stop	= c_stop,
+	.show	= show_cpuinfo,
 };
 
 int get_hardware_list(char *buffer)
 {
-    int len = 0;
-    char model[80];
-    unsigned long mem;
-    int i;
+	int len = 0;
+	char model[80];
+	unsigned long mem;
+	int i;
 
-    if (mach_get_model)
-	mach_get_model(model);
-    else
-	strcpy(model, "Unknown m68k");
+	if (mach_get_model)
+		mach_get_model(model);
+	else
+		strcpy(model, "Unknown m68k");
 
-    len += sprintf(buffer+len, "Model:\t\t%s\n", model);
-    for (mem = 0, i = 0; i < m68k_num_memory; i++)
-	mem += m68k_memory[i].size;
-    len += sprintf(buffer+len, "System Memory:\t%ldK\n", mem>>10);
+	len += sprintf(buffer + len, "Model:\t\t%s\n", model);
+	for (mem = 0, i = 0; i < m68k_num_memory; i++)
+		mem += m68k_memory[i].size;
+	len += sprintf(buffer + len, "System Memory:\t%ldK\n", mem >> 10);
 
-    if (mach_get_hardware_list)
-	len += mach_get_hardware_list(buffer+len);
+	if (mach_get_hardware_list)
+		len += mach_get_hardware_list(buffer + len);
 
-    return(len);
+	return len;
 }
 
 void check_bugs(void)
 {
 #ifndef CONFIG_M68KFPU_EMU
 	if (m68k_fputype == 0) {
-		printk( KERN_EMERG "*** YOU DO NOT HAVE A FLOATING POINT UNIT, "
-				"WHICH IS REQUIRED BY LINUX/M68K ***\n" );
-		printk( KERN_EMERG "Upgrade your hardware or join the FPU "
-				"emulation project\n" );
-		panic( "no FPU" );
+		printk(KERN_EMERG "*** YOU DO NOT HAVE A FLOATING POINT UNIT, "
+			"WHICH IS REQUIRED BY LINUX/M68K ***\n");
+		printk(KERN_EMERG "Upgrade your hardware or join the FPU "
+			"emulation project\n");
+		panic("no FPU");
 	}
 #endif /* !CONFIG_M68KFPU_EMU */
 }
+
+#ifdef CONFIG_ADB
+static int __init adb_probe_sync_enable (char *str) {
+	extern int __adb_probe_sync;
+	__adb_probe_sync = 1;
+	return 1;
+}
+
+__setup("adb_sync", adb_probe_sync_enable);
+#endif /* CONFIG_ADB */
diff --git a/arch/m68k/lib/checksum.c b/arch/m68k/lib/checksum.c
index aed3be2..cf6bb51 100644
--- a/arch/m68k/lib/checksum.c
+++ b/arch/m68k/lib/checksum.c
@@ -320,6 +320,9 @@
 	return(sum);
 }
 
+EXPORT_SYMBOL(csum_partial_copy_from_user);
+
+
 /*
  * copy from kernel space while checksumming, otherwise like csum_partial
  */
diff --git a/arch/m68k/mac/baboon.c b/arch/m68k/mac/baboon.c
index a1c7ec7..673a108 100644
--- a/arch/m68k/mac/baboon.c
+++ b/arch/m68k/mac/baboon.c
@@ -22,7 +22,7 @@
 /* #define DEBUG_BABOON */
 /* #define DEBUG_IRQS */
 
-int baboon_present,baboon_active;
+int baboon_present;
 volatile struct baboon *baboon;
 
 irqreturn_t baboon_irq(int, void *);
@@ -45,7 +45,6 @@
 
 	baboon = (struct baboon *) BABOON_BASE;
 	baboon_present = 1;
-	baboon_active = 0;
 
 	printk("Baboon detected at %p\n", baboon);
 }
@@ -66,26 +65,28 @@
 
 irqreturn_t baboon_irq(int irq, void *dev_id)
 {
-	int irq_bit,i;
+	int irq_bit, irq_num;
 	unsigned char events;
 
 #ifdef DEBUG_IRQS
-	printk("baboon_irq: mb_control %02X mb_ifr %02X mb_status %02X active %02X\n",
+	printk("baboon_irq: mb_control %02X mb_ifr %02X mb_status %02X\n",
 		(uint) baboon->mb_control, (uint) baboon->mb_ifr,
-		(uint) baboon->mb_status,  baboon_active);
+		(uint) baboon->mb_status);
 #endif
 
 	if (!(events = baboon->mb_ifr & 0x07))
 		return IRQ_NONE;
 
-	for (i = 0, irq_bit = 1 ; i < 3 ; i++, irq_bit <<= 1) {
-	        if (events & irq_bit/* & baboon_active*/) {
-			baboon_active &= ~irq_bit;
-			m68k_handle_int(IRQ_BABOON_0 + i);
-			baboon_active |= irq_bit;
+	irq_num = IRQ_BABOON_0;
+	irq_bit = 1;
+	do {
+	        if (events & irq_bit) {
 			baboon->mb_ifr &= ~irq_bit;
+			m68k_handle_int(irq_num);
 		}
-	}
+		irq_bit <<= 1;
+		irq_num++;
+	} while(events >= irq_bit);
 #if 0
 	if (baboon->mb_ifr & 0x02) macide_ack_intr(NULL);
 	/* for now we need to smash all interrupts */
@@ -95,21 +96,18 @@
 }
 
 void baboon_irq_enable(int irq) {
-	int irq_idx	= IRQ_IDX(irq);
-
 #ifdef DEBUG_IRQUSE
 	printk("baboon_irq_enable(%d)\n", irq);
 #endif
-	baboon_active |= (1 << irq_idx);
+	/* FIXME: figure out how to mask and unmask baboon interrupt sources */
+	enable_irq(IRQ_NUBUS_C);
 }
 
 void baboon_irq_disable(int irq) {
-	int irq_idx	= IRQ_IDX(irq);
-
 #ifdef DEBUG_IRQUSE
 	printk("baboon_irq_disable(%d)\n", irq);
 #endif
-	baboon_active &= ~(1 << irq_idx);
+	disable_irq(IRQ_NUBUS_C);
 }
 
 void baboon_irq_clear(int irq) {
diff --git a/arch/m68k/mac/config.c b/arch/m68k/mac/config.c
index 562b38d..5fd4132 100644
--- a/arch/m68k/mac/config.c
+++ b/arch/m68k/mac/config.c
@@ -59,15 +59,15 @@
 
 extern char m68k_command_line[CL_SIZE];
 
-void *mac_env;		/* Loaded by the boot asm */
+void *mac_env;					/* Loaded by the boot asm */
 
 /* The phys. video addr. - might be bogus on some machines */
 unsigned long mac_orig_videoaddr;
 
 /* Mac specific timer functions */
-extern unsigned long mac_gettimeoffset (void);
-extern int mac_hwclk (int, struct rtc_time *);
-extern int mac_set_clock_mmss (unsigned long);
+extern unsigned long mac_gettimeoffset(void);
+extern int mac_hwclk(int, struct rtc_time *);
+extern int mac_set_clock_mmss(unsigned long);
 extern int show_mac_interrupts(struct seq_file *, void *);
 extern void iop_preinit(void);
 extern void iop_init(void);
@@ -82,10 +82,6 @@
 
 extern void nubus_sweep_video(void);
 
-/* Mac specific debug functions (in debug.c) */
-extern void mac_debug_init(void);
-extern void mac_debugging_long(int, long);
-
 static void mac_get_model(char *str);
 
 static void mac_sched_init(irq_handler_t vector)
@@ -99,51 +95,52 @@
 
 int __init mac_parse_bootinfo(const struct bi_record *record)
 {
-    int unknown = 0;
-    const u_long *data = record->data;
+	int unknown = 0;
+	const u_long *data = record->data;
 
-    switch (record->tag) {
+	switch (record->tag) {
 	case BI_MAC_MODEL:
-	    mac_bi_data.id = *data;
-	    break;
+		mac_bi_data.id = *data;
+		break;
 	case BI_MAC_VADDR:
-	    mac_bi_data.videoaddr = *data;
-	    break;
+		mac_bi_data.videoaddr = *data;
+		break;
 	case BI_MAC_VDEPTH:
-	    mac_bi_data.videodepth = *data;
-	    break;
+		mac_bi_data.videodepth = *data;
+		break;
 	case BI_MAC_VROW:
-	    mac_bi_data.videorow = *data;
-	    break;
+		mac_bi_data.videorow = *data;
+		break;
 	case BI_MAC_VDIM:
-	    mac_bi_data.dimensions = *data;
-	    break;
+		mac_bi_data.dimensions = *data;
+		break;
 	case BI_MAC_VLOGICAL:
-	    mac_bi_data.videological = VIDEOMEMBASE + (*data & ~VIDEOMEMMASK);
-	    mac_orig_videoaddr = *data;
-	    break;
+		mac_bi_data.videological = VIDEOMEMBASE + (*data & ~VIDEOMEMMASK);
+		mac_orig_videoaddr = *data;
+		break;
 	case BI_MAC_SCCBASE:
-	    mac_bi_data.sccbase = *data;
-	    break;
+		mac_bi_data.sccbase = *data;
+		break;
 	case BI_MAC_BTIME:
-	    mac_bi_data.boottime = *data;
-	    break;
+		mac_bi_data.boottime = *data;
+		break;
 	case BI_MAC_GMTBIAS:
-	    mac_bi_data.gmtbias = *data;
-	    break;
+		mac_bi_data.gmtbias = *data;
+		break;
 	case BI_MAC_MEMSIZE:
-	    mac_bi_data.memsize = *data;
-	    break;
+		mac_bi_data.memsize = *data;
+		break;
 	case BI_MAC_CPUID:
-	    mac_bi_data.cpuid = *data;
-	    break;
-        case BI_MAC_ROMBASE:
-	    mac_bi_data.rombase = *data;
-	    break;
+		mac_bi_data.cpuid = *data;
+		break;
+	case BI_MAC_ROMBASE:
+		mac_bi_data.rombase = *data;
+		break;
 	default:
-	    unknown = 1;
-    }
-    return(unknown);
+		unknown = 1;
+		break;
+	}
+	return unknown;
 }
 
 /*
@@ -155,6 +152,7 @@
 static void mac_cache_card_flush(int writeback)
 {
 	unsigned long flags;
+
 	local_irq_save(flags);
 	via_flush_cache();
 	local_irq_restore(flags);
@@ -162,28 +160,24 @@
 
 void __init config_mac(void)
 {
-	if (!MACH_IS_MAC) {
-	  printk(KERN_ERR "ERROR: no Mac, but config_mac() called!! \n");
-	}
+	if (!MACH_IS_MAC)
+		printk(KERN_ERR "ERROR: no Mac, but config_mac() called!! \n");
 
-	mach_sched_init      = mac_sched_init;
-	mach_init_IRQ        = mac_init_IRQ;
-	mach_get_model	 = mac_get_model;
-	mach_gettimeoffset   = mac_gettimeoffset;
+	mach_sched_init = mac_sched_init;
+	mach_init_IRQ = mac_init_IRQ;
+	mach_get_model = mac_get_model;
+	mach_gettimeoffset = mac_gettimeoffset;
 #warning move to adb/via init
 #if 0
-	mach_hwclk           = mac_hwclk;
+	mach_hwclk = mac_hwclk;
 #endif
-	mach_set_clock_mmss	 = mac_set_clock_mmss;
-	mach_reset           = mac_reset;
-	mach_halt            = mac_poweroff;
-	mach_power_off       = mac_poweroff;
+	mach_set_clock_mmss = mac_set_clock_mmss;
+	mach_reset = mac_reset;
+	mach_halt = mac_poweroff;
+	mach_power_off = mac_poweroff;
 	mach_max_dma_address = 0xffffffff;
-#if 0
-	mach_debug_init	 = mac_debug_init;
-#endif
 #if defined(CONFIG_INPUT_M68K_BEEP) || defined(CONFIG_INPUT_M68K_BEEP_MODULE)
-        mach_beep            = mac_mksound;
+	mach_beep = mac_mksound;
 #endif
 #ifdef CONFIG_HEARTBEAT
 #if 0
@@ -199,21 +193,22 @@
 	mac_identify();
 	mac_report_hardware();
 
-	/* AFAIK only the IIci takes a cache card.  The IIfx has onboard
-	   cache ... someone needs to figure out how to tell if it's on or
-	   not. */
+	/*
+	 * AFAIK only the IIci takes a cache card.  The IIfx has onboard
+	 * cache ... someone needs to figure out how to tell if it's on or
+	 * not.
+	 */
 
 	if (macintosh_config->ident == MAC_MODEL_IICI
-	    || macintosh_config->ident == MAC_MODEL_IIFX) {
+	    || macintosh_config->ident == MAC_MODEL_IIFX)
 		mach_l2_flush = mac_cache_card_flush;
-	}
 
 	/*
 	 * Check for machine specific fixups.
 	 */
 
 #ifdef OLD_NUBUS_CODE
-	 nubus_sweep_video();
+	nubus_sweep_video();
 #endif
 }
 
@@ -233,8 +228,7 @@
 struct mac_model *macintosh_config;
 EXPORT_SYMBOL(macintosh_config);
 
-static struct mac_model mac_data_table[]=
-{
+static struct mac_model mac_data_table[] = {
 	/*
 	 *	We'll pretend to be a Macintosh II, that's pretty safe.
 	 */
@@ -784,12 +778,12 @@
 	if (!model) {
 		/* no bootinfo model id -> NetBSD booter was used! */
 		/* XXX FIXME: breaks for model > 31 */
-		model=(mac_bi_data.cpuid>>2)&63;
-		printk (KERN_WARNING "No bootinfo model ID, using cpuid instead (hey, use Penguin!)\n");
+		model = (mac_bi_data.cpuid >> 2) & 63;
+		printk(KERN_WARNING "No bootinfo model ID, using cpuid instead (hey, use Penguin!)\n");
 	}
 
 	macintosh_config = mac_data_table;
-	for (m = macintosh_config ; m->ident != -1 ; m++) {
+	for (m = macintosh_config; m->ident != -1; m++) {
 		if (m->ident == model) {
 			macintosh_config = m;
 			break;
@@ -801,27 +795,26 @@
 	/* the serial ports set to "Faster" mode in MacOS. */
 
 	iop_preinit();
-	mac_debug_init();
 
-	printk (KERN_INFO "Detected Macintosh model: %d \n", model);
+	printk(KERN_INFO "Detected Macintosh model: %d \n", model);
 
 	/*
 	 * Report booter data:
 	 */
-	printk (KERN_DEBUG " Penguin bootinfo data:\n");
-	printk (KERN_DEBUG " Video: addr 0x%lx row 0x%lx depth %lx dimensions %ld x %ld\n",
+	printk(KERN_DEBUG " Penguin bootinfo data:\n");
+	printk(KERN_DEBUG " Video: addr 0x%lx row 0x%lx depth %lx dimensions %ld x %ld\n",
 		mac_bi_data.videoaddr, mac_bi_data.videorow,
 		mac_bi_data.videodepth, mac_bi_data.dimensions & 0xFFFF,
 		mac_bi_data.dimensions >> 16);
-	printk (KERN_DEBUG " Videological 0x%lx phys. 0x%lx, SCC at 0x%lx \n",
+	printk(KERN_DEBUG " Videological 0x%lx phys. 0x%lx, SCC at 0x%lx \n",
 		mac_bi_data.videological, mac_orig_videoaddr,
 		mac_bi_data.sccbase);
-	printk (KERN_DEBUG " Boottime: 0x%lx GMTBias: 0x%lx \n",
+	printk(KERN_DEBUG " Boottime: 0x%lx GMTBias: 0x%lx \n",
 		mac_bi_data.boottime, mac_bi_data.gmtbias);
-	printk (KERN_DEBUG " Machine ID: %ld CPUid: 0x%lx memory size: 0x%lx \n",
+	printk(KERN_DEBUG " Machine ID: %ld CPUid: 0x%lx memory size: 0x%lx \n",
 		mac_bi_data.id, mac_bi_data.cpuid, mac_bi_data.memsize);
 #if 0
-	printk ("Ramdisk: addr 0x%lx size 0x%lx\n",
+	printk("Ramdisk: addr 0x%lx size 0x%lx\n",
 		m68k_ramdisk.addr, m68k_ramdisk.size);
 #endif
 
@@ -830,22 +823,22 @@
 	 */
 	switch (macintosh_config->scsi_type) {
 	case MAC_SCSI_OLD:
-	  MACHW_SET(MAC_SCSI_80);
-	  break;
+		MACHW_SET(MAC_SCSI_80);
+		break;
 	case MAC_SCSI_QUADRA:
 	case MAC_SCSI_QUADRA2:
 	case MAC_SCSI_QUADRA3:
-	  MACHW_SET(MAC_SCSI_96);
-	  if ((macintosh_config->ident == MAC_MODEL_Q900) ||
-	      (macintosh_config->ident == MAC_MODEL_Q950))
-	    MACHW_SET(MAC_SCSI_96_2);
-	  break;
+		MACHW_SET(MAC_SCSI_96);
+		if ((macintosh_config->ident == MAC_MODEL_Q900) ||
+		    (macintosh_config->ident == MAC_MODEL_Q950))
+			MACHW_SET(MAC_SCSI_96_2);
+		break;
 	default:
-	  printk(KERN_WARNING "config.c: wtf: unknown scsi, using 53c80\n");
-	  MACHW_SET(MAC_SCSI_80);
-	  break;
-
+		printk(KERN_WARNING "config.c: wtf: unknown scsi, using 53c80\n");
+		MACHW_SET(MAC_SCSI_80);
+		break;
 	}
+
 	iop_init();
 	via_init();
 	oss_init();
@@ -860,6 +853,6 @@
 
 static void mac_get_model(char *str)
 {
-	strcpy(str,"Macintosh ");
+	strcpy(str, "Macintosh ");
 	strcat(str, macintosh_config->name);
 }
diff --git a/arch/m68k/mac/debug.c b/arch/m68k/mac/debug.c
index 4eeb09d..7a5bed5 100644
--- a/arch/m68k/mac/debug.c
+++ b/arch/m68k/mac/debug.c
@@ -27,10 +27,6 @@
 #include <asm/machw.h>
 #include <asm/macints.h>
 
-extern char m68k_debug_device[];
-
-extern struct compat_bootinfo compat_boot_info;
-
 extern unsigned long mac_videobase;
 extern unsigned long mac_videodepth;
 extern unsigned long mac_rowbytes;
@@ -52,7 +48,7 @@
  */
 
 #ifdef DEBUG_SCREEN
-static int peng=0, line=0;
+static int peng, line;
 #endif
 
 void mac_debugging_short(int pos, short num)
@@ -74,15 +70,14 @@
 	}
 
 	/* calculate current offset */
-	pengoffset=(unsigned char *)(mac_videobase+(150+line*2)*mac_rowbytes)
-		    +80*peng;
+	pengoffset = (unsigned char *)mac_videobase +
+		(150+line*2) * mac_rowbytes) + 80 * peng;
 
-	pptr=pengoffset;
+	pptr = pengoffset;
 
-	for(i=0;i<8*sizeof(short);i++) /* # of bits */
-	{
+	for (i = 0; i < 8 * sizeof(short); i++) { /* # of bits */
 		/*        value        mask for bit i, reverse order */
-		*pptr++ = (num & ( 1 << (8*sizeof(short)-i-1) ) ? 0xFF : 0x00);
+		*pptr++ = (num & (1 << (8*sizeof(short)-i-1)) ? 0xFF : 0x00);
 	}
 
 	peng++;
@@ -115,11 +110,10 @@
 	pengoffset=(unsigned char *)(mac_videobase+(150+line*2)*mac_rowbytes)
 		    +80*peng;
 
-	pptr=pengoffset;
+	pptr = pengoffset;
 
-	for(i=0;i<8*sizeof(long);i++) /* # of bits */
-	{
-		*pptr++ = (addr & ( 1 << (8*sizeof(long)-i-1) ) ? 0xFF : 0x00);
+	for (i = 0; i < 8 * sizeof(long); i++) { /* # of bits */
+		*pptr++ = (addr & (1 << (8*sizeof(long)-i-1)) ? 0xFF : 0x00);
 	}
 
 	peng++;
@@ -136,16 +130,15 @@
  * TODO: serial debug code
  */
 
-struct mac_SCC
- {
-  u_char cha_b_ctrl;
-  u_char char_dummy1;
-  u_char cha_a_ctrl;
-  u_char char_dummy2;
-  u_char cha_b_data;
-  u_char char_dummy3;
-  u_char cha_a_data;
- };
+struct mac_SCC {
+	u_char cha_b_ctrl;
+	u_char char_dummy1;
+	u_char cha_a_ctrl;
+	u_char char_dummy2;
+	u_char cha_b_data;
+	u_char char_dummy3;
+	u_char cha_a_data;
+};
 
 # define scc (*((volatile struct mac_SCC*)mac_bi_data.sccbase))
 
@@ -158,9 +151,9 @@
 static int scc_port = -1;
 
 static struct console mac_console_driver = {
-	.name =		"debug",
-	.flags =	CON_PRINTBUFFER,
-	.index =	-1,
+	.name	= "debug",
+	.flags	= CON_PRINTBUFFER,
+	.index	= -1,
 };
 
 /*
@@ -178,8 +171,8 @@
  * this driver if Mac.
  */
 
-void mac_debug_console_write (struct console *co, const char *str,
-			      unsigned int count)
+void mac_debug_console_write(struct console *co, const char *str,
+			     unsigned int count)
 {
 	mac_serial_print(str);
 }
@@ -190,48 +183,50 @@
 
 #define uSEC 1
 
-static inline void mac_sccb_out (char c)
+static inline void mac_sccb_out(char c)
 {
-    int i;
-    do {
-	for( i = uSEC; i > 0; --i )
+	int i;
+
+	do {
+		for (i = uSEC; i > 0; --i)
+			barrier();
+	} while (!(scc.cha_b_ctrl & 0x04)); /* wait for tx buf empty */
+	for (i = uSEC; i > 0; --i)
 		barrier();
-    } while (!(scc.cha_b_ctrl & 0x04)); /* wait for tx buf empty */
-    for( i = uSEC; i > 0; --i )
-	barrier();
-    scc.cha_b_data = c;
+	scc.cha_b_data = c;
 }
 
-static inline void mac_scca_out (char c)
+static inline void mac_scca_out(char c)
 {
-    int i;
-    do {
-	for( i = uSEC; i > 0; --i )
+	int i;
+
+	do {
+		for (i = uSEC; i > 0; --i)
+			barrier();
+	} while (!(scc.cha_a_ctrl & 0x04)); /* wait for tx buf empty */
+	for (i = uSEC; i > 0; --i)
 		barrier();
-    } while (!(scc.cha_a_ctrl & 0x04)); /* wait for tx buf empty */
-    for( i = uSEC; i > 0; --i )
-	barrier();
-    scc.cha_a_data = c;
+	scc.cha_a_data = c;
 }
 
-void mac_sccb_console_write (struct console *co, const char *str,
-			      unsigned int count)
+void mac_sccb_console_write(struct console *co, const char *str,
+			    unsigned int count)
 {
-    while (count--) {
-	if (*str == '\n')
-	    mac_sccb_out( '\r' );
-	mac_sccb_out( *str++ );
-    }
+	while (count--) {
+		if (*str == '\n')
+			mac_sccb_out('\r');
+		mac_sccb_out(*str++);
+	}
 }
 
-void mac_scca_console_write (struct console *co, const char *str,
-			      unsigned int count)
+void mac_scca_console_write(struct console *co, const char *str,
+			    unsigned int count)
 {
-    while (count--) {
-	if (*str == '\n')
-	    mac_scca_out( '\r' );
-	mac_scca_out( *str++ );
-    }
+	while (count--) {
+		if (*str == '\n')
+			mac_scca_out('\r');
+		mac_scca_out(*str++);
+	}
 }
 
 
@@ -239,41 +234,41 @@
  * SCC serial ports. They're used by the debugging interface, kgdb, and the
  * serial console code. */
 #define SCCB_WRITE(reg,val)				\
-    do {						\
-	int i;						\
-	scc.cha_b_ctrl = (reg);				\
-	for( i = uSEC; i > 0; --i )			\
-		barrier();				\
-	scc.cha_b_ctrl = (val);				\
-	for( i = uSEC; i > 0; --i )			\
-		barrier();				\
-    } while(0)
+	do {						\
+		int i;					\
+		scc.cha_b_ctrl = (reg);			\
+		for (i = uSEC; i > 0; --i)		\
+			barrier();			\
+		scc.cha_b_ctrl = (val);			\
+		for (i = uSEC; i > 0; --i)		\
+			barrier();			\
+	} while(0)
 
 #define SCCA_WRITE(reg,val)				\
-    do {						\
-	int i;						\
-	scc.cha_a_ctrl = (reg);				\
-	for( i = uSEC; i > 0; --i )			\
-		barrier();				\
-	scc.cha_a_ctrl = (val);				\
-	for( i = uSEC; i > 0; --i )			\
-		barrier();				\
-    } while(0)
+	do {						\
+		int i;					\
+		scc.cha_a_ctrl = (reg);			\
+		for (i = uSEC; i > 0; --i)		\
+			barrier();			\
+		scc.cha_a_ctrl = (val);			\
+		for (i = uSEC; i > 0; --i)		\
+			barrier();			\
+	} while(0)
 
 /* loops_per_jiffy isn't initialized yet, so we can't use udelay(). This does a
  * delay of ~ 60us. */
 /* Mac: loops_per_jiffy min. 19000 ^= .5 us; MFPDELAY was 0.6 us*/
-#define LONG_DELAY()				\
-    do {					\
-	int i;					\
-	for( i = 60*uSEC; i > 0; --i )		\
-	    barrier();				\
-    } while(0)
+#define LONG_DELAY()					\
+	do {						\
+		int i;					\
+		for (i = 60*uSEC; i > 0; --i)		\
+		    barrier();				\
+	} while(0)
 
 #ifndef CONFIG_SERIAL_CONSOLE
-static void __init mac_init_scc_port( int cflag, int port )
+static void __init mac_init_scc_port(int cflag, int port)
 #else
-void mac_init_scc_port( int cflag, int port )
+void mac_init_scc_port(int cflag, int port)
 #endif
 {
 	extern int mac_SCC_reset_done;
@@ -292,106 +287,102 @@
 		/* reg12 (BRG low) */
 		{ 94, 62, 46, 22, 10, 4, 1, 0, 0 };
 
-    int baud = cflag & CBAUD;
-    int clksrc, clkmode, div, reg3, reg5;
+	int baud = cflag & CBAUD;
+	int clksrc, clkmode, div, reg3, reg5;
 
-    if (cflag & CBAUDEX)
-	baud += B38400;
-    if (baud < B1200 || baud > B38400+2)
-	baud = B9600; /* use default 9600bps for non-implemented rates */
-    baud -= B1200; /* tables starts at 1200bps */
+	if (cflag & CBAUDEX)
+		baud += B38400;
+	if (baud < B1200 || baud > B38400+2)
+		baud = B9600; /* use default 9600bps for non-implemented rates */
+	baud -= B1200; /* tables starts at 1200bps */
 
-    clksrc  = clksrc_table[baud];
-    clkmode = clkmode_table[baud];
-    div     = div_table[baud];
+	clksrc  = clksrc_table[baud];
+	clkmode = clkmode_table[baud];
+	div     = div_table[baud];
 
-    reg3 = (((cflag & CSIZE) == CS8) ? 0xc0 : 0x40);
-    reg5 = (((cflag & CSIZE) == CS8) ? 0x60 : 0x20) | 0x82 /* assert DTR/RTS */;
+	reg3 = (((cflag & CSIZE) == CS8) ? 0xc0 : 0x40);
+	reg5 = (((cflag & CSIZE) == CS8) ? 0x60 : 0x20) | 0x82 /* assert DTR/RTS */;
 
-    if (port == 1) {
-	    (void)scc.cha_b_ctrl;	/* reset reg pointer */
-	    SCCB_WRITE( 9, 0xc0 );	/* reset */
-	    LONG_DELAY();		/* extra delay after WR9 access */
-	    SCCB_WRITE( 4, (cflag & PARENB) ? ((cflag & PARODD) ? 0x01 : 0x03) : 0 |
+	if (port == 1) {
+		(void)scc.cha_b_ctrl;	/* reset reg pointer */
+		SCCB_WRITE(9, 0xc0);	/* reset */
+		LONG_DELAY();		/* extra delay after WR9 access */
+		SCCB_WRITE(4, (cflag & PARENB) ? ((cflag & PARODD) ? 0x01 : 0x03) : 0 |
+			   0x04 /* 1 stopbit */ |
+			   clkmode);
+		SCCB_WRITE(3, reg3);
+		SCCB_WRITE(5, reg5);
+		SCCB_WRITE(9, 0);	/* no interrupts */
+		LONG_DELAY();		/* extra delay after WR9 access */
+		SCCB_WRITE(10, 0);	/* NRZ mode */
+		SCCB_WRITE(11, clksrc);	/* main clock source */
+		SCCB_WRITE(12, div);	/* BRG value */
+		SCCB_WRITE(13, 0);	/* BRG high byte */
+		SCCB_WRITE(14, 1);
+		SCCB_WRITE(3, reg3 | 1);
+		SCCB_WRITE(5, reg5 | 8);
+	} else if (port == 0) {
+		(void)scc.cha_a_ctrl;	/* reset reg pointer */
+		SCCA_WRITE(9, 0xc0);	/* reset */
+		LONG_DELAY();		/* extra delay after WR9 access */
+		SCCA_WRITE(4, (cflag & PARENB) ? ((cflag & PARODD) ? 0x01 : 0x03) : 0 |
 			  0x04 /* 1 stopbit */ |
-			  clkmode );
-	    SCCB_WRITE( 3, reg3 );
-	    SCCB_WRITE( 5, reg5 );
-	    SCCB_WRITE( 9, 0 );		/* no interrupts */
-	    LONG_DELAY();		/* extra delay after WR9 access */
-	    SCCB_WRITE( 10, 0 );	/* NRZ mode */
-	    SCCB_WRITE( 11, clksrc );	/* main clock source */
-	    SCCB_WRITE( 12, div );	/* BRG value */
-	    SCCB_WRITE( 13, 0 );		/* BRG high byte */
-	    SCCB_WRITE( 14, 1 );
-	    SCCB_WRITE( 3, reg3 | 1 );
-	    SCCB_WRITE( 5, reg5 | 8 );
-    } else if (port == 0) {
-	    (void)scc.cha_a_ctrl;	/* reset reg pointer */
-	    SCCA_WRITE( 9, 0xc0 );	/* reset */
-	    LONG_DELAY();		/* extra delay after WR9 access */
-	    SCCA_WRITE( 4, (cflag & PARENB) ? ((cflag & PARODD) ? 0x01 : 0x03) : 0 |
-			  0x04 /* 1 stopbit */ |
-			  clkmode );
-	    SCCA_WRITE( 3, reg3 );
-	    SCCA_WRITE( 5, reg5 );
-	    SCCA_WRITE( 9, 0 );		/* no interrupts */
-	    LONG_DELAY();		/* extra delay after WR9 access */
-	    SCCA_WRITE( 10, 0 );	/* NRZ mode */
-	    SCCA_WRITE( 11, clksrc );	/* main clock source */
-	    SCCA_WRITE( 12, div );	/* BRG value */
-	    SCCA_WRITE( 13, 0 );		/* BRG high byte */
-	    SCCA_WRITE( 14, 1 );
-	    SCCA_WRITE( 3, reg3 | 1 );
-	    SCCA_WRITE( 5, reg5 | 8 );
-    }
+			  clkmode);
+		SCCA_WRITE(3, reg3);
+		SCCA_WRITE(5, reg5);
+		SCCA_WRITE(9, 0);	/* no interrupts */
+		LONG_DELAY();		/* extra delay after WR9 access */
+		SCCA_WRITE(10, 0);	/* NRZ mode */
+		SCCA_WRITE(11, clksrc);	/* main clock source */
+		SCCA_WRITE(12, div);	/* BRG value */
+		SCCA_WRITE(13, 0);	/* BRG high byte */
+		SCCA_WRITE(14, 1);
+		SCCA_WRITE(3, reg3 | 1);
+		SCCA_WRITE(5, reg5 | 8);
+	}
 
-    mac_SCC_reset_done = 1;
-    mac_SCC_init_done = 1;
+	mac_SCC_reset_done = 1;
+	mac_SCC_init_done = 1;
 }
 #endif /* DEBUG_SERIAL */
 
-void mac_init_scca_port( int cflag )
+void mac_init_scca_port(int cflag)
 {
 	mac_init_scc_port(cflag, 0);
 }
 
-void mac_init_sccb_port( int cflag )
+void mac_init_sccb_port(int cflag)
 {
 	mac_init_scc_port(cflag, 1);
 }
 
-void __init mac_debug_init(void)
+static int __init mac_debug_setup(char *arg)
 {
+	if (!MACH_IS_MAC)
+		return 0;
+
 #ifdef DEBUG_SERIAL
-    if (   !strcmp( m68k_debug_device, "ser"  )
-        || !strcmp( m68k_debug_device, "ser1" )) {
-	/* Mac modem port */
-	mac_init_scc_port( B9600|CS8, 0 );
-	mac_console_driver.write = mac_scca_console_write;
-	scc_port = 0;
-    }
-    else if (!strcmp( m68k_debug_device, "ser2" )) {
-	/* Mac printer port */
-	mac_init_scc_port( B9600|CS8, 1 );
-	mac_console_driver.write = mac_sccb_console_write;
-	scc_port = 1;
-    }
+	if (!strcmp(arg, "ser") || !strcmp(arg, "ser1")) {
+		/* Mac modem port */
+		mac_init_scc_port(B9600|CS8, 0);
+		mac_console_driver.write = mac_scca_console_write;
+		scc_port = 0;
+	} else if (!strcmp(arg, "ser2")) {
+		/* Mac printer port */
+		mac_init_scc_port(B9600|CS8, 1);
+		mac_console_driver.write = mac_sccb_console_write;
+		scc_port = 1;
+	}
 #endif
 #ifdef DEBUG_HEADS
-    if (   !strcmp( m68k_debug_device, "scn"  )
-        || !strcmp( m68k_debug_device, "con" )) {
-	/* display, using head.S console routines */
-	mac_console_driver.write = mac_debug_console_write;
-    }
+	if (!strcmp(arg, "scn") || !strcmp(arg, "con")) {
+		/* display, using head.S console routines */
+		mac_console_driver.write = mac_debug_console_write;
+	}
 #endif
-    if (mac_console_driver.write)
-	register_console(&mac_console_driver);
+	if (mac_console_driver.write)
+		register_console(&mac_console_driver);
+	return 0;
 }
 
-/*
- * Local variables:
- *  c-indent-level: 4
- *  tab-width: 8
- * End:
- */
+early_param("debug", mac_debug_setup);
diff --git a/arch/m68k/mac/oss.c b/arch/m68k/mac/oss.c
index 6369081..d7be169 100644
--- a/arch/m68k/mac/oss.c
+++ b/arch/m68k/mac/oss.c
@@ -109,13 +109,11 @@
 	/* FIXME: how do you clear a pending IRQ?    */
 
 	if (events & OSS_IP_SOUND) {
-		/* FIXME: call sound handler */
 		oss->irq_pending &= ~OSS_IP_SOUND;
+		/* FIXME: call sound handler */
 	} else if (events & OSS_IP_SCSI) {
-		oss->irq_level[OSS_SCSI] = OSS_IRQLEV_DISABLED;
-		m68k_handle_int(IRQ_MAC_SCSI);
 		oss->irq_pending &= ~OSS_IP_SCSI;
-		oss->irq_level[OSS_SCSI] = OSS_IRQLEV_SCSI;
+		m68k_handle_int(IRQ_MAC_SCSI);
 	} else {
 		/* FIXME: error check here? */
 	}
@@ -143,14 +141,16 @@
 #endif
 	/* There are only six slots on the OSS, not seven */
 
-	for (i = 0, irq_bit = 1 ; i < 6 ; i++, irq_bit <<= 1) {
+	i = 6;
+	irq_bit = 0x40;
+	do {
+		--i;
+		irq_bit >>= 1;
 		if (events & irq_bit) {
-			oss->irq_level[i] = OSS_IRQLEV_DISABLED;
-			m68k_handle_int(NUBUS_SOURCE_BASE + i);
 			oss->irq_pending &= ~irq_bit;
-			oss->irq_level[i] = OSS_IRQLEV_NUBUS;
+			m68k_handle_int(NUBUS_SOURCE_BASE + i);
 		}
-	}
+	} while(events & (irq_bit - 1));
 	return IRQ_HANDLED;
 }
 
diff --git a/arch/m68k/mac/psc.c b/arch/m68k/mac/psc.c
index 15378a5..d66f723 100644
--- a/arch/m68k/mac/psc.c
+++ b/arch/m68k/mac/psc.c
@@ -131,11 +131,8 @@
 {
 	int pIFR	= pIFRbase + ((int) dev_id);
 	int pIER	= pIERbase + ((int) dev_id);
-	int base_irq;
-	int irq_bit,i;
-	unsigned char events;
-
-	base_irq = irq << 3;
+	int irq_num;
+	unsigned char irq_bit, events;
 
 #ifdef DEBUG_IRQS
 	printk("psc_irq: irq %d pIFR = 0x%02X pIER = 0x%02X\n",
@@ -146,14 +143,16 @@
 	if (!events)
 		return IRQ_NONE;
 
-	for (i = 0, irq_bit = 1 ; i < 4 ; i++, irq_bit <<= 1) {
-	        if (events & irq_bit) {
-			psc_write_byte(pIER, irq_bit);
-			m68k_handle_int(base_irq + i);
+	irq_num = irq << 3;
+	irq_bit = 1;
+	do {
+		if (events & irq_bit) {
 			psc_write_byte(pIFR, irq_bit);
-			psc_write_byte(pIER, irq_bit | 0x80);
+			m68k_handle_int(irq_num);
 		}
-	}
+		irq_num++;
+		irq_bit <<= 1;
+	} while (events >= irq_bit);
 	return IRQ_HANDLED;
 }
 
diff --git a/arch/m68k/mac/via.c b/arch/m68k/mac/via.c
index e27735b..d5cac72e 100644
--- a/arch/m68k/mac/via.c
+++ b/arch/m68k/mac/via.c
@@ -13,6 +13,10 @@
  * for info.  A full-text web search on 6522 AND VIA will probably also
  * net some usefulness. <cananian@alumni.princeton.edu> 20apr1999
  *
+ * Additional data is here (the SY6522 was used in the Mac II etc):
+ *     http://www.6502.org/documents/datasheets/synertek/synertek_sy6522.pdf
+ *     http://www.6502.org/documents/datasheets/synertek/synertek_sy6522_programming_reference.pdf
+ *
  * PRAM/RTC access algorithms are from the NetBSD RTC toolkit version 1.08b
  * by Erik Vogan and adapted to Linux by Joshua M. Thompson (funaho@jurai.org)
  *
@@ -37,7 +41,7 @@
 /* See note in mac_via.h about how this is possibly not useful */
 volatile long *via_memory_bogon=(long *)&via_memory_bogon;
 #endif
-int  rbv_present,via_alt_mapping;
+int rbv_present, via_alt_mapping;
 __u8 rbv_clear;
 
 /*
@@ -60,7 +64,19 @@
 #define MAC_CLOCK_LOW		(MAC_CLOCK_TICK&0xFF)
 #define MAC_CLOCK_HIGH		(MAC_CLOCK_TICK>>8)
 
-static int  nubus_active;
+/* To disable a NuBus slot on Quadras we make the slot IRQ lines outputs, set
+ * high. On RBV we just use the slot interrupt enable register. On Macs with
+ * genuine VIA chips we must use nubus_disabled to keep track of disabled slot
+ * interrupts. When any slot IRQ is disabled we mask the (edge triggered) CA1
+ * or "SLOTS" interrupt. When no slot is disabled, we unmask the CA1 interrupt.
+ * So, on genuine VIAs, having more than one NuBus IRQ can mean trouble,
+ * because closing one of those drivers can mask all of the NuBus interrupts.
+ * Also, since we can't mask the unregistered slot IRQs on genuine VIAs, it's
+ * possible to get interrupts from cards that MacOS or the ROM has configured
+ * but we have not. FWIW, "Designing Cards and Drivers for Macintosh II and
+ * Macintosh SE", page 9-8, says, a slot IRQ with no driver would crash MacOS.
+ */
+static u8 nubus_disabled;
 
 void via_debug_dump(void);
 irqreturn_t via1_irq(int, void *);
@@ -138,11 +154,11 @@
 
 	printk(KERN_INFO "VIA2 at %p is ", via2);
 	if (rbv_present) {
-		printk(KERN_INFO "an RBV\n");
+		printk("an RBV\n");
 	} else if (oss_present) {
-		printk(KERN_INFO "an OSS\n");
+		printk("an OSS\n");
 	} else {
-		printk(KERN_INFO "a 6522 or clone\n");
+		printk("a 6522 or clone\n");
 	}
 
 #ifdef DEBUG_VIA
@@ -163,6 +179,7 @@
 	via1[vT2CL] = 0;
 	via1[vT2CH] = 0;
 	via1[vACR] &= 0x3F;
+	via1[vACR] &= ~0x03; /* disable port A & B latches */
 
 	/*
 	 * SE/30: disable video IRQ
@@ -193,8 +210,14 @@
 	/* that the IIfx emulates this alternate mapping using the OSS. */
 
 	switch(macintosh_config->ident) {
+		case MAC_MODEL_P475:
+		case MAC_MODEL_P475F:
+		case MAC_MODEL_P575:
+		case MAC_MODEL_Q605:
+		case MAC_MODEL_Q605_ACC:
 		case MAC_MODEL_C610:
 		case MAC_MODEL_Q610:
+		case MAC_MODEL_Q630:
 		case MAC_MODEL_C650:
 		case MAC_MODEL_Q650:
 		case MAC_MODEL_Q700:
@@ -228,6 +251,22 @@
 		via2[vT2CL] = 0;
 		via2[vT2CH] = 0;
 		via2[vACR] &= 0x3F;
+		via2[vACR] &= ~0x03; /* disable port A & B latches */
+	}
+
+	/*
+	 * Set vPCR for SCSI interrupts (but not on RBV)
+	 */
+	if (!rbv_present) {
+		if (macintosh_config->scsi_type == MAC_SCSI_OLD) {
+			/* CB2 (IRQ) indep. input, positive edge */
+			/* CA2 (DRQ) indep. input, positive edge */
+			via2[vPCR] = 0x66;
+		} else {
+			/* CB2 (IRQ) indep. input, negative edge */
+			/* CA2 (DRQ) indep. input, negative edge */
+			via2[vPCR] = 0x22;
+		}
 	}
 }
 
@@ -356,78 +395,75 @@
 
 void __init via_nubus_init(void)
 {
-	/* don't set nubus_active = 0 here, it kills the Baboon */
-	/* interrupt that we've already registered.		*/
-
 	/* unlock nubus transactions */
 
-	if (!rbv_present) {
-		/* set the line to be an output on non-RBV machines */
-		if ((macintosh_config->adb_type != MAC_ADB_PB1) &&
-		   (macintosh_config->adb_type != MAC_ADB_PB2)) {
-			via2[vDirB] |= 0x02;
-		}
-	}
-
-	/* this seems to be an ADB bit on PMU machines */
-	/* according to MkLinux.  -- jmt               */
-
 	if ((macintosh_config->adb_type != MAC_ADB_PB1) &&
 	    (macintosh_config->adb_type != MAC_ADB_PB2)) {
+		/* set the line to be an output on non-RBV machines */
+		if (!rbv_present)
+			via2[vDirB] |= 0x02;
+
+		/* this seems to be an ADB bit on PMU machines */
+		/* according to MkLinux.  -- jmt               */
 		via2[gBufB] |= 0x02;
 	}
 
-	/* disable nubus slot interrupts. */
-	if (rbv_present) {
-		via2[rSIER] = 0x7F;
-		via2[rSIER] = nubus_active | 0x80;
-	} else {
-		/* These are ADB bits on PMU */
-		if ((macintosh_config->adb_type != MAC_ADB_PB1) &&
-		   (macintosh_config->adb_type != MAC_ADB_PB2)) {
-			switch(macintosh_config->ident)
-			{
-				case MAC_MODEL_II:
-				case MAC_MODEL_IIX:
-				case MAC_MODEL_IICX:
-				case MAC_MODEL_SE30:
-					via2[vBufA] |= 0x3F;
-					via2[vDirA] = ~nubus_active | 0xc0;
-					break;
-				default:
-					via2[vBufA] = 0xFF;
-					via2[vDirA] = ~nubus_active;
-			}
+	/* Disable all the slot interrupts (where possible). */
+
+	switch (macintosh_config->via_type) {
+	case MAC_VIA_II:
+		/* Just make the port A lines inputs. */
+		switch(macintosh_config->ident) {
+		case MAC_MODEL_II:
+		case MAC_MODEL_IIX:
+		case MAC_MODEL_IICX:
+		case MAC_MODEL_SE30:
+			/* The top two bits are RAM size outputs. */
+			via2[vDirA] &= 0xC0;
+			break;
+		default:
+			via2[vDirA] &= 0x80;
 		}
+		break;
+	case MAC_VIA_IIci:
+		/* RBV. Disable all the slot interrupts. SIER works like IER. */
+		via2[rSIER] = 0x7F;
+		break;
+	case MAC_VIA_QUADRA:
+		/* Disable the inactive slot interrupts by making those lines outputs. */
+		if ((macintosh_config->adb_type != MAC_ADB_PB1) &&
+		    (macintosh_config->adb_type != MAC_ADB_PB2)) {
+			via2[vBufA] |= 0x7F;
+			via2[vDirA] |= 0x7F;
+		}
+		break;
 	}
 }
 
 /*
  * The generic VIA interrupt routines (shamelessly stolen from Alan Cox's
  * via6522.c :-), disable/pending masks added.
- *
- * The new interrupt architecture in macints.c takes care of a lot of the
- * gruntwork for us, including tallying the interrupts and calling the
- * handlers on the linked list. All we need to do here is basically generate
- * the machspec interrupt number after clearing the interrupt.
  */
 
 irqreturn_t via1_irq(int irq, void *dev_id)
 {
-	int irq_bit, i;
-	unsigned char events, mask;
+	int irq_num;
+	unsigned char irq_bit, events;
 
-	mask = via1[vIER] & 0x7F;
-	if (!(events = via1[vIFR] & mask))
+	events = via1[vIFR] & via1[vIER] & 0x7F;
+	if (!events)
 		return IRQ_NONE;
 
-	for (i = 0, irq_bit = 1 ; i < 7 ; i++, irq_bit <<= 1)
+	irq_num = VIA1_SOURCE_BASE;
+	irq_bit = 1;
+	do {
 		if (events & irq_bit) {
-			via1[vIER] = irq_bit;
-			m68k_handle_int(VIA1_SOURCE_BASE + i);
 			via1[vIFR] = irq_bit;
-			via1[vIER] = irq_bit | 0x80;
+			m68k_handle_int(irq_num);
 		}
+		++irq_num;
+		irq_bit <<= 1;
+	} while (events >= irq_bit);
 
 #if 0 /* freakin' pmu is doing weird stuff */
 	if (!oss_present) {
@@ -448,20 +484,23 @@
 
 irqreturn_t via2_irq(int irq, void *dev_id)
 {
-	int irq_bit, i;
-	unsigned char events, mask;
+	int irq_num;
+	unsigned char irq_bit, events;
 
-	mask = via2[gIER] & 0x7F;
-	if (!(events = via2[gIFR] & mask))
+	events = via2[gIFR] & via2[gIER] & 0x7F;
+	if (!events)
 		return IRQ_NONE;
 
-	for (i = 0, irq_bit = 1 ; i < 7 ; i++, irq_bit <<= 1)
+	irq_num = VIA2_SOURCE_BASE;
+	irq_bit = 1;
+	do {
 		if (events & irq_bit) {
-			via2[gIER] = irq_bit;
 			via2[gIFR] = irq_bit | rbv_clear;
-			m68k_handle_int(VIA2_SOURCE_BASE + i);
-			via2[gIER] = irq_bit | 0x80;
+			m68k_handle_int(irq_num);
 		}
+		++irq_num;
+		irq_bit <<= 1;
+	} while (events >= irq_bit);
 	return IRQ_HANDLED;
 }
 
@@ -472,71 +511,75 @@
 
 irqreturn_t via_nubus_irq(int irq, void *dev_id)
 {
-	int irq_bit, i;
-	unsigned char events;
+	int slot_irq;
+	unsigned char slot_bit, events;
 
-	if (!(events = ~via2[gBufA] & nubus_active))
+	events = ~via2[gBufA] & 0x7F;
+	if (rbv_present)
+		events &= via2[rSIER];
+	else
+		events &= ~via2[vDirA];
+	if (!events)
 		return IRQ_NONE;
 
-	for (i = 0, irq_bit = 1 ; i < 7 ; i++, irq_bit <<= 1) {
-		if (events & irq_bit) {
-			via_irq_disable(NUBUS_SOURCE_BASE + i);
-			m68k_handle_int(NUBUS_SOURCE_BASE + i);
-			via_irq_enable(NUBUS_SOURCE_BASE + i);
-		}
-	}
+	do {
+		slot_irq = IRQ_NUBUS_F;
+		slot_bit = 0x40;
+		do {
+			if (events & slot_bit) {
+				events &= ~slot_bit;
+				m68k_handle_int(slot_irq);
+			}
+			--slot_irq;
+			slot_bit >>= 1;
+		} while (events);
+
+ 		/* clear the CA1 interrupt and make certain there's no more. */
+		via2[gIFR] = 0x02 | rbv_clear;
+		events = ~via2[gBufA] & 0x7F;
+		if (rbv_present)
+			events &= via2[rSIER];
+		else
+			events &= ~via2[vDirA];
+	} while (events);
 	return IRQ_HANDLED;
 }
 
 void via_irq_enable(int irq) {
 	int irq_src	= IRQ_SRC(irq);
 	int irq_idx	= IRQ_IDX(irq);
-	int irq_bit	= 1 << irq_idx;
 
 #ifdef DEBUG_IRQUSE
 	printk(KERN_DEBUG "via_irq_enable(%d)\n", irq);
 #endif
 
 	if (irq_src == 1) {
-		via1[vIER] = irq_bit | 0x80;
+		via1[vIER] = IER_SET_BIT(irq_idx);
 	} else if (irq_src == 2) {
-		/*
-		 * Set vPCR for SCSI interrupts (but not on RBV)
-		 */
-		if ((irq_idx == 0) && !rbv_present) {
-			if (macintosh_config->scsi_type == MAC_SCSI_OLD) {
-				/* CB2 (IRQ) indep. input, positive edge */
-				/* CA2 (DRQ) indep. input, positive edge */
-				via2[vPCR] = 0x66;
-			} else {
-				/* CB2 (IRQ) indep. input, negative edge */
-				/* CA2 (DRQ) indep. input, negative edge */
-				via2[vPCR] = 0x22;
-			}
-		}
-		via2[gIER] = irq_bit | 0x80;
+		if (irq != IRQ_MAC_NUBUS || nubus_disabled == 0)
+			via2[gIER] = IER_SET_BIT(irq_idx);
 	} else if (irq_src == 7) {
-		nubus_active |= irq_bit;
-		if (rbv_present) {
-			/* enable the slot interrupt. SIER works like IER. */
+		switch (macintosh_config->via_type) {
+		case MAC_VIA_II:
+			nubus_disabled &= ~(1 << irq_idx);
+			/* Enable the CA1 interrupt when no slot is disabled. */
+			if (!nubus_disabled)
+				via2[gIER] = IER_SET_BIT(1);
+			break;
+		case MAC_VIA_IIci:
+			/* On RBV, enable the slot interrupt.
+			 * SIER works like IER.
+			 */
 			via2[rSIER] = IER_SET_BIT(irq_idx);
-		} else {
-			/* Make sure the bit is an input, to enable the irq */
-			/* But not on PowerBooks, that's ADB... */
+			break;
+		case MAC_VIA_QUADRA:
+			/* Make the port A line an input to enable the slot irq.
+			 * But not on PowerBooks, that's ADB.
+			 */
 			if ((macintosh_config->adb_type != MAC_ADB_PB1) &&
-			   (macintosh_config->adb_type != MAC_ADB_PB2)) {
-				switch(macintosh_config->ident)
-				{
-					case MAC_MODEL_II:
-					case MAC_MODEL_IIX:
-					case MAC_MODEL_IICX:
-					case MAC_MODEL_SE30:
-						via2[vDirA] &= (~irq_bit | 0xc0);
-						break;
-					default:
-						via2[vDirA] &= ~irq_bit;
-				}
-			}
+			    (macintosh_config->adb_type != MAC_ADB_PB2))
+				via2[vDirA] &= ~(1 << irq_idx);
+			break;
 		}
 	}
 }
@@ -544,29 +587,31 @@
 void via_irq_disable(int irq) {
 	int irq_src	= IRQ_SRC(irq);
 	int irq_idx	= IRQ_IDX(irq);
-	int irq_bit	= 1 << irq_idx;
 
 #ifdef DEBUG_IRQUSE
 	printk(KERN_DEBUG "via_irq_disable(%d)\n", irq);
 #endif
 
 	if (irq_src == 1) {
-		via1[vIER] = irq_bit;
+		via1[vIER] = IER_CLR_BIT(irq_idx);
 	} else if (irq_src == 2) {
-		via2[gIER] = irq_bit;
+		via2[gIER] = IER_CLR_BIT(irq_idx);
 	} else if (irq_src == 7) {
-		if (rbv_present) {
-			/* disable the slot interrupt.  SIER works like IER. */
+		switch (macintosh_config->via_type) {
+		case MAC_VIA_II:
+			nubus_disabled |= 1 << irq_idx;
+			if (nubus_disabled)
+				via2[gIER] = IER_CLR_BIT(1);
+			break;
+		case MAC_VIA_IIci:
 			via2[rSIER] = IER_CLR_BIT(irq_idx);
-		} else {
-			/* disable the nubus irq by changing dir to output */
-			/* except on PMU */
+			break;
+		case MAC_VIA_QUADRA:
 			if ((macintosh_config->adb_type != MAC_ADB_PB1) &&
-			   (macintosh_config->adb_type != MAC_ADB_PB2)) {
-				via2[vDirA] |= irq_bit;
-			}
+			    (macintosh_config->adb_type != MAC_ADB_PB2))
+				via2[vDirA] |= 1 << irq_idx;
+			break;
 		}
-		nubus_active &= ~irq_bit;
 	}
 }
 
@@ -580,7 +625,9 @@
 	} else if (irq_src == 2) {
 		via2[gIFR] = irq_bit | rbv_clear;
 	} else if (irq_src == 7) {
-		/* FIXME: hmm.. */
+		/* FIXME: There is no way to clear an individual nubus slot
+		 * IRQ flag, other than getting the device to do it.
+		 */
 	}
 }
 
@@ -600,6 +647,7 @@
 	} else if (irq_src == 2) {
 		return via2[gIFR] & irq_bit;
 	} else if (irq_src == 7) {
+		/* Always 0 for MAC_VIA_QUADRA if the slot irq is disabled. */
 		return ~via2[gBufA] & irq_bit;
 	}
 	return 0;
diff --git a/arch/m68k/q40/config.c b/arch/m68k/q40/config.c
index 92f873c..476e18e 100644
--- a/arch/m68k/q40/config.c
+++ b/arch/m68k/q40/config.c
@@ -35,35 +35,35 @@
 #include <asm/machdep.h>
 #include <asm/q40_master.h>
 
-extern irqreturn_t q40_process_int (int level, struct pt_regs *regs);
-extern void q40_init_IRQ (void);
+extern irqreturn_t q40_process_int(int level, struct pt_regs *regs);
+extern void q40_init_IRQ(void);
 static void q40_get_model(char *model);
 static int  q40_get_hardware_list(char *buffer);
 extern void q40_sched_init(irq_handler_t handler);
 
-extern unsigned long q40_gettimeoffset (void);
-extern int q40_hwclk (int, struct rtc_time *);
-extern unsigned int q40_get_ss (void);
-extern int q40_set_clock_mmss (unsigned long);
+extern unsigned long q40_gettimeoffset(void);
+extern int q40_hwclk(int, struct rtc_time *);
+extern unsigned int q40_get_ss(void);
+extern int q40_set_clock_mmss(unsigned long);
 static int q40_get_rtc_pll(struct rtc_pll_info *pll);
 static int q40_set_rtc_pll(struct rtc_pll_info *pll);
-extern void q40_reset (void);
+extern void q40_reset(void);
 void q40_halt(void);
 extern void q40_waitbut(void);
-void q40_set_vectors (void);
+void q40_set_vectors(void);
 
-extern void q40_mksound(unsigned int /*freq*/, unsigned int /*ticks*/ );
+extern void q40_mksound(unsigned int /*freq*/, unsigned int /*ticks*/);
 
-extern char m68k_debug_device[];
 static void q40_mem_console_write(struct console *co, const char *b,
-				    unsigned int count);
+				  unsigned int count);
 
 extern int ql_ticks;
 
 static struct console q40_console_driver = {
-	.name =		"debug",
-	.flags =	CON_PRINTBUFFER,
-	.index =	-1,
+	.name	= "debug",
+	.write	= q40_mem_console_write,
+	.flags	= CON_PRINTBUFFER,
+	.index	= -1,
 };
 
 
@@ -74,150 +74,162 @@
 static void q40_mem_console_write(struct console *co, const char *s,
 				  unsigned int count)
 {
-  char *p=(char *)s;
+	const char *p = s;
 
-  if (count<_cpleft)
-    while (count-- >0){
-      *q40_mem_cptr=*p++;
-      q40_mem_cptr+=4;
-      _cpleft--;
-    }
+	if (count < _cpleft) {
+		while (count-- > 0) {
+			*q40_mem_cptr = *p++;
+			q40_mem_cptr += 4;
+			_cpleft--;
+		}
+	}
 }
+
+static int __init q40_debug_setup(char *arg)
+{
+	/* useful for early debugging stages - writes kernel messages into SRAM */
+	if (MACH_IS_Q40 && !strncmp(arg, "mem", 3)) {
+		/*printk("using NVRAM debug, q40_mem_cptr=%p\n",q40_mem_cptr);*/
+		_cpleft = 2000 - ((long)q40_mem_cptr-0xff020000) / 4;
+		register_console(&q40_console_driver);
+	}
+	return 0;
+}
+
+early_param("debug", q40_debug_setup);
+
 #if 0
 void printq40(char *str)
 {
-  int l=strlen(str);
-  char *p=q40_mem_cptr;
+	int l = strlen(str);
+	char *p = q40_mem_cptr;
 
-  while (l-- >0 && _cpleft-- >0)
-    {
-      *p=*str++;
-      p+=4;
-    }
-  q40_mem_cptr=p;
+	while (l-- > 0 && _cpleft-- > 0) {
+		*p = *str++;
+		p += 4;
+	}
+	q40_mem_cptr = p;
 }
 #endif
 
-static int halted=0;
+static int halted;
 
 #ifdef CONFIG_HEARTBEAT
 static void q40_heartbeat(int on)
 {
-  if (halted) return;
+	if (halted)
+		return;
 
-  if (on)
-    Q40_LED_ON();
-  else
-    Q40_LED_OFF();
+	if (on)
+		Q40_LED_ON();
+	else
+		Q40_LED_OFF();
 }
 #endif
 
 void q40_reset(void)
 {
-        halted=1;
-        printk ("\n\n*******************************************\n"
+        halted = 1;
+        printk("\n\n*******************************************\n"
 		"Called q40_reset : press the RESET button!! \n"
 		"*******************************************\n");
 	Q40_LED_ON();
-	while(1) ;
+	while (1)
+		;
 }
 void q40_halt(void)
 {
-        halted=1;
-        printk ("\n\n*******************\n"
-		    "  Called q40_halt\n"
-		    "*******************\n");
+        halted = 1;
+        printk("\n\n*******************\n"
+		   "  Called q40_halt\n"
+		   "*******************\n");
 	Q40_LED_ON();
-	while(1) ;
+	while (1)
+		;
 }
 
 static void q40_get_model(char *model)
 {
-    sprintf(model, "Q40");
+	sprintf(model, "Q40");
 }
 
 /* No hardware options on Q40? */
 
 static int q40_get_hardware_list(char *buffer)
 {
-    *buffer = '\0';
-    return 0;
+	*buffer = '\0';
+	return 0;
 }
 
-static unsigned int serports[]={0x3f8,0x2f8,0x3e8,0x2e8,0};
+static unsigned int serports[] =
+{
+	0x3f8,0x2f8,0x3e8,0x2e8,0
+};
 void q40_disable_irqs(void)
 {
-  unsigned i,j;
+	unsigned i, j;
 
-  j=0;
-  while((i=serports[j++])) outb(0,i+UART_IER);
-  master_outb(0,EXT_ENABLE_REG);
-  master_outb(0,KEY_IRQ_ENABLE_REG);
+	j = 0;
+	while ((i = serports[j++]))
+		outb(0, i + UART_IER);
+	master_outb(0, EXT_ENABLE_REG);
+	master_outb(0, KEY_IRQ_ENABLE_REG);
 }
 
 void __init config_q40(void)
 {
-    mach_sched_init      = q40_sched_init;
+	mach_sched_init = q40_sched_init;
 
-    mach_init_IRQ        = q40_init_IRQ;
-    mach_gettimeoffset   = q40_gettimeoffset;
-    mach_hwclk           = q40_hwclk;
-    mach_get_ss          = q40_get_ss;
-    mach_get_rtc_pll     = q40_get_rtc_pll;
-    mach_set_rtc_pll     = q40_set_rtc_pll;
-    mach_set_clock_mmss	 = q40_set_clock_mmss;
+	mach_init_IRQ = q40_init_IRQ;
+	mach_gettimeoffset = q40_gettimeoffset;
+	mach_hwclk = q40_hwclk;
+	mach_get_ss = q40_get_ss;
+	mach_get_rtc_pll = q40_get_rtc_pll;
+	mach_set_rtc_pll = q40_set_rtc_pll;
+	mach_set_clock_mmss = q40_set_clock_mmss;
 
-    mach_reset		 = q40_reset;
-    mach_get_model       = q40_get_model;
-    mach_get_hardware_list = q40_get_hardware_list;
+	mach_reset = q40_reset;
+	mach_get_model = q40_get_model;
+	mach_get_hardware_list = q40_get_hardware_list;
 
 #if defined(CONFIG_INPUT_M68K_BEEP) || defined(CONFIG_INPUT_M68K_BEEP_MODULE)
-    mach_beep            = q40_mksound;
+	mach_beep = q40_mksound;
 #endif
 #ifdef CONFIG_HEARTBEAT
-    mach_heartbeat = q40_heartbeat;
+	mach_heartbeat = q40_heartbeat;
 #endif
-    mach_halt = q40_halt;
+	mach_halt = q40_halt;
 
-    /* disable a few things that SMSQ might have left enabled */
-    q40_disable_irqs();
+	/* disable a few things that SMSQ might have left enabled */
+	q40_disable_irqs();
 
-    /* no DMA at all, but ide-scsi requires it.. make sure
-     * all physical RAM fits into the boundary - otherwise
-     * allocator may play costly and useless tricks */
-    mach_max_dma_address = 1024*1024*1024;
-
-    /* useful for early debugging stages - writes kernel messages into SRAM */
-    if (!strncmp( m68k_debug_device,"mem",3 ))
-      {
-	/*printk("using NVRAM debug, q40_mem_cptr=%p\n",q40_mem_cptr);*/
-	_cpleft=2000-((long)q40_mem_cptr-0xff020000)/4;
-	q40_console_driver.write = q40_mem_console_write;
-	register_console(&q40_console_driver);
-      }
+	/* no DMA at all, but ide-scsi requires it.. make sure
+	 * all physical RAM fits into the boundary - otherwise
+	 * allocator may play costly and useless tricks */
+	mach_max_dma_address = 1024*1024*1024;
 }
 
 
 int q40_parse_bootinfo(const struct bi_record *rec)
 {
-  return 1;
+	return 1;
 }
 
 
-static inline unsigned char bcd2bin (unsigned char b)
+static inline unsigned char bcd2bin(unsigned char b)
 {
-	return ((b>>4)*10 + (b&15));
+	return (b >> 4) * 10 + (b & 15);
 }
 
-static inline unsigned char bin2bcd (unsigned char b)
+static inline unsigned char bin2bcd(unsigned char b)
 {
-	return (((b/10)*16) + (b%10));
+	return (b / 10) * 16 + (b % 10);
 }
 
 
-unsigned long q40_gettimeoffset (void)
+unsigned long q40_gettimeoffset(void)
 {
-    return 5000*(ql_ticks!=0);
+	return 5000 * (ql_ticks != 0);
 }
 
 
@@ -238,9 +250,9 @@
 
 int q40_hwclk(int op, struct rtc_time *t)
 {
-        if (op)
-	{	/* Write.... */
-	        Q40_RTC_CTRL |= Q40_RTC_WRITE;
+	if (op) {
+		/* Write.... */
+		Q40_RTC_CTRL |= Q40_RTC_WRITE;
 
 		Q40_RTC_SECS = bin2bcd(t->tm_sec);
 		Q40_RTC_MINS = bin2bcd(t->tm_min);
@@ -251,25 +263,23 @@
 		if (t->tm_wday >= 0)
 			Q40_RTC_DOW = bin2bcd(t->tm_wday+1);
 
-	        Q40_RTC_CTRL &= ~(Q40_RTC_WRITE);
-	}
-	else
-	{	/* Read....  */
-	  Q40_RTC_CTRL |= Q40_RTC_READ;
+		Q40_RTC_CTRL &= ~(Q40_RTC_WRITE);
+	} else {
+		/* Read....  */
+		Q40_RTC_CTRL |= Q40_RTC_READ;
 
-	  t->tm_year = bcd2bin (Q40_RTC_YEAR);
-	  t->tm_mon  = bcd2bin (Q40_RTC_MNTH)-1;
-	  t->tm_mday = bcd2bin (Q40_RTC_DATE);
-	  t->tm_hour = bcd2bin (Q40_RTC_HOUR);
-	  t->tm_min  = bcd2bin (Q40_RTC_MINS);
-	  t->tm_sec  = bcd2bin (Q40_RTC_SECS);
+		t->tm_year = bcd2bin (Q40_RTC_YEAR);
+		t->tm_mon  = bcd2bin (Q40_RTC_MNTH)-1;
+		t->tm_mday = bcd2bin (Q40_RTC_DATE);
+		t->tm_hour = bcd2bin (Q40_RTC_HOUR);
+		t->tm_min  = bcd2bin (Q40_RTC_MINS);
+		t->tm_sec  = bcd2bin (Q40_RTC_SECS);
 
-	  Q40_RTC_CTRL &= ~(Q40_RTC_READ);
+		Q40_RTC_CTRL &= ~(Q40_RTC_READ);
 
-	  if (t->tm_year < 70)
-	    t->tm_year += 100;
-	  t->tm_wday = bcd2bin(Q40_RTC_DOW)-1;
-
+		if (t->tm_year < 70)
+			t->tm_year += 100;
+		t->tm_wday = bcd2bin(Q40_RTC_DOW)-1;
 	}
 
 	return 0;
@@ -285,29 +295,25 @@
  * clock is out by > 30 minutes.  Logic lifted from atari code.
  */
 
-int q40_set_clock_mmss (unsigned long nowtime)
+int q40_set_clock_mmss(unsigned long nowtime)
 {
 	int retval = 0;
 	short real_seconds = nowtime % 60, real_minutes = (nowtime / 60) % 60;
 
 	int rtc_minutes;
 
+	rtc_minutes = bcd2bin(Q40_RTC_MINS);
 
-	rtc_minutes = bcd2bin (Q40_RTC_MINS);
-
-	if ((rtc_minutes < real_minutes
-		? real_minutes - rtc_minutes
-			: rtc_minutes - real_minutes) < 30)
-	{
-	        Q40_RTC_CTRL |= Q40_RTC_WRITE;
+	if ((rtc_minutes < real_minutes ?
+	     real_minutes - rtc_minutes :
+	     rtc_minutes - real_minutes) < 30) {
+		Q40_RTC_CTRL |= Q40_RTC_WRITE;
 		Q40_RTC_MINS = bin2bcd(real_minutes);
 		Q40_RTC_SECS = bin2bcd(real_seconds);
 		Q40_RTC_CTRL &= ~(Q40_RTC_WRITE);
-	}
-	else
+	} else
 		retval = -1;
 
-
 	return retval;
 }
 
@@ -318,21 +324,23 @@
 
 static int q40_get_rtc_pll(struct rtc_pll_info *pll)
 {
-	int tmp=Q40_RTC_CTRL;
+	int tmp = Q40_RTC_CTRL;
+
 	pll->pll_value = tmp & Q40_RTC_PLL_MASK;
 	if (tmp & Q40_RTC_PLL_SIGN)
 		pll->pll_value = -pll->pll_value;
-	pll->pll_max=31;
-	pll->pll_min=-31;
-	pll->pll_posmult=512;
-	pll->pll_negmult=256;
-	pll->pll_clock=125829120;
+	pll->pll_max = 31;
+	pll->pll_min = -31;
+	pll->pll_posmult = 512;
+	pll->pll_negmult = 256;
+	pll->pll_clock = 125829120;
+
 	return 0;
 }
 
 static int q40_set_rtc_pll(struct rtc_pll_info *pll)
 {
-	if (!pll->pll_ctrl){
+	if (!pll->pll_ctrl) {
 		/* the docs are a bit unclear so I am doublesetting */
 		/* RTC_WRITE here ... */
 		int tmp = (pll->pll_value & 31) | (pll->pll_value<0 ? 32 : 0) |
diff --git a/arch/m68k/sun3/sun3ints.c b/arch/m68k/sun3/sun3ints.c
index baf74e8..4232a2c 100644
--- a/arch/m68k/sun3/sun3ints.c
+++ b/arch/m68k/sun3/sun3ints.c
@@ -103,7 +103,7 @@
 
 	m68k_setup_auto_interrupt(sun3_inthandle);
 	m68k_setup_irq_controller(&sun3_irq_controller, IRQ_AUTO_1, 7);
-	m68k_setup_user_interrupt(VEC_USER, 192, NULL);
+	m68k_setup_user_interrupt(VEC_USER, 128, NULL);
 
 	request_irq(IRQ_AUTO_5, sun3_int5, 0, "int5", NULL);
 	request_irq(IRQ_AUTO_7, sun3_int7, 0, "int7", NULL);
diff --git a/arch/m68k/sun3x/prom.c b/arch/m68k/sun3x/prom.c
index 574cf06..48f8eb7 100644
--- a/arch/m68k/sun3x/prom.c
+++ b/arch/m68k/sun3x/prom.c
@@ -34,100 +34,101 @@
 /* Handle returning to the prom */
 void sun3x_halt(void)
 {
-    unsigned long flags;
+	unsigned long flags;
 
-    /* Disable interrupts while we mess with things */
-    local_irq_save(flags);
+	/* Disable interrupts while we mess with things */
+	local_irq_save(flags);
 
-    /* Restore prom vbr */
-    __asm__ volatile ("movec %0,%%vbr" : : "r" ((void*)sun3x_prom_vbr));
+	/* Restore prom vbr */
+	asm volatile ("movec %0,%%vbr" : : "r" ((void*)sun3x_prom_vbr));
 
-    /* Restore prom NMI clock */
-//    sun3x_disable_intreg(5);
-    sun3_enable_irq(7);
+	/* Restore prom NMI clock */
+//	sun3x_disable_intreg(5);
+	sun3_enable_irq(7);
 
-    /* Let 'er rip */
-    __asm__ volatile ("trap #14" : : );
+	/* Let 'er rip */
+	asm volatile ("trap #14");
 
-    /* Restore everything */
-    sun3_disable_irq(7);
-    sun3_enable_irq(5);
+	/* Restore everything */
+	sun3_disable_irq(7);
+	sun3_enable_irq(5);
 
-    __asm__ volatile ("movec %0,%%vbr" : : "r" ((void*)vectors));
-    local_irq_restore(flags);
+	asm volatile ("movec %0,%%vbr" : : "r" ((void*)vectors));
+	local_irq_restore(flags);
 }
 
 void sun3x_reboot(void)
 {
-    /* This never returns, don't bother saving things */
-    local_irq_disable();
+	/* This never returns, don't bother saving things */
+	local_irq_disable();
 
-    /* Restore prom vbr */
-    __asm__ volatile ("movec %0,%%vbr" : : "r" ((void*)sun3x_prom_vbr));
+	/* Restore prom vbr */
+	asm volatile ("movec %0,%%vbr" : : "r" ((void*)sun3x_prom_vbr));
 
-    /* Restore prom NMI clock */
-    sun3_disable_irq(5);
-    sun3_enable_irq(7);
+	/* Restore prom NMI clock */
+	sun3_disable_irq(5);
+	sun3_enable_irq(7);
 
-    /* Let 'er rip */
-    (*romvec->pv_reboot)("vmlinux");
+	/* Let 'er rip */
+	(*romvec->pv_reboot)("vmlinux");
 }
 
-extern char m68k_debug_device[];
-
 static void sun3x_prom_write(struct console *co, const char *s,
                              unsigned int count)
 {
-    while (count--) {
-        if (*s == '\n')
-            sun3x_putchar('\r');
-        sun3x_putchar(*s++);
-    }
+	while (count--) {
+		if (*s == '\n')
+			sun3x_putchar('\r');
+		sun3x_putchar(*s++);
+	}
 }
 
 /* debug console - write-only */
 
 static struct console sun3x_debug = {
-	.name  =	"debug",
-	.write =	sun3x_prom_write,
-	.flags =	CON_PRINTBUFFER,
-	.index =	-1,
+	.name	= "debug",
+	.write	= sun3x_prom_write,
+	.flags	= CON_PRINTBUFFER,
+	.index	= -1,
 };
 
 void sun3x_prom_init(void)
 {
-    /* Read the vector table */
+	/* Read the vector table */
 
-    sun3x_putchar = *(void (**)(int)) (SUN3X_P_PUTCHAR);
-    sun3x_getchar = *(int (**)(void)) (SUN3X_P_GETCHAR);
-    sun3x_mayget = *(int (**)(void))  (SUN3X_P_MAYGET);
-    sun3x_mayput = *(int (**)(int))   (SUN3X_P_MAYPUT);
-    sun3x_prom_reboot = *(void (**)(void)) (SUN3X_P_REBOOT);
-    sun3x_prom_abort = *(e_vector *)  (SUN3X_P_ABORT);
-    romvec = (struct linux_romvec *)SUN3X_PROM_BASE;
+	sun3x_putchar = *(void (**)(int)) (SUN3X_P_PUTCHAR);
+	sun3x_getchar = *(int (**)(void)) (SUN3X_P_GETCHAR);
+	sun3x_mayget = *(int (**)(void))  (SUN3X_P_MAYGET);
+	sun3x_mayput = *(int (**)(int))   (SUN3X_P_MAYPUT);
+	sun3x_prom_reboot = *(void (**)(void)) (SUN3X_P_REBOOT);
+	sun3x_prom_abort = *(e_vector *)  (SUN3X_P_ABORT);
+	romvec = (struct linux_romvec *)SUN3X_PROM_BASE;
 
-    idprom_init();
+	idprom_init();
 
-    if(!((idprom->id_machtype & SM_ARCH_MASK) == SM_SUN3X)) {
-	    printk("Warning: machine reports strange type %02x\n",
-		   idprom->id_machtype);
-	    printk("Pretending it's a 3/80, but very afraid...\n");
-	    idprom->id_machtype = SM_SUN3X | SM_3_80;
-    }
+	if (!((idprom->id_machtype & SM_ARCH_MASK) == SM_SUN3X)) {
+		printk("Warning: machine reports strange type %02x\n",
+			idprom->id_machtype);
+		printk("Pretending it's a 3/80, but very afraid...\n");
+		idprom->id_machtype = SM_SUN3X | SM_3_80;
+	}
 
-    /* point trap #14 at abort.
-     * XXX this is futile since we restore the vbr first - oops
-     */
-    vectors[VEC_TRAP14] = sun3x_prom_abort;
-
-    /* If debug=prom was specified, start the debug console */
-
-    if (!strcmp(m68k_debug_device, "prom"))
-        register_console(&sun3x_debug);
-
-
+	/* point trap #14 at abort.
+	 * XXX this is futile since we restore the vbr first - oops
+	 */
+	vectors[VEC_TRAP14] = sun3x_prom_abort;
 }
 
+static int __init sun3x_debug_setup(char *arg)
+{
+	/* If debug=prom was specified, start the debug console */
+	if (MACH_IS_SUN3X && !strcmp(arg, "prom"))
+		register_console(&sun3x_debug);
+	return 0;
+}
+
+early_param("debug", sun3x_debug_setup);
+
 /* some prom functions to export */
 int prom_getintdefault(int node, char *property, int deflt)
 {
@@ -141,7 +142,6 @@
 
 void prom_printf(char *fmt, ...)
 {
-
 }
 
 void prom_halt (void)
@@ -159,7 +159,7 @@
         int i;
 
 	/* make a copy of the idprom structure */
-	for(i = 0; i < num_bytes; i++)
+	for (i = 0; i < num_bytes; i++)
 		idbuf[i] = ((char *)SUN3X_IDPROM)[i];
 
         return idbuf[0];
diff --git a/arch/m68knommu/kernel/dma.c b/arch/m68knommu/kernel/dma.c
index 14b19c4..0a25874a 100644
--- a/arch/m68knommu/kernel/dma.c
+++ b/arch/m68knommu/kernel/dma.c
@@ -8,7 +8,6 @@
 #include <linux/types.h>
 #include <linux/mm.h>
 #include <linux/string.h>
-#include <linux/pci.h>
 #include <asm/io.h>
 
 void *dma_alloc_coherent(struct device *dev, size_t size,
diff --git a/arch/mips/cobalt/Makefile b/arch/mips/cobalt/Makefile
index de017c1..9565b21 100644
--- a/arch/mips/cobalt/Makefile
+++ b/arch/mips/cobalt/Makefile
@@ -2,7 +2,7 @@
 # Makefile for the Cobalt micro systems family specific parts of the kernel
 #
 
-obj-y	 := irq.o reset.o setup.o
+obj-y	 := irq.o reset.o setup.o buttons.o
 
 obj-$(CONFIG_PCI)		+= pci.o
 obj-$(CONFIG_EARLY_PRINTK)	+= console.o
diff --git a/arch/mips/cobalt/buttons.c b/arch/mips/cobalt/buttons.c
new file mode 100644
index 0000000..9e14398
--- /dev/null
+++ b/arch/mips/cobalt/buttons.c
@@ -0,0 +1,54 @@
+/*
+ *  Cobalt buttons platform device.
+ *
+ *  Copyright (C) 2007  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/platform_device.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+
+static struct resource cobalt_buttons_resource __initdata = {
+	.start	= 0x1d000000,
+	.end	= 0x1d000003,
+	.flags	= IORESOURCE_MEM,
+};
+
+static __init int cobalt_add_buttons(void)
+{
+	struct platform_device *pd;
+	int error;
+
+	pd = platform_device_alloc("Cobalt buttons", -1);
+	if (!pd)
+		return -ENOMEM;
+
+	error = platform_device_add_resources(pd, &cobalt_buttons_resource, 1);
+	if (error)
+		goto err_free_device;
+
+	error = platform_device_add(pd);
+	if (error)
+		goto err_free_device;
+
+	return 0;
+
+ err_free_device:
+	platform_device_put(pd);
+	return error;
+}
+device_initcall(cobalt_add_buttons);
diff --git a/arch/mips/lib/iomap.c b/arch/mips/lib/iomap.c
index d51d5cb..e3acb2d 100644
--- a/arch/mips/lib/iomap.c
+++ b/arch/mips/lib/iomap.c
@@ -6,7 +6,6 @@
  * (C) Copyright 2007 MIPS Technologies, Inc.
  *     written by Ralf Baechle <ralf@linux-mips.org>
  */
-#include <linux/pci.h>
 #include <linux/module.h>
 #include <asm/io.h>
 
diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c
index 60d7d4b..7138092 100644
--- a/arch/powerpc/kernel/pci_64.c
+++ b/arch/powerpc/kernel/pci_64.c
@@ -340,7 +340,7 @@
 	struct pci_dev *dev;
 	const char *type;
 
-	dev = kzalloc(sizeof(struct pci_dev), GFP_KERNEL);
+	dev = alloc_pci_dev();
 	if (!dev)
 		return NULL;
 	type = of_get_property(node, "device_type", NULL);
diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c
index 9eaefac..b2c1b67a 100644
--- a/arch/powerpc/kernel/vio.c
+++ b/arch/powerpc/kernel/vio.c
@@ -37,7 +37,7 @@
 #include <asm/iseries/hv_call_xm.h>
 #include <asm/iseries/iommu.h>
 
-extern struct subsystem devices_subsys; /* needed for vio_find_name() */
+extern struct kset devices_subsys; /* needed for vio_find_name() */
 
 static struct vio_dev vio_bus_device  = { /* fake "parent" device */
 	.name = vio_bus_device.dev.bus_id,
@@ -427,7 +427,7 @@
 {
 	struct kobject *found;
 
-	found = kset_find_obj(&devices_subsys.kset, kobj_name);
+	found = kset_find_obj(&devices_subsys, kobj_name);
 	if (!found)
 		return NULL;
 
diff --git a/arch/powerpc/platforms/powermac/cpufreq_32.c b/arch/powerpc/platforms/powermac/cpufreq_32.c
index 8943a94..1fe35da 100644
--- a/arch/powerpc/platforms/powermac/cpufreq_32.c
+++ b/arch/powerpc/platforms/powermac/cpufreq_32.c
@@ -25,7 +25,6 @@
 #include <linux/cpufreq.h>
 #include <linux/init.h>
 #include <linux/sysdev.h>
-#include <linux/i2c.h>
 #include <linux/hardirq.h>
 #include <asm/prom.h>
 #include <asm/machdep.h>
diff --git a/arch/powerpc/platforms/pseries/power.c b/arch/powerpc/platforms/pseries/power.c
index 2624b71..73e6902 100644
--- a/arch/powerpc/platforms/pseries/power.c
+++ b/arch/powerpc/platforms/pseries/power.c
@@ -28,13 +28,13 @@
 
 unsigned long rtas_poweron_auto; /* default and normal state is 0 */
 
-static ssize_t auto_poweron_show(struct subsystem *subsys, char *buf)
+static ssize_t auto_poweron_show(struct kset *kset, char *buf)
 {
         return sprintf(buf, "%lu\n", rtas_poweron_auto);
 }
 
 static ssize_t
-auto_poweron_store(struct subsystem *subsys, const char *buf, size_t n)
+auto_poweron_store(struct kset *kset, const char *buf, size_t n)
 {
 	int ret;
 	unsigned long ups_restart;
@@ -72,12 +72,12 @@
 {
         int error = subsystem_register(&power_subsys);
         if (!error)
-                error = sysfs_create_group(&power_subsys.kset.kobj,&attr_group);
+                error = sysfs_create_group(&power_subsys.kobj, &attr_group);
         return error;
 }
 core_initcall(pm_init);
 #else
-extern struct subsystem power_subsys;
+extern struct kset power_subsys;
 
 static int __init apo_pm_init(void)
 {
diff --git a/arch/powerpc/platforms/pseries/ras.c b/arch/powerpc/platforms/pseries/ras.c
index 53aa041..3a393c7 100644
--- a/arch/powerpc/platforms/pseries/ras.c
+++ b/arch/powerpc/platforms/pseries/ras.c
@@ -31,7 +31,6 @@
 #include <linux/timex.h>
 #include <linux/init.h>
 #include <linux/slab.h>
-#include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/irq.h>
 #include <linux/random.h>
diff --git a/arch/ppc/8260_io/enet.c b/arch/ppc/8260_io/enet.c
index 48ce84f..4c0a7d7 100644
--- a/arch/ppc/8260_io/enet.c
+++ b/arch/ppc/8260_io/enet.c
@@ -32,7 +32,6 @@
 #include <linux/ioport.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
-#include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/netdevice.h>
diff --git a/arch/ppc/8260_io/fcc_enet.c b/arch/ppc/8260_io/fcc_enet.c
index 9db825f..cab395d 100644
--- a/arch/ppc/8260_io/fcc_enet.c
+++ b/arch/ppc/8260_io/fcc_enet.c
@@ -29,7 +29,6 @@
 #include <linux/ioport.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
-#include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/netdevice.h>
diff --git a/arch/ppc/8xx_io/enet.c b/arch/ppc/8xx_io/enet.c
index bfa3f52..e58288e 100644
--- a/arch/ppc/8xx_io/enet.c
+++ b/arch/ppc/8xx_io/enet.c
@@ -30,7 +30,6 @@
 #include <linux/ioport.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
-#include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/netdevice.h>
diff --git a/arch/ppc/syslib/ppc4xx_sgdma.c b/arch/ppc/syslib/ppc4xx_sgdma.c
index 939abe3..5dadca3e 100644
--- a/arch/ppc/syslib/ppc4xx_sgdma.c
+++ b/arch/ppc/syslib/ppc4xx_sgdma.c
@@ -23,7 +23,6 @@
 #include <linux/mm.h>
 #include <linux/init.h>
 #include <linux/module.h>
-#include <linux/pci.h>
 
 #include <asm/system.h>
 #include <asm/io.h>
diff --git a/arch/s390/appldata/appldata_net_sum.c b/arch/s390/appldata/appldata_net_sum.c
index a43f348..2180ac1 100644
--- a/arch/s390/appldata/appldata_net_sum.c
+++ b/arch/s390/appldata/appldata_net_sum.c
@@ -107,7 +107,7 @@
 	tx_dropped = 0;
 	collisions = 0;
 	read_lock(&dev_base_lock);
-	for (dev = dev_base; dev != NULL; dev = dev->next) {
+	for_each_netdev(dev) {
 		stats = dev->get_stats(dev);
 		rx_packets += stats->rx_packets;
 		tx_packets += stats->tx_packets;
diff --git a/arch/s390/crypto/aes_s390.c b/arch/s390/crypto/aes_s390.c
index 9163635..3660ca6 100644
--- a/arch/s390/crypto/aes_s390.c
+++ b/arch/s390/crypto/aes_s390.c
@@ -119,7 +119,8 @@
 	.cra_name		=	"aes",
 	.cra_driver_name	=	"aes-s390",
 	.cra_priority		=	CRYPT_S390_PRIORITY,
-	.cra_flags		=	CRYPTO_ALG_TYPE_CIPHER,
+	.cra_flags		=	CRYPTO_ALG_TYPE_CIPHER |
+					CRYPTO_ALG_NEED_FALLBACK,
 	.cra_blocksize		=	AES_BLOCK_SIZE,
 	.cra_ctxsize		=	sizeof(struct s390_aes_ctx),
 	.cra_module		=	THIS_MODULE,
@@ -206,7 +207,8 @@
 	.cra_name		=	"ecb(aes)",
 	.cra_driver_name	=	"ecb-aes-s390",
 	.cra_priority		=	CRYPT_S390_COMPOSITE_PRIORITY,
-	.cra_flags		=	CRYPTO_ALG_TYPE_BLKCIPHER,
+	.cra_flags		=	CRYPTO_ALG_TYPE_BLKCIPHER |
+					CRYPTO_ALG_NEED_FALLBACK,
 	.cra_blocksize		=	AES_BLOCK_SIZE,
 	.cra_ctxsize		=	sizeof(struct s390_aes_ctx),
 	.cra_type		=	&crypto_blkcipher_type,
@@ -300,7 +302,8 @@
 	.cra_name		=	"cbc(aes)",
 	.cra_driver_name	=	"cbc-aes-s390",
 	.cra_priority		=	CRYPT_S390_COMPOSITE_PRIORITY,
-	.cra_flags		=	CRYPTO_ALG_TYPE_BLKCIPHER,
+	.cra_flags		=	CRYPTO_ALG_TYPE_BLKCIPHER |
+					CRYPTO_ALG_NEED_FALLBACK,
 	.cra_blocksize		=	AES_BLOCK_SIZE,
 	.cra_ctxsize		=	sizeof(struct s390_aes_ctx),
 	.cra_type		=	&crypto_blkcipher_type,
@@ -333,10 +336,14 @@
 		return -EOPNOTSUPP;
 
 	/* z9 109 and z9 BC/EC only support 128 bit key length */
-	if (keylen_flag == AES_KEYLEN_128)
+	if (keylen_flag == AES_KEYLEN_128) {
+		aes_alg.cra_u.cipher.cia_max_keysize = AES_MIN_KEY_SIZE;
+		ecb_aes_alg.cra_u.blkcipher.max_keysize = AES_MIN_KEY_SIZE;
+		cbc_aes_alg.cra_u.blkcipher.max_keysize = AES_MIN_KEY_SIZE;
 		printk(KERN_INFO
 		       "aes_s390: hardware acceleration only available for"
 		       "128 bit keys\n");
+	}
 
 	ret = crypto_register_alg(&aes_alg);
 	if (ret)
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c
index 06833ac..0ea048d 100644
--- a/arch/s390/kernel/ipl.c
+++ b/arch/s390/kernel/ipl.c
@@ -164,7 +164,7 @@
 /* SYSFS */
 
 #define DEFINE_IPL_ATTR_RO(_prefix, _name, _format, _value)		\
-static ssize_t sys_##_prefix##_##_name##_show(struct subsystem *subsys,	\
+static ssize_t sys_##_prefix##_##_name##_show(struct kset *kset,	\
 		char *page)						\
 {									\
 	return sprintf(page, _format, _value);				\
@@ -173,13 +173,13 @@
 	__ATTR(_name, S_IRUGO, sys_##_prefix##_##_name##_show, NULL);
 
 #define DEFINE_IPL_ATTR_RW(_prefix, _name, _fmt_out, _fmt_in, _value)	\
-static ssize_t sys_##_prefix##_##_name##_show(struct subsystem *subsys,	\
+static ssize_t sys_##_prefix##_##_name##_show(struct kset *kset,	\
 		char *page)						\
 {									\
 	return sprintf(page, _fmt_out,					\
 			(unsigned long long) _value);			\
 }									\
-static ssize_t sys_##_prefix##_##_name##_store(struct subsystem *subsys,\
+static ssize_t sys_##_prefix##_##_name##_store(struct kset *kset,	\
 		const char *buf, size_t len)				\
 {									\
 	unsigned long long value;					\
@@ -194,12 +194,12 @@
 			sys_##_prefix##_##_name##_store);
 
 #define DEFINE_IPL_ATTR_STR_RW(_prefix, _name, _fmt_out, _fmt_in, _value)\
-static ssize_t sys_##_prefix##_##_name##_show(struct subsystem *subsys,	\
+static ssize_t sys_##_prefix##_##_name##_show(struct kset *kset,	\
 		char *page)						\
 {									\
 	return sprintf(page, _fmt_out, _value);				\
 }									\
-static ssize_t sys_##_prefix##_##_name##_store(struct subsystem *subsys,\
+static ssize_t sys_##_prefix##_##_name##_store(struct kset *kset,	\
 		const char *buf, size_t len)				\
 {									\
 	if (sscanf(buf, _fmt_in, _value) != 1)				\
@@ -272,14 +272,14 @@
 struct ipl_info ipl_info;
 EXPORT_SYMBOL_GPL(ipl_info);
 
-static ssize_t ipl_type_show(struct subsystem *subsys, char *page)
+static ssize_t ipl_type_show(struct kset *kset, char *page)
 {
 	return sprintf(page, "%s\n", ipl_type_str(ipl_info.type));
 }
 
 static struct subsys_attribute sys_ipl_type_attr = __ATTR_RO(ipl_type);
 
-static ssize_t sys_ipl_device_show(struct subsystem *subsys, char *page)
+static ssize_t sys_ipl_device_show(struct kset *kset, char *page)
 {
 	struct ipl_parameter_block *ipl = IPL_PARMBLOCK_START;
 
@@ -371,7 +371,7 @@
 
 /* CCW ipl device attributes */
 
-static ssize_t ipl_ccw_loadparm_show(struct subsystem *subsys, char *page)
+static ssize_t ipl_ccw_loadparm_show(struct kset *kset, char *page)
 {
 	char loadparm[LOADPARM_LEN + 1] = {};
 
@@ -469,7 +469,7 @@
 	strstrip(loadparm);
 }
 
-static ssize_t reipl_ccw_loadparm_show(struct subsystem *subsys, char *page)
+static ssize_t reipl_ccw_loadparm_show(struct kset *kset, char *page)
 {
 	char buf[LOADPARM_LEN + 1];
 
@@ -477,7 +477,7 @@
 	return sprintf(page, "%s\n", buf);
 }
 
-static ssize_t reipl_ccw_loadparm_store(struct subsystem *subsys,
+static ssize_t reipl_ccw_loadparm_store(struct kset *kset,
 					const char *buf, size_t len)
 {
 	int i, lp_len;
@@ -572,12 +572,12 @@
 	return 0;
 }
 
-static ssize_t reipl_type_show(struct subsystem *subsys, char *page)
+static ssize_t reipl_type_show(struct kset *kset, char *page)
 {
 	return sprintf(page, "%s\n", ipl_type_str(reipl_type));
 }
 
-static ssize_t reipl_type_store(struct subsystem *subsys, const char *buf,
+static ssize_t reipl_type_store(struct kset *kset, const char *buf,
 				size_t len)
 {
 	int rc = -EINVAL;
@@ -665,12 +665,12 @@
 	return 0;
 }
 
-static ssize_t dump_type_show(struct subsystem *subsys, char *page)
+static ssize_t dump_type_show(struct kset *kset, char *page)
 {
 	return sprintf(page, "%s\n", dump_type_str(dump_type));
 }
 
-static ssize_t dump_type_store(struct subsystem *subsys, const char *buf,
+static ssize_t dump_type_store(struct kset *kset, const char *buf,
 			       size_t len)
 {
 	int rc = -EINVAL;
@@ -697,12 +697,12 @@
 
 /* on panic */
 
-static ssize_t on_panic_show(struct subsystem *subsys, char *page)
+static ssize_t on_panic_show(struct kset *kset, char *page)
 {
 	return sprintf(page, "%s\n", shutdown_action_str(on_panic_action));
 }
 
-static ssize_t on_panic_store(struct subsystem *subsys, const char *buf,
+static ssize_t on_panic_store(struct kset *kset, const char *buf,
 			      size_t len)
 {
 	if (strncmp(buf, SHUTDOWN_REIPL_STR, strlen(SHUTDOWN_REIPL_STR)) == 0)
diff --git a/arch/s390/kernel/kprobes.c b/arch/s390/kernel/kprobes.c
index 993f353..23c61f6 100644
--- a/arch/s390/kernel/kprobes.c
+++ b/arch/s390/kernel/kprobes.c
@@ -516,7 +516,7 @@
 	return 1;
 }
 
-static int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
+int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
 {
 	struct kprobe *cur = kprobe_running();
 	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
@@ -603,7 +603,6 @@
 			ret = NOTIFY_STOP;
 		break;
 	case DIE_TRAP:
-	case DIE_PAGE_FAULT:
 		/* kprobe_running() needs smp_processor_id() */
 		preempt_disable();
 		if (kprobe_running() &&
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index 3dfd098..6bfb088 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -65,7 +65,7 @@
  * User copy operations.
  */
 struct uaccess_ops uaccess;
-EXPORT_SYMBOL_GPL(uaccess);
+EXPORT_SYMBOL(uaccess);
 
 /*
  * Machine setup..
@@ -74,6 +74,8 @@
 unsigned int console_devno = -1;
 unsigned int console_irq = -1;
 unsigned long machine_flags = 0;
+unsigned long elf_hwcap = 0;
+char elf_platform[ELF_PLATFORM_SIZE];
 
 struct mem_chunk __initdata memory_chunk[MEMORY_CHUNKS];
 volatile int __cpu_logical_map[NR_CPUS]; /* logical cpu to cpu address */
@@ -749,6 +751,98 @@
 #endif
 }
 
+static __init unsigned int stfl(void)
+{
+	asm volatile(
+		"	.insn	s,0xb2b10000,0(0)\n" /* stfl */
+		"0:\n"
+		EX_TABLE(0b,0b));
+	return S390_lowcore.stfl_fac_list;
+}
+
+static __init int stfle(unsigned long long *list, int doublewords)
+{
+	typedef struct { unsigned long long _[doublewords]; } addrtype;
+	register unsigned long __nr asm("0") = doublewords - 1;
+
+	asm volatile(".insn s,0xb2b00000,%0" /* stfle */
+		     : "=m" (*(addrtype *) list), "+d" (__nr) : : "cc");
+	return __nr + 1;
+}
+
+/*
+ * Setup hardware capabilities.
+ */
+static void __init setup_hwcaps(void)
+{
+	static const int stfl_bits[6] = { 0, 2, 7, 17, 19, 21 };
+	struct cpuinfo_S390 *cpuinfo = &S390_lowcore.cpu_data;
+	unsigned long long facility_list_extended;
+	unsigned int facility_list;
+	int i;
+
+	facility_list = stfl();
+	/*
+	 * The store facility list bits numbers as found in the principles
+	 * of operation are numbered with bit 1UL<<31 as number 0 to
+	 * bit 1UL<<0 as number 31.
+	 *   Bit 0: instructions named N3, "backported" to esa-mode
+	 *   Bit 2: z/Architecture mode is active
+	 *   Bit 7: the store-facility-list-extended facility is installed
+	 *   Bit 17: the message-security assist is installed
+	 *   Bit 19: the long-displacement facility is installed
+	 *   Bit 21: the extended-immediate facility is installed
+	 * These get translated to:
+	 *   HWCAP_S390_ESAN3 bit 0, HWCAP_S390_ZARCH bit 1,
+	 *   HWCAP_S390_STFLE bit 2, HWCAP_S390_MSA bit 3,
+	 *   HWCAP_S390_LDISP bit 4, and HWCAP_S390_EIMM bit 5.
+	 */
+	for (i = 0; i < 6; i++)
+		if (facility_list & (1UL << (31 - stfl_bits[i])))
+			elf_hwcap |= 1UL << i;
+
+	/*
+	 * Check for additional facilities with store-facility-list-extended.
+	 * stfle stores doublewords (8 byte) with bit 1ULL<<63 as bit 0
+	 * and 1ULL<<0 as bit 63. Bits 0-31 contain the same information
+	 * as stored by stfl, bits 32-xxx contain additional facilities.
+	 * How many facility words are stored depends on the number of
+	 * doublewords passed to the instruction. The additional facilites
+	 * are:
+	 *   Bit 43: decimal floating point facility is installed
+	 * translated to:
+	 *   HWCAP_S390_DFP bit 6.
+	 */
+	if ((elf_hwcap & (1UL << 2)) &&
+	    stfle(&facility_list_extended, 1) > 0) {
+		if (facility_list_extended & (1ULL << (64 - 43)))
+			elf_hwcap |= 1UL << 6;
+	}
+
+	switch (cpuinfo->cpu_id.machine) {
+	case 0x9672:
+#if !defined(CONFIG_64BIT)
+	default:	/* Use "g5" as default for 31 bit kernels. */
+#endif
+		strcpy(elf_platform, "g5");
+		break;
+	case 0x2064:
+	case 0x2066:
+#if defined(CONFIG_64BIT)
+	default:	/* Use "z900" as default for 64 bit kernels. */
+#endif
+		strcpy(elf_platform, "z900");
+		break;
+	case 0x2084:
+	case 0x2086:
+		strcpy(elf_platform, "z990");
+		break;
+	case 0x2094:
+		strcpy(elf_platform, "z9-109");
+		break;
+	}
+}
+
 /*
  * Setup function called from init/main.c just after the banner
  * was printed.
@@ -805,6 +899,11 @@
 	smp_setup_cpu_possible_map();
 
 	/*
+	 * Setup capabilities (ELF_HWCAP & ELF_PLATFORM).
+	 */
+	setup_hwcaps();
+
+	/*
 	 * Create kernel page tables and switch to virtual addressing.
 	 */
         paging_init();
@@ -839,8 +938,12 @@
 
 static int show_cpuinfo(struct seq_file *m, void *v)
 {
+	static const char *hwcap_str[7] = {
+		"esan3", "zarch", "stfle", "msa", "ldisp", "eimm", "dfp"
+	};
         struct cpuinfo_S390 *cpuinfo;
 	unsigned long n = (unsigned long) v - 1;
+	int i;
 
 	s390_adjust_jiffies();
 	preempt_disable();
@@ -850,7 +953,13 @@
 			       "bogomips per cpu: %lu.%02lu\n",
 			       num_online_cpus(), loops_per_jiffy/(500000/HZ),
 			       (loops_per_jiffy/(5000/HZ))%100);
+		seq_puts(m, "features\t: ");
+		for (i = 0; i < 7; i++)
+			if (hwcap_str[i] && (elf_hwcap & (1UL << i)))
+				seq_printf(m, "%s ", hwcap_str[i]);
+		seq_puts(m, "\n");
 	}
+
 	if (cpu_online(n)) {
 #ifdef CONFIG_SMP
 		if (smp_processor_id() == n)
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c
index 2b76a87..91f705a 100644
--- a/arch/s390/mm/fault.c
+++ b/arch/s390/mm/fault.c
@@ -52,38 +52,24 @@
 extern void die(const char *,struct pt_regs *,long);
 
 #ifdef CONFIG_KPROBES
-static ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain);
-int register_page_fault_notifier(struct notifier_block *nb)
-{
-	return atomic_notifier_chain_register(&notify_page_fault_chain, nb);
-}
-
-int unregister_page_fault_notifier(struct notifier_block *nb)
-{
-	return atomic_notifier_chain_unregister(&notify_page_fault_chain, nb);
-}
-
-static int __kprobes __notify_page_fault(struct pt_regs *regs, long err)
-{
-	struct die_args args = { .str = "page fault",
-				 .trapnr = 14,
-				 .signr = SIGSEGV };
-	args.regs = regs;
-	args.err = err;
-	return atomic_notifier_call_chain(&notify_page_fault_chain,
-					  DIE_PAGE_FAULT, &args);
-}
-
 static inline int notify_page_fault(struct pt_regs *regs, long err)
 {
-	if (unlikely(kprobe_running()))
-		return __notify_page_fault(regs, err);
-	return NOTIFY_DONE;
+	int ret = 0;
+
+	/* kprobe_running() needs smp_processor_id() */
+	if (!user_mode(regs)) {
+		preempt_disable();
+		if (kprobe_running() && kprobe_fault_handler(regs, 14))
+			ret = 1;
+		preempt_enable();
+	}
+
+	return ret;
 }
 #else
 static inline int notify_page_fault(struct pt_regs *regs, long err)
 {
-	return NOTIFY_DONE;
+	return 0;
 }
 #endif
 
@@ -319,7 +305,7 @@
 	int space;
 	int si_code;
 
-	if (notify_page_fault(regs, error_code) == NOTIFY_STOP)
+	if (notify_page_fault(regs, error_code))
 		return;
 
 	tsk = current;
diff --git a/arch/sh64/mach-cayman/iomap.c b/arch/sh64/mach-cayman/iomap.c
index 2d06e9a..a5c645f 100644
--- a/arch/sh64/mach-cayman/iomap.c
+++ b/arch/sh64/mach-cayman/iomap.c
@@ -9,7 +9,6 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  */
-#include <linux/pci.h>
 #include <asm/io.h>
 #include <asm/cayman.h>
 
diff --git a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig
index 590a41b..be9e10b 100644
--- a/arch/sparc64/Kconfig
+++ b/arch/sparc64/Kconfig
@@ -306,6 +306,7 @@
 
 config PCI
 	bool "PCI support"
+	select ARCH_SUPPORTS_MSI
 	help
 	  Find out whether you have a PCI motherboard. PCI is the name of a
 	  bus system, i.e. the way the CPU talks to the other stuff inside
diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c
index 023af41..9a54954 100644
--- a/arch/sparc64/kernel/pci.c
+++ b/arch/sparc64/kernel/pci.c
@@ -1092,10 +1092,10 @@
 		return -EINVAL;
 
 	err = p->setup_msi_irq(&virt_irq, pdev, desc);
-	if (err < 0)
+	if (err)
 		return err;
 
-	return virt_irq;
+	return 0;
 }
 
 void arch_teardown_msi_irq(unsigned int virt_irq)
diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c
index 94295c2..1ccf4c9 100644
--- a/arch/sparc64/kernel/pci_sun4v.c
+++ b/arch/sparc64/kernel/pci_sun4v.c
@@ -1169,8 +1169,6 @@
 	if (!devino)
 		goto out_err;
 
-	set_irq_msi(*virt_irq_p, entry);
-
 	msiqid = ((devino - pbm->msiq_first_devino) +
 		  pbm->msiq_first);
 
@@ -1204,6 +1202,8 @@
 		msg.address_lo = pbm->msi32_start;
 	}
 	msg.data = msi_num;
+
+	set_irq_msi(*virt_irq_p, entry);
 	write_msi_msg(*virt_irq_p, &msg);
 
 	irq_install_pre_handler(*virt_irq_p,
diff --git a/arch/sparc64/solaris/ioctl.c b/arch/sparc64/solaris/ioctl.c
index 330743c..18352a4 100644
--- a/arch/sparc64/solaris/ioctl.c
+++ b/arch/sparc64/solaris/ioctl.c
@@ -686,7 +686,8 @@
 			int i = 0;
 			
 			read_lock_bh(&dev_base_lock);
-			for (d = dev_base; d; d = d->next) i++;
+			for_each_netdev(d)
+				i++;
 			read_unlock_bh(&dev_base_lock);
 
 			if (put_user (i, (int __user *)A(arg)))
diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig
index 1cad418..145bb82 100644
--- a/arch/x86_64/Kconfig
+++ b/arch/x86_64/Kconfig
@@ -701,6 +701,7 @@
 
 config PCI
 	bool "PCI support"
+	select ARCH_SUPPORTS_MSI if (X86_LOCAL_APIC && X86_IO_APIC)
 
 # x86-64 doesn't support PCI BIOS access from long mode so always go direct.
 config PCI_DIRECT
diff --git a/arch/x86_64/kernel/cpufreq/Kconfig b/arch/x86_64/kernel/cpufreq/Kconfig
index 40acb67..c0749d2 100644
--- a/arch/x86_64/kernel/cpufreq/Kconfig
+++ b/arch/x86_64/kernel/cpufreq/Kconfig
@@ -16,6 +16,9 @@
 	help
 	  This adds the CPUFreq driver for mobile AMD Opteron/Athlon64 processors.
 
+	  To compile this driver as a module, choose M here: the
+	  module will be called powernow-k8.
+
 	  For details, take a look at <file:Documentation/cpu-freq/>. 
 
 	  If in doubt, say N.
@@ -38,6 +41,9 @@
 	  mobile CPUs.  This means Intel Pentium M (Centrino) CPUs
 	  or 64bit enabled Intel Xeons.
 
+	  To compile this driver as a module, choose M here: the
+	  module will be called speedstep-centrino.
+
 	  For details, take a look at <file:Documentation/cpu-freq/>.
 
 	  If in doubt, say N.
@@ -55,6 +61,9 @@
 	  Processor Performance States.
 	  This driver also supports Intel Enhanced Speedstep.
 
+	  To compile this driver as a module, choose M here: the
+	  module will be called acpi-cpufreq.
+
 	  For details, take a look at <file:Documentation/cpu-freq/>.
 
 	  If in doubt, say N.
@@ -62,7 +71,7 @@
 comment "shared options"
 
 config X86_ACPI_CPUFREQ_PROC_INTF
-        bool "/proc/acpi/processor/../performance interface (deprecated)"
+	bool "/proc/acpi/processor/../performance interface (deprecated)"
 	depends on PROC_FS
 	depends on X86_ACPI_CPUFREQ || X86_SPEEDSTEP_CENTRINO_ACPI || X86_POWERNOW_K8_ACPI
 	help
@@ -86,16 +95,18 @@
 	  slowdowns and noticeable latencies.  Normally Speedstep should be used
 	  instead.
 
+	  To compile this driver as a module, choose M here: the
+	  module will be called p4-clockmod.
+
 	  For details, take a look at <file:Documentation/cpu-freq/>.
 
 	  Unless you are absolutely sure say N.
 
 
 config X86_SPEEDSTEP_LIB
-        tristate
-        default X86_P4_CLOCKMOD
+	tristate
+	default X86_P4_CLOCKMOD
 
 endif
 
 endmenu
-
diff --git a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c
index dd14ffa..2a2df14 100644
--- a/arch/x86_64/kernel/io_apic.c
+++ b/arch/x86_64/kernel/io_apic.c
@@ -1954,18 +1954,18 @@
 	if (irq < 0)
 		return irq;
 
-	set_irq_msi(irq, desc);
 	ret = msi_compose_msg(dev, irq, &msg);
 	if (ret < 0) {
 		destroy_irq(irq);
 		return ret;
 	}
 
+	set_irq_msi(irq, desc);
 	write_msi_msg(irq, &msg);
 
 	set_irq_chip_and_handler_name(irq, &msi_chip, handle_edge_irq, "edge");
 
-	return irq;
+	return 0;
 }
 
 void arch_teardown_msi_irq(unsigned int irq)
diff --git a/arch/xtensa/kernel/xtensa_ksyms.c b/arch/xtensa/kernel/xtensa_ksyms.c
index 0b4cb93..cd7e6a0 100644
--- a/arch/xtensa/kernel/xtensa_ksyms.c
+++ b/arch/xtensa/kernel/xtensa_ksyms.c
@@ -18,7 +18,6 @@
 #include <linux/interrupt.h>
 #include <asm/irq.h>
 #include <linux/in6.h>
-#include <linux/pci.h>
 #include <linux/ide.h>
 
 #include <asm/uaccess.h>
diff --git a/arch/xtensa/platform-iss/setup.c b/arch/xtensa/platform-iss/setup.c
index c8a42b6..f60c8cf 100644
--- a/arch/xtensa/platform-iss/setup.c
+++ b/arch/xtensa/platform-iss/setup.c
@@ -20,7 +20,6 @@
 #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>
diff --git a/block/genhd.c b/block/genhd.c
index 441432a..b566444 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -17,7 +17,7 @@
 #include <linux/buffer_head.h>
 #include <linux/mutex.h>
 
-struct subsystem block_subsys;
+struct kset block_subsys;
 static DEFINE_MUTEX(block_subsys_lock);
 
 /*
@@ -221,7 +221,7 @@
 	loff_t l = *pos;
 
 	mutex_lock(&block_subsys_lock);
-	list_for_each(p, &block_subsys.kset.list)
+	list_for_each(p, &block_subsys.list)
 		if (!l--)
 			return list_entry(p, struct gendisk, kobj.entry);
 	return NULL;
@@ -231,7 +231,7 @@
 {
 	struct list_head *p = ((struct gendisk *)v)->kobj.entry.next;
 	++*pos;
-	return p==&block_subsys.kset.list ? NULL : 
+	return p==&block_subsys.list ? NULL :
 		list_entry(p, struct gendisk, kobj.entry);
 }
 
@@ -246,7 +246,7 @@
 	int n;
 	char buf[BDEVNAME_SIZE];
 
-	if (&sgp->kobj.entry == block_subsys.kset.list.next)
+	if (&sgp->kobj.entry == block_subsys.list.next)
 		seq_puts(part, "major minor  #blocks  name\n\n");
 
 	/* Don't show non-partitionable removeable devices or empty devices */
@@ -565,7 +565,7 @@
 	struct list_head *p;
 
 	mutex_lock(&block_subsys_lock);
-	list_for_each(p, &block_subsys.kset.list)
+	list_for_each(p, &block_subsys.list)
 		if (!k--)
 			return list_entry(p, struct gendisk, kobj.entry);
 	return NULL;
@@ -575,7 +575,7 @@
 {
 	struct list_head *p = ((struct gendisk *)v)->kobj.entry.next;
 	++*pos;
-	return p==&block_subsys.kset.list ? NULL :
+	return p==&block_subsys.list ? NULL :
 		list_entry(p, struct gendisk, kobj.entry);
 }
 
diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c
index 123003a..5873861 100644
--- a/block/ll_rw_blk.c
+++ b/block/ll_rw_blk.c
@@ -1925,6 +1925,8 @@
 	blk_queue_max_hw_segments(q, MAX_HW_SEGMENTS);
 	blk_queue_max_phys_segments(q, MAX_PHYS_SEGMENTS);
 
+	q->sg_reserved_size = INT_MAX;
+
 	/*
 	 * all done
 	 */
diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c
index 65c6a3c..e83f1db 100644
--- a/block/scsi_ioctl.c
+++ b/block/scsi_ioctl.c
@@ -78,7 +78,9 @@
 
 static int sg_get_reserved_size(request_queue_t *q, int __user *p)
 {
-	return put_user(q->sg_reserved_size, p);
+	unsigned val = min(q->sg_reserved_size, q->max_sectors << 9);
+
+	return put_user(val, p);
 }
 
 static int sg_set_reserved_size(request_queue_t *q, int __user *p)
diff --git a/crypto/Kconfig b/crypto/Kconfig
index 086fcec..620e14c 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -16,6 +16,10 @@
 	help
 	  This option provides the API for cryptographic algorithms.
 
+config CRYPTO_ABLKCIPHER
+	tristate
+	select CRYPTO_BLKCIPHER
+
 config CRYPTO_BLKCIPHER
 	tristate
 	select CRYPTO_ALGAPI
@@ -171,6 +175,15 @@
 	  The first 128, 192 or 256 bits in the key are used for AES and the
 	  rest is used to tie each cipher block to its logical position.
 
+config CRYPTO_CRYPTD
+	tristate "Software async crypto daemon"
+	select CRYPTO_ABLKCIPHER
+	select CRYPTO_MANAGER
+	help
+	  This is a generic software asynchronous crypto daemon that
+	  converts an arbitrary synchronous software crypto algorithm
+	  into an asynchronous algorithm that executes in a kernel thread.
+
 config CRYPTO_DES
 	tristate "DES and Triple DES EDE cipher algorithms"
 	select CRYPTO_ALGAPI
diff --git a/crypto/Makefile b/crypto/Makefile
index 12f93f5..cce46a1 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -8,6 +8,7 @@
 crypto_algapi-objs := algapi.o $(crypto_algapi-y)
 obj-$(CONFIG_CRYPTO_ALGAPI) += crypto_algapi.o
 
+obj-$(CONFIG_CRYPTO_ABLKCIPHER) += ablkcipher.o
 obj-$(CONFIG_CRYPTO_BLKCIPHER) += blkcipher.o
 
 crypto_hash-objs := hash.o
@@ -29,6 +30,7 @@
 obj-$(CONFIG_CRYPTO_CBC) += cbc.o
 obj-$(CONFIG_CRYPTO_PCBC) += pcbc.o
 obj-$(CONFIG_CRYPTO_LRW) += lrw.o
+obj-$(CONFIG_CRYPTO_CRYPTD) += cryptd.o
 obj-$(CONFIG_CRYPTO_DES) += des.o
 obj-$(CONFIG_CRYPTO_FCRYPT) += fcrypt.o
 obj-$(CONFIG_CRYPTO_BLOWFISH) += blowfish.o
diff --git a/crypto/ablkcipher.c b/crypto/ablkcipher.c
new file mode 100644
index 0000000..9348ddd
--- /dev/null
+++ b/crypto/ablkcipher.c
@@ -0,0 +1,83 @@
+/*
+ * Asynchronous block chaining cipher operations.
+ * 
+ * This is the asynchronous version of blkcipher.c indicating completion
+ * via a callback.
+ *
+ * Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au>
+ *
+ * This program is free software; you can redistribute it and/or 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 <crypto/algapi.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/seq_file.h>
+
+static int setkey(struct crypto_ablkcipher *tfm, const u8 *key,
+		  unsigned int keylen)
+{
+	struct ablkcipher_alg *cipher = crypto_ablkcipher_alg(tfm);
+
+	if (keylen < cipher->min_keysize || keylen > cipher->max_keysize) {
+		crypto_ablkcipher_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
+		return -EINVAL;
+	}
+
+	return cipher->setkey(tfm, key, keylen);
+}
+
+static unsigned int crypto_ablkcipher_ctxsize(struct crypto_alg *alg, u32 type,
+					      u32 mask)
+{
+	return alg->cra_ctxsize;
+}
+
+static int crypto_init_ablkcipher_ops(struct crypto_tfm *tfm, u32 type,
+				      u32 mask)
+{
+	struct ablkcipher_alg *alg = &tfm->__crt_alg->cra_ablkcipher;
+	struct ablkcipher_tfm *crt = &tfm->crt_ablkcipher;
+
+	if (alg->ivsize > PAGE_SIZE / 8)
+		return -EINVAL;
+
+	crt->setkey = setkey;
+	crt->encrypt = alg->encrypt;
+	crt->decrypt = alg->decrypt;
+	crt->ivsize = alg->ivsize;
+
+	return 0;
+}
+
+static void crypto_ablkcipher_show(struct seq_file *m, struct crypto_alg *alg)
+	__attribute__ ((unused));
+static void crypto_ablkcipher_show(struct seq_file *m, struct crypto_alg *alg)
+{
+	struct ablkcipher_alg *ablkcipher = &alg->cra_ablkcipher;
+
+	seq_printf(m, "type         : ablkcipher\n");
+	seq_printf(m, "blocksize    : %u\n", alg->cra_blocksize);
+	seq_printf(m, "min keysize  : %u\n", ablkcipher->min_keysize);
+	seq_printf(m, "max keysize  : %u\n", ablkcipher->max_keysize);
+	seq_printf(m, "ivsize       : %u\n", ablkcipher->ivsize);
+	seq_printf(m, "qlen         : %u\n", ablkcipher->queue->qlen);
+	seq_printf(m, "max qlen     : %u\n", ablkcipher->queue->max_qlen);
+}
+
+const struct crypto_type crypto_ablkcipher_type = {
+	.ctxsize = crypto_ablkcipher_ctxsize,
+	.init = crypto_init_ablkcipher_ops,
+#ifdef CONFIG_PROC_FS
+	.show = crypto_ablkcipher_show,
+#endif
+};
+EXPORT_SYMBOL_GPL(crypto_ablkcipher_type);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Asynchronous block chaining cipher type");
diff --git a/crypto/algapi.c b/crypto/algapi.c
index f7d2185..f137a432 100644
--- a/crypto/algapi.c
+++ b/crypto/algapi.c
@@ -84,36 +84,47 @@
 	crypto_tmpl_put(tmpl);
 }
 
+static void crypto_remove_spawn(struct crypto_spawn *spawn,
+				struct list_head *list,
+				struct list_head *secondary_spawns)
+{
+	struct crypto_instance *inst = spawn->inst;
+	struct crypto_template *tmpl = inst->tmpl;
+
+	list_del_init(&spawn->list);
+	spawn->alg = NULL;
+
+	if (crypto_is_dead(&inst->alg))
+		return;
+
+	inst->alg.cra_flags |= CRYPTO_ALG_DEAD;
+	if (!tmpl || !crypto_tmpl_get(tmpl))
+		return;
+
+	crypto_notify(CRYPTO_MSG_ALG_UNREGISTER, &inst->alg);
+	list_move(&inst->alg.cra_list, list);
+	hlist_del(&inst->list);
+	inst->alg.cra_destroy = crypto_destroy_instance;
+
+	list_splice(&inst->alg.cra_users, secondary_spawns);
+}
+
 static void crypto_remove_spawns(struct list_head *spawns,
-				 struct list_head *list)
+				 struct list_head *list, u32 new_type)
 {
 	struct crypto_spawn *spawn, *n;
+	LIST_HEAD(secondary_spawns);
 
 	list_for_each_entry_safe(spawn, n, spawns, list) {
-		struct crypto_instance *inst = spawn->inst;
-		struct crypto_template *tmpl = inst->tmpl;
-
-		list_del_init(&spawn->list);
-		spawn->alg = NULL;
-
-		if (crypto_is_dead(&inst->alg))
+		if ((spawn->alg->cra_flags ^ new_type) & spawn->mask)
 			continue;
 
-		inst->alg.cra_flags |= CRYPTO_ALG_DEAD;
-		if (!tmpl || !crypto_tmpl_get(tmpl))
-			continue;
+		crypto_remove_spawn(spawn, list, &secondary_spawns);
+	}
 
-		crypto_notify(CRYPTO_MSG_ALG_UNREGISTER, &inst->alg);
-		list_move(&inst->alg.cra_list, list);
-		hlist_del(&inst->list);
-		inst->alg.cra_destroy = crypto_destroy_instance;
-
-		if (!list_empty(&inst->alg.cra_users)) {
-			if (&n->list == spawns)
-				n = list_entry(inst->alg.cra_users.next,
-					       typeof(*n), list);
-			__list_splice(&inst->alg.cra_users, spawns->prev);
-		}
+	while (!list_empty(&secondary_spawns)) {
+		list_for_each_entry_safe(spawn, n, &secondary_spawns, list)
+			crypto_remove_spawn(spawn, list, &secondary_spawns);
 	}
 }
 
@@ -164,7 +175,7 @@
 		    q->cra_priority > alg->cra_priority)
 			continue;
 
-		crypto_remove_spawns(&q->cra_users, list);
+		crypto_remove_spawns(&q->cra_users, list, alg->cra_flags);
 	}
 	
 	list_add(&alg->cra_list, &crypto_alg_list);
@@ -214,7 +225,7 @@
 
 	crypto_notify(CRYPTO_MSG_ALG_UNREGISTER, alg);
 	list_del_init(&alg->cra_list);
-	crypto_remove_spawns(&alg->cra_users, list);
+	crypto_remove_spawns(&alg->cra_users, list, alg->cra_flags);
 
 	return 0;
 }
@@ -351,11 +362,12 @@
 EXPORT_SYMBOL_GPL(crypto_register_instance);
 
 int crypto_init_spawn(struct crypto_spawn *spawn, struct crypto_alg *alg,
-		      struct crypto_instance *inst)
+		      struct crypto_instance *inst, u32 mask)
 {
 	int err = -EAGAIN;
 
 	spawn->inst = inst;
+	spawn->mask = mask;
 
 	down_write(&crypto_alg_sem);
 	if (!crypto_is_moribund(alg)) {
@@ -425,15 +437,45 @@
 }
 EXPORT_SYMBOL_GPL(crypto_unregister_notifier);
 
-struct crypto_alg *crypto_get_attr_alg(void *param, unsigned int len,
-				       u32 type, u32 mask)
+struct crypto_attr_type *crypto_get_attr_type(struct rtattr **tb)
 {
-	struct rtattr *rta = param;
+	struct rtattr *rta = tb[CRYPTOA_TYPE - 1];
+	struct crypto_attr_type *algt;
+
+	if (!rta)
+		return ERR_PTR(-ENOENT);
+	if (RTA_PAYLOAD(rta) < sizeof(*algt))
+		return ERR_PTR(-EINVAL);
+
+	algt = RTA_DATA(rta);
+
+	return algt;
+}
+EXPORT_SYMBOL_GPL(crypto_get_attr_type);
+
+int crypto_check_attr_type(struct rtattr **tb, u32 type)
+{
+	struct crypto_attr_type *algt;
+
+	algt = crypto_get_attr_type(tb);
+	if (IS_ERR(algt))
+		return PTR_ERR(algt);
+
+	if ((algt->type ^ type) & algt->mask)
+		return -EINVAL;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(crypto_check_attr_type);
+
+struct crypto_alg *crypto_get_attr_alg(struct rtattr **tb, u32 type, u32 mask)
+{
+	struct rtattr *rta = tb[CRYPTOA_ALG - 1];
 	struct crypto_attr_alg *alga;
 
-	if (!RTA_OK(rta, len))
-		return ERR_PTR(-EBADR);
-	if (rta->rta_type != CRYPTOA_ALG || RTA_PAYLOAD(rta) < sizeof(*alga))
+	if (!rta)
+		return ERR_PTR(-ENOENT);
+	if (RTA_PAYLOAD(rta) < sizeof(*alga))
 		return ERR_PTR(-EINVAL);
 
 	alga = RTA_DATA(rta);
@@ -464,7 +506,8 @@
 		goto err_free_inst;
 
 	spawn = crypto_instance_ctx(inst);
-	err = crypto_init_spawn(spawn, alg, inst);
+	err = crypto_init_spawn(spawn, alg, inst,
+				CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_ASYNC);
 
 	if (err)
 		goto err_free_inst;
@@ -477,6 +520,68 @@
 }
 EXPORT_SYMBOL_GPL(crypto_alloc_instance);
 
+void crypto_init_queue(struct crypto_queue *queue, unsigned int max_qlen)
+{
+	INIT_LIST_HEAD(&queue->list);
+	queue->backlog = &queue->list;
+	queue->qlen = 0;
+	queue->max_qlen = max_qlen;
+}
+EXPORT_SYMBOL_GPL(crypto_init_queue);
+
+int crypto_enqueue_request(struct crypto_queue *queue,
+			   struct crypto_async_request *request)
+{
+	int err = -EINPROGRESS;
+
+	if (unlikely(queue->qlen >= queue->max_qlen)) {
+		err = -EBUSY;
+		if (!(request->flags & CRYPTO_TFM_REQ_MAY_BACKLOG))
+			goto out;
+		if (queue->backlog == &queue->list)
+			queue->backlog = &request->list;
+	}
+
+	queue->qlen++;
+	list_add_tail(&request->list, &queue->list);
+
+out:
+	return err;
+}
+EXPORT_SYMBOL_GPL(crypto_enqueue_request);
+
+struct crypto_async_request *crypto_dequeue_request(struct crypto_queue *queue)
+{
+	struct list_head *request;
+
+	if (unlikely(!queue->qlen))
+		return NULL;
+
+	queue->qlen--;
+
+	if (queue->backlog != &queue->list)
+		queue->backlog = queue->backlog->next;
+
+	request = queue->list.next;
+	list_del(request);
+
+	return list_entry(request, struct crypto_async_request, list);
+}
+EXPORT_SYMBOL_GPL(crypto_dequeue_request);
+
+int crypto_tfm_in_queue(struct crypto_queue *queue, struct crypto_tfm *tfm)
+{
+	struct crypto_async_request *req;
+
+	list_for_each_entry(req, &queue->list, list) {
+		if (req->tfm == tfm)
+			return 1;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(crypto_tfm_in_queue);
+
 static int __init crypto_algapi_init(void)
 {
 	crypto_init_proc();
diff --git a/crypto/blkcipher.c b/crypto/blkcipher.c
index b5befe8c..8edf40c 100644
--- a/crypto/blkcipher.c
+++ b/crypto/blkcipher.c
@@ -349,13 +349,48 @@
 	return cipher->setkey(tfm, key, keylen);
 }
 
+static int async_setkey(struct crypto_ablkcipher *tfm, const u8 *key,
+			unsigned int keylen)
+{
+	return setkey(crypto_ablkcipher_tfm(tfm), key, keylen);
+}
+
+static int async_encrypt(struct ablkcipher_request *req)
+{
+	struct crypto_tfm *tfm = req->base.tfm;
+	struct blkcipher_alg *alg = &tfm->__crt_alg->cra_blkcipher;
+	struct blkcipher_desc desc = {
+		.tfm = __crypto_blkcipher_cast(tfm),
+		.info = req->info,
+		.flags = req->base.flags,
+	};
+
+
+	return alg->encrypt(&desc, req->dst, req->src, req->nbytes);
+}
+
+static int async_decrypt(struct ablkcipher_request *req)
+{
+	struct crypto_tfm *tfm = req->base.tfm;
+	struct blkcipher_alg *alg = &tfm->__crt_alg->cra_blkcipher;
+	struct blkcipher_desc desc = {
+		.tfm = __crypto_blkcipher_cast(tfm),
+		.info = req->info,
+		.flags = req->base.flags,
+	};
+
+	return alg->decrypt(&desc, req->dst, req->src, req->nbytes);
+}
+
 static unsigned int crypto_blkcipher_ctxsize(struct crypto_alg *alg, u32 type,
 					     u32 mask)
 {
 	struct blkcipher_alg *cipher = &alg->cra_blkcipher;
 	unsigned int len = alg->cra_ctxsize;
 
-	if (cipher->ivsize) {
+	type ^= CRYPTO_ALG_ASYNC;
+	mask &= CRYPTO_ALG_ASYNC;
+	if ((type & mask) && cipher->ivsize) {
 		len = ALIGN(len, (unsigned long)alg->cra_alignmask + 1);
 		len += cipher->ivsize;
 	}
@@ -363,16 +398,26 @@
 	return len;
 }
 
-static int crypto_init_blkcipher_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
+static int crypto_init_blkcipher_ops_async(struct crypto_tfm *tfm)
+{
+	struct ablkcipher_tfm *crt = &tfm->crt_ablkcipher;
+	struct blkcipher_alg *alg = &tfm->__crt_alg->cra_blkcipher;
+
+	crt->setkey = async_setkey;
+	crt->encrypt = async_encrypt;
+	crt->decrypt = async_decrypt;
+	crt->ivsize = alg->ivsize;
+
+	return 0;
+}
+
+static int crypto_init_blkcipher_ops_sync(struct crypto_tfm *tfm)
 {
 	struct blkcipher_tfm *crt = &tfm->crt_blkcipher;
 	struct blkcipher_alg *alg = &tfm->__crt_alg->cra_blkcipher;
 	unsigned long align = crypto_tfm_alg_alignmask(tfm) + 1;
 	unsigned long addr;
 
-	if (alg->ivsize > PAGE_SIZE / 8)
-		return -EINVAL;
-
 	crt->setkey = setkey;
 	crt->encrypt = alg->encrypt;
 	crt->decrypt = alg->decrypt;
@@ -385,8 +430,23 @@
 	return 0;
 }
 
+static int crypto_init_blkcipher_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
+{
+	struct blkcipher_alg *alg = &tfm->__crt_alg->cra_blkcipher;
+
+	if (alg->ivsize > PAGE_SIZE / 8)
+		return -EINVAL;
+
+	type ^= CRYPTO_ALG_ASYNC;
+	mask &= CRYPTO_ALG_ASYNC;
+	if (type & mask)
+		return crypto_init_blkcipher_ops_sync(tfm);
+	else
+		return crypto_init_blkcipher_ops_async(tfm);
+}
+
 static void crypto_blkcipher_show(struct seq_file *m, struct crypto_alg *alg)
-	__attribute_used__;
+	__attribute__ ((unused));
 static void crypto_blkcipher_show(struct seq_file *m, struct crypto_alg *alg)
 {
 	seq_printf(m, "type         : blkcipher\n");
diff --git a/crypto/cbc.c b/crypto/cbc.c
index 136fea7..1f2649e 100644
--- a/crypto/cbc.c
+++ b/crypto/cbc.c
@@ -275,13 +275,18 @@
 	crypto_free_cipher(ctx->child);
 }
 
-static struct crypto_instance *crypto_cbc_alloc(void *param, unsigned int len)
+static struct crypto_instance *crypto_cbc_alloc(struct rtattr **tb)
 {
 	struct crypto_instance *inst;
 	struct crypto_alg *alg;
+	int err;
 
-	alg = crypto_get_attr_alg(param, len, CRYPTO_ALG_TYPE_CIPHER,
-				  CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_ASYNC);
+	err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_BLKCIPHER);
+	if (err)
+		return ERR_PTR(err);
+
+	alg = crypto_get_attr_alg(tb, CRYPTO_ALG_TYPE_CIPHER,
+				  CRYPTO_ALG_TYPE_MASK);
 	if (IS_ERR(alg))
 		return ERR_PTR(PTR_ERR(alg));
 
diff --git a/crypto/cryptd.c b/crypto/cryptd.c
new file mode 100644
index 0000000..3ff4e1f
--- /dev/null
+++ b/crypto/cryptd.c
@@ -0,0 +1,375 @@
+/*
+ * Software async crypto daemon.
+ *
+ * Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au>
+ *
+ * This program is free software; you can redistribute it and/or 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 <crypto/algapi.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/kthread.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/scatterlist.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+#define CRYPTD_MAX_QLEN 100
+
+struct cryptd_state {
+	spinlock_t lock;
+	struct mutex mutex;
+	struct crypto_queue queue;
+	struct task_struct *task;
+};
+
+struct cryptd_instance_ctx {
+	struct crypto_spawn spawn;
+	struct cryptd_state *state;
+};
+
+struct cryptd_blkcipher_ctx {
+	struct crypto_blkcipher *child;
+};
+
+struct cryptd_blkcipher_request_ctx {
+	crypto_completion_t complete;
+};
+
+
+static inline struct cryptd_state *cryptd_get_state(struct crypto_tfm *tfm)
+{
+	struct crypto_instance *inst = crypto_tfm_alg_instance(tfm);
+	struct cryptd_instance_ctx *ictx = crypto_instance_ctx(inst);
+	return ictx->state;
+}
+
+static int cryptd_blkcipher_setkey(struct crypto_ablkcipher *parent,
+				   const u8 *key, unsigned int keylen)
+{
+	struct cryptd_blkcipher_ctx *ctx = crypto_ablkcipher_ctx(parent);
+	struct crypto_blkcipher *child = ctx->child;
+	int err;
+
+	crypto_blkcipher_clear_flags(child, CRYPTO_TFM_REQ_MASK);
+	crypto_blkcipher_set_flags(child, crypto_ablkcipher_get_flags(parent) &
+					  CRYPTO_TFM_REQ_MASK);
+	err = crypto_blkcipher_setkey(child, key, keylen);
+	crypto_ablkcipher_set_flags(parent, crypto_blkcipher_get_flags(child) &
+					    CRYPTO_TFM_RES_MASK);
+	return err;
+}
+
+static void cryptd_blkcipher_crypt(struct ablkcipher_request *req,
+				   struct crypto_blkcipher *child,
+				   int err,
+				   int (*crypt)(struct blkcipher_desc *desc,
+						struct scatterlist *dst,
+						struct scatterlist *src,
+						unsigned int len))
+{
+	struct cryptd_blkcipher_request_ctx *rctx;
+	struct blkcipher_desc desc;
+
+	rctx = ablkcipher_request_ctx(req);
+
+	if (unlikely(err == -EINPROGRESS)) {
+		rctx->complete(&req->base, err);
+		return;
+	}
+
+	desc.tfm = child;
+	desc.info = req->info;
+	desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP;
+
+	err = crypt(&desc, req->dst, req->src, req->nbytes);
+
+	req->base.complete = rctx->complete;
+
+	local_bh_disable();
+	req->base.complete(&req->base, err);
+	local_bh_enable();
+}
+
+static void cryptd_blkcipher_encrypt(struct crypto_async_request *req, int err)
+{
+	struct cryptd_blkcipher_ctx *ctx = crypto_tfm_ctx(req->tfm);
+	struct crypto_blkcipher *child = ctx->child;
+
+	cryptd_blkcipher_crypt(ablkcipher_request_cast(req), child, err,
+			       crypto_blkcipher_crt(child)->encrypt);
+}
+
+static void cryptd_blkcipher_decrypt(struct crypto_async_request *req, int err)
+{
+	struct cryptd_blkcipher_ctx *ctx = crypto_tfm_ctx(req->tfm);
+	struct crypto_blkcipher *child = ctx->child;
+
+	cryptd_blkcipher_crypt(ablkcipher_request_cast(req), child, err,
+			       crypto_blkcipher_crt(child)->decrypt);
+}
+
+static int cryptd_blkcipher_enqueue(struct ablkcipher_request *req,
+				    crypto_completion_t complete)
+{
+	struct cryptd_blkcipher_request_ctx *rctx = ablkcipher_request_ctx(req);
+	struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req);
+	struct cryptd_state *state =
+		cryptd_get_state(crypto_ablkcipher_tfm(tfm));
+	int err;
+
+	rctx->complete = req->base.complete;
+	req->base.complete = complete;
+
+	spin_lock_bh(&state->lock);
+	err = ablkcipher_enqueue_request(crypto_ablkcipher_alg(tfm), req);
+	spin_unlock_bh(&state->lock);
+
+	wake_up_process(state->task);
+	return err;
+}
+
+static int cryptd_blkcipher_encrypt_enqueue(struct ablkcipher_request *req)
+{
+	return cryptd_blkcipher_enqueue(req, cryptd_blkcipher_encrypt);
+}
+
+static int cryptd_blkcipher_decrypt_enqueue(struct ablkcipher_request *req)
+{
+	return cryptd_blkcipher_enqueue(req, cryptd_blkcipher_decrypt);
+}
+
+static int cryptd_blkcipher_init_tfm(struct crypto_tfm *tfm)
+{
+	struct crypto_instance *inst = crypto_tfm_alg_instance(tfm);
+	struct cryptd_instance_ctx *ictx = crypto_instance_ctx(inst);
+	struct crypto_spawn *spawn = &ictx->spawn;
+	struct cryptd_blkcipher_ctx *ctx = crypto_tfm_ctx(tfm);
+	struct crypto_blkcipher *cipher;
+
+	cipher = crypto_spawn_blkcipher(spawn);
+	if (IS_ERR(cipher))
+		return PTR_ERR(cipher);
+
+	ctx->child = cipher;
+	tfm->crt_ablkcipher.reqsize =
+		sizeof(struct cryptd_blkcipher_request_ctx);
+	return 0;
+}
+
+static void cryptd_blkcipher_exit_tfm(struct crypto_tfm *tfm)
+{
+	struct cryptd_blkcipher_ctx *ctx = crypto_tfm_ctx(tfm);
+	struct cryptd_state *state = cryptd_get_state(tfm);
+	int active;
+
+	mutex_lock(&state->mutex);
+	active = ablkcipher_tfm_in_queue(__crypto_ablkcipher_cast(tfm));
+	mutex_unlock(&state->mutex);
+
+	BUG_ON(active);
+
+	crypto_free_blkcipher(ctx->child);
+}
+
+static struct crypto_instance *cryptd_alloc_instance(struct crypto_alg *alg,
+						     struct cryptd_state *state)
+{
+	struct crypto_instance *inst;
+	struct cryptd_instance_ctx *ctx;
+	int err;
+
+	inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL);
+	if (IS_ERR(inst))
+		goto out;
+
+	err = -ENAMETOOLONG;
+	if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME,
+		     "cryptd(%s)", alg->cra_driver_name) >= CRYPTO_MAX_ALG_NAME)
+		goto out_free_inst;
+
+	ctx = crypto_instance_ctx(inst);
+	err = crypto_init_spawn(&ctx->spawn, alg, inst,
+				CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_ASYNC);
+	if (err)
+		goto out_free_inst;
+
+	ctx->state = state;
+
+	memcpy(inst->alg.cra_name, alg->cra_name, CRYPTO_MAX_ALG_NAME);
+
+	inst->alg.cra_priority = alg->cra_priority + 50;
+	inst->alg.cra_blocksize = alg->cra_blocksize;
+	inst->alg.cra_alignmask = alg->cra_alignmask;
+
+out:
+	return inst;
+
+out_free_inst:
+	kfree(inst);
+	inst = ERR_PTR(err);
+	goto out;
+}
+
+static struct crypto_instance *cryptd_alloc_blkcipher(
+	struct rtattr **tb, struct cryptd_state *state)
+{
+	struct crypto_instance *inst;
+	struct crypto_alg *alg;
+
+	alg = crypto_get_attr_alg(tb, CRYPTO_ALG_TYPE_BLKCIPHER,
+				  CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_ASYNC);
+	if (IS_ERR(alg))
+		return ERR_PTR(PTR_ERR(alg));
+
+	inst = cryptd_alloc_instance(alg, state);
+	if (IS_ERR(inst))
+		goto out_put_alg;
+
+	inst->alg.cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER | CRYPTO_ALG_ASYNC;
+	inst->alg.cra_type = &crypto_ablkcipher_type;
+
+	inst->alg.cra_ablkcipher.ivsize = alg->cra_blkcipher.ivsize;
+	inst->alg.cra_ablkcipher.min_keysize = alg->cra_blkcipher.min_keysize;
+	inst->alg.cra_ablkcipher.max_keysize = alg->cra_blkcipher.max_keysize;
+
+	inst->alg.cra_ctxsize = sizeof(struct cryptd_blkcipher_ctx);
+
+	inst->alg.cra_init = cryptd_blkcipher_init_tfm;
+	inst->alg.cra_exit = cryptd_blkcipher_exit_tfm;
+
+	inst->alg.cra_ablkcipher.setkey = cryptd_blkcipher_setkey;
+	inst->alg.cra_ablkcipher.encrypt = cryptd_blkcipher_encrypt_enqueue;
+	inst->alg.cra_ablkcipher.decrypt = cryptd_blkcipher_decrypt_enqueue;
+
+	inst->alg.cra_ablkcipher.queue = &state->queue;
+
+out_put_alg:
+	crypto_mod_put(alg);
+	return inst;
+}
+
+static struct cryptd_state state;
+
+static struct crypto_instance *cryptd_alloc(struct rtattr **tb)
+{
+	struct crypto_attr_type *algt;
+
+	algt = crypto_get_attr_type(tb);
+	if (IS_ERR(algt))
+		return ERR_PTR(PTR_ERR(algt));
+
+	switch (algt->type & algt->mask & CRYPTO_ALG_TYPE_MASK) {
+	case CRYPTO_ALG_TYPE_BLKCIPHER:
+		return cryptd_alloc_blkcipher(tb, &state);
+	}
+
+	return ERR_PTR(-EINVAL);
+}
+
+static void cryptd_free(struct crypto_instance *inst)
+{
+	struct cryptd_instance_ctx *ctx = crypto_instance_ctx(inst);
+
+	crypto_drop_spawn(&ctx->spawn);
+	kfree(inst);
+}
+
+static struct crypto_template cryptd_tmpl = {
+	.name = "cryptd",
+	.alloc = cryptd_alloc,
+	.free = cryptd_free,
+	.module = THIS_MODULE,
+};
+
+static inline int cryptd_create_thread(struct cryptd_state *state,
+				       int (*fn)(void *data), const char *name)
+{
+	spin_lock_init(&state->lock);
+	mutex_init(&state->mutex);
+	crypto_init_queue(&state->queue, CRYPTD_MAX_QLEN);
+
+	state->task = kthread_create(fn, state, name);
+	if (IS_ERR(state->task))
+		return PTR_ERR(state->task);
+
+	return 0;
+}
+
+static inline void cryptd_stop_thread(struct cryptd_state *state)
+{
+	BUG_ON(state->queue.qlen);
+	kthread_stop(state->task);
+}
+
+static int cryptd_thread(void *data)
+{
+	struct cryptd_state *state = data;
+	int stop;
+
+	do {
+		struct crypto_async_request *req, *backlog;
+
+		mutex_lock(&state->mutex);
+		__set_current_state(TASK_INTERRUPTIBLE);
+
+		spin_lock_bh(&state->lock);
+		backlog = crypto_get_backlog(&state->queue);
+		req = crypto_dequeue_request(&state->queue);
+		spin_unlock_bh(&state->lock);
+
+		stop = kthread_should_stop();
+
+		if (stop || req) {
+			__set_current_state(TASK_RUNNING);
+			if (req) {
+				if (backlog)
+					backlog->complete(backlog,
+							  -EINPROGRESS);
+				req->complete(req, 0);
+			}
+		}
+
+		mutex_unlock(&state->mutex);
+
+		schedule();
+	} while (!stop);
+
+	return 0;
+}
+
+static int __init cryptd_init(void)
+{
+	int err;
+
+	err = cryptd_create_thread(&state, cryptd_thread, "cryptd");
+	if (err)
+		return err;
+
+	err = crypto_register_template(&cryptd_tmpl);
+	if (err)
+		kthread_stop(state.task);
+
+	return err;
+}
+
+static void __exit cryptd_exit(void)
+{
+	cryptd_stop_thread(&state);
+	crypto_unregister_template(&cryptd_tmpl);
+}
+
+module_init(cryptd_init);
+module_exit(cryptd_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Software async crypto daemon");
diff --git a/crypto/cryptomgr.c b/crypto/cryptomgr.c
index 2ebffb8..6958ea8 100644
--- a/crypto/cryptomgr.c
+++ b/crypto/cryptomgr.c
@@ -14,17 +14,24 @@
 #include <linux/ctype.h>
 #include <linux/err.h>
 #include <linux/init.h>
+#include <linux/kthread.h>
 #include <linux/module.h>
 #include <linux/notifier.h>
 #include <linux/rtnetlink.h>
 #include <linux/sched.h>
 #include <linux/string.h>
-#include <linux/workqueue.h>
 
 #include "internal.h"
 
 struct cryptomgr_param {
-	struct work_struct work;
+	struct task_struct *thread;
+
+	struct rtattr *tb[CRYPTOA_MAX];
+
+	struct {
+		struct rtattr attr;
+		struct crypto_attr_type data;
+	} type;
 
 	struct {
 		struct rtattr attr;
@@ -32,18 +39,15 @@
 	} alg;
 
 	struct {
-		u32 type;
-		u32 mask;
 		char name[CRYPTO_MAX_ALG_NAME];
 	} larval;
 
 	char template[CRYPTO_MAX_ALG_NAME];
 };
 
-static void cryptomgr_probe(struct work_struct *work)
+static int cryptomgr_probe(void *data)
 {
-	struct cryptomgr_param *param =
-		container_of(work, struct cryptomgr_param, work);
+	struct cryptomgr_param *param = data;
 	struct crypto_template *tmpl;
 	struct crypto_instance *inst;
 	int err;
@@ -53,7 +57,7 @@
 		goto err;
 
 	do {
-		inst = tmpl->alloc(&param->alg, sizeof(param->alg));
+		inst = tmpl->alloc(param->tb);
 		if (IS_ERR(inst))
 			err = PTR_ERR(inst);
 		else if ((err = crypto_register_instance(tmpl, inst)))
@@ -67,11 +71,11 @@
 
 out:
 	kfree(param);
-	return;
+	module_put_and_exit(0);
 
 err:
-	crypto_larval_error(param->larval.name, param->larval.type,
-			    param->larval.mask);
+	crypto_larval_error(param->larval.name, param->type.data.type,
+			    param->type.data.mask);
 	goto out;
 }
 
@@ -82,10 +86,13 @@
 	const char *p;
 	unsigned int len;
 
-	param = kmalloc(sizeof(*param), GFP_KERNEL);
-	if (!param)
+	if (!try_module_get(THIS_MODULE))
 		goto err;
 
+	param = kzalloc(sizeof(*param), GFP_KERNEL);
+	if (!param)
+		goto err_put_module;
+
 	for (p = name; isalnum(*p) || *p == '-' || *p == '_'; p++)
 		;
 
@@ -94,32 +101,45 @@
 		goto err_free_param;
 
 	memcpy(param->template, name, len);
-	param->template[len] = 0;
 
 	name = p + 1;
-	for (p = name; isalnum(*p) || *p == '-' || *p == '_'; p++)
-		;
+	len = 0;
+	for (p = name; *p; p++) {
+		for (; isalnum(*p) || *p == '-' || *p == '_' || *p == '('; p++)
+			;
 
-	len = p - name;
-	if (!len || *p != ')' || p[1])
+		if (*p != ')')
+			goto err_free_param;
+
+		len = p - name;
+	}
+
+	if (!len || name[len + 1])
 		goto err_free_param;
 
+	param->type.attr.rta_len = sizeof(param->type);
+	param->type.attr.rta_type = CRYPTOA_TYPE;
+	param->type.data.type = larval->alg.cra_flags;
+	param->type.data.mask = larval->mask;
+	param->tb[CRYPTOA_TYPE - 1] = &param->type.attr;
+
 	param->alg.attr.rta_len = sizeof(param->alg);
 	param->alg.attr.rta_type = CRYPTOA_ALG;
 	memcpy(param->alg.data.name, name, len);
-	param->alg.data.name[len] = 0;
+	param->tb[CRYPTOA_ALG - 1] = &param->alg.attr;
 
 	memcpy(param->larval.name, larval->alg.cra_name, CRYPTO_MAX_ALG_NAME);
-	param->larval.type = larval->alg.cra_flags;
-	param->larval.mask = larval->mask;
 
-	INIT_WORK(&param->work, cryptomgr_probe);
-	schedule_work(&param->work);
+	param->thread = kthread_run(cryptomgr_probe, param, "cryptomgr");
+	if (IS_ERR(param->thread))
+		goto err_free_param;
 
 	return NOTIFY_STOP;
 
 err_free_param:
 	kfree(param);
+err_put_module:
+	module_put(THIS_MODULE);
 err:
 	return NOTIFY_OK;
 }
diff --git a/crypto/ecb.c b/crypto/ecb.c
index 839a0ae..6310387 100644
--- a/crypto/ecb.c
+++ b/crypto/ecb.c
@@ -115,13 +115,18 @@
 	crypto_free_cipher(ctx->child);
 }
 
-static struct crypto_instance *crypto_ecb_alloc(void *param, unsigned int len)
+static struct crypto_instance *crypto_ecb_alloc(struct rtattr **tb)
 {
 	struct crypto_instance *inst;
 	struct crypto_alg *alg;
+	int err;
 
-	alg = crypto_get_attr_alg(param, len, CRYPTO_ALG_TYPE_CIPHER,
-				  CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_ASYNC);
+	err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_BLKCIPHER);
+	if (err)
+		return ERR_PTR(err);
+
+	alg = crypto_get_attr_alg(tb, CRYPTO_ALG_TYPE_CIPHER,
+				  CRYPTO_ALG_TYPE_MASK);
 	if (IS_ERR(alg))
 		return ERR_PTR(PTR_ERR(alg));
 
diff --git a/crypto/hash.c b/crypto/hash.c
index 12c4514..4ccd22d 100644
--- a/crypto/hash.c
+++ b/crypto/hash.c
@@ -41,7 +41,7 @@
 }
 
 static void crypto_hash_show(struct seq_file *m, struct crypto_alg *alg)
-	__attribute_used__;
+	__attribute__ ((unused));
 static void crypto_hash_show(struct seq_file *m, struct crypto_alg *alg)
 {
 	seq_printf(m, "type         : hash\n");
diff --git a/crypto/hmac.c b/crypto/hmac.c
index 44187c5..8802fb6 100644
--- a/crypto/hmac.c
+++ b/crypto/hmac.c
@@ -197,13 +197,18 @@
 	kfree(inst);
 }
 
-static struct crypto_instance *hmac_alloc(void *param, unsigned int len)
+static struct crypto_instance *hmac_alloc(struct rtattr **tb)
 {
 	struct crypto_instance *inst;
 	struct crypto_alg *alg;
+	int err;
 
-	alg = crypto_get_attr_alg(param, len, CRYPTO_ALG_TYPE_HASH,
-				  CRYPTO_ALG_TYPE_HASH_MASK | CRYPTO_ALG_ASYNC);
+	err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_HASH);
+	if (err)
+		return ERR_PTR(err);
+
+	alg = crypto_get_attr_alg(tb, CRYPTO_ALG_TYPE_HASH,
+				  CRYPTO_ALG_TYPE_HASH_MASK);
 	if (IS_ERR(alg))
 		return ERR_PTR(PTR_ERR(alg));
 
diff --git a/crypto/lrw.c b/crypto/lrw.c
index b410508..621095d 100644
--- a/crypto/lrw.c
+++ b/crypto/lrw.c
@@ -228,13 +228,18 @@
 	crypto_free_cipher(ctx->child);
 }
 
-static struct crypto_instance *alloc(void *param, unsigned int len)
+static struct crypto_instance *alloc(struct rtattr **tb)
 {
 	struct crypto_instance *inst;
 	struct crypto_alg *alg;
+	int err;
 
-	alg = crypto_get_attr_alg(param, len, CRYPTO_ALG_TYPE_CIPHER,
-				  CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_ASYNC);
+	err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_BLKCIPHER);
+	if (err)
+		return ERR_PTR(err);
+
+	alg = crypto_get_attr_alg(tb, CRYPTO_ALG_TYPE_CIPHER,
+				  CRYPTO_ALG_TYPE_MASK);
 	if (IS_ERR(alg))
 		return ERR_PTR(PTR_ERR(alg));
 
diff --git a/crypto/pcbc.c b/crypto/pcbc.c
index 5174d7f..c3ed8a1 100644
--- a/crypto/pcbc.c
+++ b/crypto/pcbc.c
@@ -279,13 +279,18 @@
 	crypto_free_cipher(ctx->child);
 }
 
-static struct crypto_instance *crypto_pcbc_alloc(void *param, unsigned int len)
+static struct crypto_instance *crypto_pcbc_alloc(struct rtattr **tb)
 {
 	struct crypto_instance *inst;
 	struct crypto_alg *alg;
+	int err;
 
-	alg = crypto_get_attr_alg(param, len, CRYPTO_ALG_TYPE_CIPHER,
-				  CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_ASYNC);
+	err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_BLKCIPHER);
+	if (err)
+		return ERR_PTR(err);
+
+	alg = crypto_get_attr_alg(tb, CRYPTO_ALG_TYPE_CIPHER,
+				  CRYPTO_ALG_TYPE_MASK);
 	if (IS_ERR(alg))
 		return ERR_PTR(PTR_ERR(alg));
 
diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c
index 8eaa5aa..f0aed01 100644
--- a/crypto/tcrypt.c
+++ b/crypto/tcrypt.c
@@ -57,6 +57,11 @@
 #define ENCRYPT 1
 #define DECRYPT 0
 
+struct tcrypt_result {
+	struct completion completion;
+	int err;
+};
+
 static unsigned int IDX[8] = { IDX1, IDX2, IDX3, IDX4, IDX5, IDX6, IDX7, IDX8 };
 
 /*
@@ -84,6 +89,17 @@
 	printk("\n");
 }
 
+static void tcrypt_complete(struct crypto_async_request *req, int err)
+{
+	struct tcrypt_result *res = req->data;
+
+	if (err == -EINPROGRESS)
+		return;
+
+	res->err = err;
+	complete(&res->completion);
+}
+
 static void test_hash(char *algo, struct hash_testvec *template,
 		      unsigned int tcount)
 {
@@ -203,15 +219,14 @@
 {
 	unsigned int ret, i, j, k, temp;
 	unsigned int tsize;
-	unsigned int iv_len;
-	unsigned int len;
 	char *q;
-	struct crypto_blkcipher *tfm;
+	struct crypto_ablkcipher *tfm;
 	char *key;
 	struct cipher_testvec *cipher_tv;
-	struct blkcipher_desc desc;
+	struct ablkcipher_request *req;
 	struct scatterlist sg[8];
 	const char *e;
+	struct tcrypt_result result;
 
 	if (enc == ENCRYPT)
 	        e = "encryption";
@@ -232,15 +247,24 @@
 	memcpy(tvmem, template, tsize);
 	cipher_tv = (void *)tvmem;
 
-	tfm = crypto_alloc_blkcipher(algo, 0, CRYPTO_ALG_ASYNC);
+	init_completion(&result.completion);
+
+	tfm = crypto_alloc_ablkcipher(algo, 0, 0);
 
 	if (IS_ERR(tfm)) {
 		printk("failed to load transform for %s: %ld\n", algo,
 		       PTR_ERR(tfm));
 		return;
 	}
-	desc.tfm = tfm;
-	desc.flags = 0;
+
+	req = ablkcipher_request_alloc(tfm, GFP_KERNEL);
+	if (!req) {
+		printk("failed to allocate request for %s\n", algo);
+		goto out;
+	}
+
+	ablkcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
+					tcrypt_complete, &result);
 
 	j = 0;
 	for (i = 0; i < tcount; i++) {
@@ -249,17 +273,17 @@
 			printk("test %u (%d bit key):\n",
 			j, cipher_tv[i].klen * 8);
 
-			crypto_blkcipher_clear_flags(tfm, ~0);
+			crypto_ablkcipher_clear_flags(tfm, ~0);
 			if (cipher_tv[i].wk)
-				crypto_blkcipher_set_flags(
+				crypto_ablkcipher_set_flags(
 					tfm, CRYPTO_TFM_REQ_WEAK_KEY);
 			key = cipher_tv[i].key;
 
-			ret = crypto_blkcipher_setkey(tfm, key,
-						      cipher_tv[i].klen);
+			ret = crypto_ablkcipher_setkey(tfm, key,
+						       cipher_tv[i].klen);
 			if (ret) {
 				printk("setkey() failed flags=%x\n",
-				       crypto_blkcipher_get_flags(tfm));
+				       crypto_ablkcipher_get_flags(tfm));
 
 				if (!cipher_tv[i].fail)
 					goto out;
@@ -268,19 +292,28 @@
 			sg_set_buf(&sg[0], cipher_tv[i].input,
 				   cipher_tv[i].ilen);
 
-			iv_len = crypto_blkcipher_ivsize(tfm);
-			if (iv_len)
-				crypto_blkcipher_set_iv(tfm, cipher_tv[i].iv,
-							iv_len);
+			ablkcipher_request_set_crypt(req, sg, sg,
+						     cipher_tv[i].ilen,
+						     cipher_tv[i].iv);
 
-			len = cipher_tv[i].ilen;
 			ret = enc ?
-				crypto_blkcipher_encrypt(&desc, sg, sg, len) :
-				crypto_blkcipher_decrypt(&desc, sg, sg, len);
+				crypto_ablkcipher_encrypt(req) :
+				crypto_ablkcipher_decrypt(req);
 
-			if (ret) {
-				printk("%s () failed flags=%x\n", e,
-				       desc.flags);
+			switch (ret) {
+			case 0:
+				break;
+			case -EINPROGRESS:
+			case -EBUSY:
+				ret = wait_for_completion_interruptible(
+					&result.completion);
+				if (!ret && !((ret = result.err))) {
+					INIT_COMPLETION(result.completion);
+					break;
+				}
+				/* fall through */
+			default:
+				printk("%s () failed err=%d\n", e, -ret);
 				goto out;
 			}
 
@@ -303,17 +336,17 @@
 			printk("test %u (%d bit key):\n",
 			j, cipher_tv[i].klen * 8);
 
-			crypto_blkcipher_clear_flags(tfm, ~0);
+			crypto_ablkcipher_clear_flags(tfm, ~0);
 			if (cipher_tv[i].wk)
-				crypto_blkcipher_set_flags(
+				crypto_ablkcipher_set_flags(
 					tfm, CRYPTO_TFM_REQ_WEAK_KEY);
 			key = cipher_tv[i].key;
 
-			ret = crypto_blkcipher_setkey(tfm, key,
-						      cipher_tv[i].klen);
+			ret = crypto_ablkcipher_setkey(tfm, key,
+						       cipher_tv[i].klen);
 			if (ret) {
 				printk("setkey() failed flags=%x\n",
-				       crypto_blkcipher_get_flags(tfm));
+				       crypto_ablkcipher_get_flags(tfm));
 
 				if (!cipher_tv[i].fail)
 					goto out;
@@ -329,19 +362,28 @@
 					   cipher_tv[i].tap[k]);
 			}
 
-			iv_len = crypto_blkcipher_ivsize(tfm);
-			if (iv_len)
-				crypto_blkcipher_set_iv(tfm, cipher_tv[i].iv,
-							iv_len);
+			ablkcipher_request_set_crypt(req, sg, sg,
+						     cipher_tv[i].ilen,
+						     cipher_tv[i].iv);
 
-			len = cipher_tv[i].ilen;
 			ret = enc ?
-				crypto_blkcipher_encrypt(&desc, sg, sg, len) :
-				crypto_blkcipher_decrypt(&desc, sg, sg, len);
+				crypto_ablkcipher_encrypt(req) :
+				crypto_ablkcipher_decrypt(req);
 
-			if (ret) {
-				printk("%s () failed flags=%x\n", e,
-				       desc.flags);
+			switch (ret) {
+			case 0:
+				break;
+			case -EINPROGRESS:
+			case -EBUSY:
+				ret = wait_for_completion_interruptible(
+					&result.completion);
+				if (!ret && !((ret = result.err))) {
+					INIT_COMPLETION(result.completion);
+					break;
+				}
+				/* fall through */
+			default:
+				printk("%s () failed err=%d\n", e, -ret);
 				goto out;
 			}
 
@@ -360,7 +402,8 @@
 	}
 
 out:
-	crypto_free_blkcipher(tfm);
+	crypto_free_ablkcipher(tfm);
+	ablkcipher_request_free(req);
 }
 
 static int test_cipher_jiffies(struct blkcipher_desc *desc, int enc, char *p,
@@ -832,7 +875,7 @@
 
 	while (*name) {
 		printk("alg %s ", *name);
-		printk(crypto_has_alg(*name, 0, CRYPTO_ALG_ASYNC) ?
+		printk(crypto_has_alg(*name, 0, 0) ?
 		       "found\n" : "not found\n");
 		name++;
 	}
diff --git a/crypto/xcbc.c b/crypto/xcbc.c
index 53e8ccb..9f502b8 100644
--- a/crypto/xcbc.c
+++ b/crypto/xcbc.c
@@ -288,12 +288,18 @@
 	crypto_free_cipher(ctx->child);
 }
 
-static struct crypto_instance *xcbc_alloc(void *param, unsigned int len)
+static struct crypto_instance *xcbc_alloc(struct rtattr **tb)
 {
 	struct crypto_instance *inst;
 	struct crypto_alg *alg;
-	alg = crypto_get_attr_alg(param, len, CRYPTO_ALG_TYPE_CIPHER,
-				  CRYPTO_ALG_TYPE_HASH_MASK | CRYPTO_ALG_ASYNC);
+	int err;
+
+	err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_HASH);
+	if (err)
+		return ERR_PTR(err);
+
+	alg = crypto_get_attr_alg(tb, CRYPTO_ALG_TYPE_CIPHER,
+				  CRYPTO_ALG_TYPE_MASK);
 	if (IS_ERR(alg))
 		return ERR_PTR(PTR_ERR(alg));
 
diff --git a/drivers/Makefile b/drivers/Makefile
index 920c975..26ca903 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -58,7 +58,7 @@
 obj-$(CONFIG_INPUT)		+= input/
 obj-$(CONFIG_I2O)		+= message/
 obj-$(CONFIG_RTC_LIB)		+= rtc/
-obj-$(CONFIG_I2C)		+= i2c/
+obj-y				+= i2c/
 obj-$(CONFIG_W1)		+= w1/
 obj-$(CONFIG_HWMON)		+= hwmon/
 obj-$(CONFIG_PHONE)		+= telephony/
diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c
index 2f2e796..c4efc0c 100644
--- a/drivers/acpi/processor_perflib.c
+++ b/drivers/acpi/processor_perflib.c
@@ -433,49 +433,6 @@
 			   PDE(inode)->data);
 }
 
-static ssize_t
-acpi_processor_write_performance(struct file *file,
-				 const char __user * buffer,
-				 size_t count, loff_t * data)
-{
-	int result = 0;
-	struct seq_file *m = file->private_data;
-	struct acpi_processor *pr = m->private;
-	struct acpi_processor_performance *perf;
-	char state_string[12] = { '\0' };
-	unsigned int new_state = 0;
-	struct cpufreq_policy policy;
-
-
-	if (!pr || (count > sizeof(state_string) - 1))
-		return -EINVAL;
-
-	perf = pr->performance;
-	if (!perf)
-		return -EINVAL;
-
-	if (copy_from_user(state_string, buffer, count))
-		return -EFAULT;
-
-	state_string[count] = '\0';
-	new_state = simple_strtoul(state_string, NULL, 0);
-
-	if (new_state >= perf->state_count)
-		return -EINVAL;
-
-	cpufreq_get_policy(&policy, pr->id);
-
-	policy.cpu = pr->id;
-	policy.min = perf->states[new_state].core_frequency * 1000;
-	policy.max = perf->states[new_state].core_frequency * 1000;
-
-	result = cpufreq_set_policy(&policy);
-	if (result)
-		return result;
-
-	return count;
-}
-
 static void acpi_cpufreq_add_file(struct acpi_processor *pr)
 {
 	struct proc_dir_entry *entry = NULL;
@@ -487,10 +444,9 @@
 
 	/* add file 'performance' [R/W] */
 	entry = create_proc_entry(ACPI_PROCESSOR_FILE_PERFORMANCE,
-				  S_IFREG | S_IRUGO | S_IWUSR,
+				  S_IFREG | S_IRUGO,
 				  acpi_device_dir(device));
 	if (entry){
-		acpi_processor_perf_fops.write = acpi_processor_write_performance;
 		entry->proc_fops = &acpi_processor_perf_fops;
 		entry->data = acpi_driver_data(device);
 		entry->owner = THIS_MODULE;
diff --git a/drivers/atm/adummy.c b/drivers/atm/adummy.c
index 8d60c4eb..2ebd07f 100644
--- a/drivers/atm/adummy.c
+++ b/drivers/atm/adummy.c
@@ -6,7 +6,6 @@
 #include <linux/version.h>
 #include <linux/kernel.h>
 #include <linux/skbuff.h>
-#include <linux/pci.h>
 #include <linux/errno.h>
 #include <linux/types.h>
 #include <linux/string.h>
diff --git a/drivers/base/base.h b/drivers/base/base.h
index d597f26..5512d84 100644
--- a/drivers/base/base.h
+++ b/drivers/base/base.h
@@ -45,3 +45,5 @@
 extern char *make_class_name(const char *name, struct kobject *kobj);
 
 extern void devres_release_all(struct device *dev);
+
+extern struct kset devices_subsys;
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index 1d76e23..dca7348 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -17,7 +17,7 @@
 #include "power/power.h"
 
 #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)
+#define to_bus(obj) container_of(obj, struct bus_type, subsys.kobj)
 
 /*
  * sysfs bindings for drivers
@@ -123,7 +123,7 @@
 {
 	int error;
 	if (get_bus(bus)) {
-		error = sysfs_create_file(&bus->subsys.kset.kobj, &attr->attr);
+		error = sysfs_create_file(&bus->subsys.kobj, &attr->attr);
 		put_bus(bus);
 	} else
 		error = -EINVAL;
@@ -133,7 +133,7 @@
 void bus_remove_file(struct bus_type * bus, struct bus_attribute * attr)
 {
 	if (get_bus(bus)) {
-		sysfs_remove_file(&bus->subsys.kset.kobj, &attr->attr);
+		sysfs_remove_file(&bus->subsys.kobj, &attr->attr);
 		put_bus(bus);
 	}
 }
@@ -397,7 +397,7 @@
 static int make_deprecated_bus_links(struct device *dev)
 {
 	return sysfs_create_link(&dev->kobj,
-				 &dev->bus->subsys.kset.kobj, "bus");
+				 &dev->bus->subsys.kobj, "bus");
 }
 
 static void remove_deprecated_bus_links(struct device *dev)
@@ -431,7 +431,7 @@
 		if (error)
 			goto out_id;
 		error = sysfs_create_link(&dev->kobj,
-				&dev->bus->subsys.kset.kobj, "subsystem");
+				&dev->bus->subsys.kobj, "subsystem");
 		if (error)
 			goto out_subsys;
 		error = make_deprecated_bus_links(dev);
@@ -810,7 +810,7 @@
 
 	BLOCKING_INIT_NOTIFIER_HEAD(&bus->bus_notifier);
 
-	retval = kobject_set_name(&bus->subsys.kset.kobj, "%s", bus->name);
+	retval = kobject_set_name(&bus->subsys.kobj, "%s", bus->name);
 	if (retval)
 		goto out;
 
@@ -820,13 +820,13 @@
 		goto out;
 
 	kobject_set_name(&bus->devices.kobj, "devices");
-	bus->devices.subsys = &bus->subsys;
+	bus->devices.kobj.parent = &bus->subsys.kobj;
 	retval = kset_register(&bus->devices);
 	if (retval)
 		goto bus_devices_fail;
 
 	kobject_set_name(&bus->drivers.kobj, "drivers");
-	bus->drivers.subsys = &bus->subsys;
+	bus->drivers.kobj.parent = &bus->subsys.kobj;
 	bus->drivers.ktype = &ktype_driver;
 	retval = kset_register(&bus->drivers);
 	if (retval)
diff --git a/drivers/base/class.c b/drivers/base/class.c
index 80bbb20..20c4ea6 100644
--- a/drivers/base/class.c
+++ b/drivers/base/class.c
@@ -19,10 +19,8 @@
 #include <linux/slab.h>
 #include "base.h"
 
-extern struct subsystem devices_subsys;
-
 #define to_class_attr(_attr) container_of(_attr, struct class_attribute, attr)
-#define to_class(obj) container_of(obj, struct class, subsys.kset.kobj)
+#define to_class(obj) container_of(obj, struct class, subsys.kobj)
 
 static ssize_t
 class_attr_show(struct kobject * kobj, struct attribute * attr, char * buf)
@@ -80,7 +78,7 @@
 {
 	int error;
 	if (cls) {
-		error = sysfs_create_file(&cls->subsys.kset.kobj, &attr->attr);
+		error = sysfs_create_file(&cls->subsys.kobj, &attr->attr);
 	} else
 		error = -EINVAL;
 	return error;
@@ -89,7 +87,7 @@
 void class_remove_file(struct class * cls, const struct class_attribute * attr)
 {
 	if (cls)
-		sysfs_remove_file(&cls->subsys.kset.kobj, &attr->attr);
+		sysfs_remove_file(&cls->subsys.kobj, &attr->attr);
 }
 
 static struct class *class_get(struct class *cls)
@@ -147,7 +145,7 @@
 	INIT_LIST_HEAD(&cls->interfaces);
 	kset_init(&cls->class_dirs);
 	init_MUTEX(&cls->sem);
-	error = kobject_set_name(&cls->subsys.kset.kobj, "%s", cls->name);
+	error = kobject_set_name(&cls->subsys.kobj, "%s", cls->name);
 	if (error)
 		return error;
 
@@ -611,7 +609,7 @@
 	if (parent_class_dev)
 		class_dev->kobj.parent = &parent_class_dev->kobj;
 	else
-		class_dev->kobj.parent = &parent_class->subsys.kset.kobj;
+		class_dev->kobj.parent = &parent_class->subsys.kobj;
 
 	error = kobject_add(&class_dev->kobj);
 	if (error)
@@ -619,7 +617,7 @@
 
 	/* add the needed attributes to this device */
 	error = sysfs_create_link(&class_dev->kobj,
-				  &parent_class->subsys.kset.kobj, "subsystem");
+				  &parent_class->subsys.kobj, "subsystem");
 	if (error)
 		goto out3;
 	class_dev->uevent_attr.attr.name = "uevent";
@@ -917,8 +915,8 @@
 	/* ick, this is ugly, the things we go through to keep from showing up
 	 * in sysfs... */
 	subsystem_init(&class_obj_subsys);
-	if (!class_obj_subsys.kset.subsys)
-			class_obj_subsys.kset.subsys = &class_obj_subsys;
+	if (!class_obj_subsys.kobj.parent)
+		class_obj_subsys.kobj.parent = &class_obj_subsys.kobj;
 	return 0;
 }
 
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 8aa090d..b78fc1e 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -252,7 +252,7 @@
 	struct kobject *top_kobj;
 	struct kset *kset;
 	char *envp[32];
-	char data[PAGE_SIZE];
+	char *data = NULL;
 	char *pos;
 	int i;
 	size_t count = 0;
@@ -276,6 +276,10 @@
 		if (!kset->uevent_ops->filter(kset, &dev->kobj))
 			goto out;
 
+	data = (char *)get_zeroed_page(GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
 	/* let the kset specific function add its keys */
 	pos = data;
 	retval = kset->uevent_ops->uevent(kset, &dev->kobj,
@@ -290,6 +294,7 @@
 		count += sprintf(pos, "%s\n", envp[i]);
 	}
 out:
+	free_page((unsigned long)data);
 	return count;
 }
 
@@ -560,7 +565,7 @@
 	/* Set the parent to the class, not the parent device */
 	/* this keeps sysfs from having a symlink to make old udevs happy */
 	if (dev->class)
-		return &dev->class->subsys.kset.kobj;
+		return &dev->class->subsys.kobj;
 	else if (parent)
 		return &parent->kobj;
 
@@ -572,7 +577,7 @@
 	static struct kobject *virtual_dir = NULL;
 
 	if (!virtual_dir)
-		virtual_dir = kobject_add_dir(&devices_subsys.kset.kobj, "virtual");
+		virtual_dir = kobject_add_dir(&devices_subsys.kobj, "virtual");
 
 	return virtual_dir;
 }
@@ -706,12 +711,12 @@
 	}
 
 	if (dev->class) {
-		sysfs_create_link(&dev->kobj, &dev->class->subsys.kset.kobj,
+		sysfs_create_link(&dev->kobj, &dev->class->subsys.kobj,
 				  "subsystem");
 		/* If this is not a "fake" compatible device, then create the
 		 * symlink from the class to the device. */
-		if (dev->kobj.parent != &dev->class->subsys.kset.kobj)
-			sysfs_create_link(&dev->class->subsys.kset.kobj,
+		if (dev->kobj.parent != &dev->class->subsys.kobj)
+			sysfs_create_link(&dev->class->subsys.kobj,
 					  &dev->kobj, dev->bus_id);
 		if (parent) {
 			sysfs_create_link(&dev->kobj, &dev->parent->kobj,
@@ -769,8 +774,8 @@
 		sysfs_remove_link(&dev->kobj, "subsystem");
 		/* If this is not a "fake" compatible device, remove the
 		 * symlink from the class to the device. */
-		if (dev->kobj.parent != &dev->class->subsys.kset.kobj)
-			sysfs_remove_link(&dev->class->subsys.kset.kobj,
+		if (dev->kobj.parent != &dev->class->subsys.kobj)
+			sysfs_remove_link(&dev->class->subsys.kobj,
 					  dev->bus_id);
 		if (parent) {
 #ifdef CONFIG_SYSFS_DEPRECATED
@@ -870,8 +875,8 @@
 		sysfs_remove_link(&dev->kobj, "subsystem");
 		/* If this is not a "fake" compatible device, remove the
 		 * symlink from the class to the device. */
-		if (dev->kobj.parent != &dev->class->subsys.kset.kobj)
-			sysfs_remove_link(&dev->class->subsys.kset.kobj,
+		if (dev->kobj.parent != &dev->class->subsys.kobj)
+			sysfs_remove_link(&dev->class->subsys.kobj,
 					  dev->bus_id);
 		if (parent) {
 #ifdef CONFIG_SYSFS_DEPRECATED
@@ -1187,9 +1192,9 @@
 #endif
 
 	if (dev->class) {
-		sysfs_remove_link(&dev->class->subsys.kset.kobj,
+		sysfs_remove_link(&dev->class->subsys.kobj,
 				  old_symlink_name);
-		sysfs_create_link(&dev->class->subsys.kset.kobj, &dev->kobj,
+		sysfs_create_link(&dev->class->subsys.kobj, &dev->kobj,
 				  dev->bus_id);
 	}
 	put_device(dev);
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index 18dba8e..92428e5 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -226,12 +226,10 @@
  *
  *	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. If the bus specifies
- *	multithreaded probing, walking the list of drivers is done
- *	on a probing thread.
+ *	pair is found, break out and return.
  *
  *	Returns 1 if the device was bound to a driver;
- *	0 if no matching device was found or multithreaded probing is done;
+ *	0 if no matching device was found;
  *	-ENODEV if the device is not registered.
  *
  *	When called for a USB interface, @dev->parent->sem must be held.
@@ -239,7 +237,6 @@
 int device_attach(struct device * dev)
 {
 	int ret = 0;
-	struct task_struct *probe_task = ERR_PTR(-ENOMEM);
 
 	down(&dev->sem);
 	if (dev->driver) {
@@ -251,12 +248,7 @@
 			ret = 0;
 		}
 	} else {
-		if (dev->bus->multithread_probe)
-			probe_task = kthread_run(device_probe_drivers, dev,
-						 "probe-%s", dev->bus_id);
-		if(IS_ERR(probe_task))
-			ret = bus_for_each_drv(dev->bus, NULL, dev,
-					       __device_attach);
+		ret = bus_for_each_drv(dev->bus, NULL, dev, __device_attach);
 	}
 	up(&dev->sem);
 	return ret;
@@ -383,33 +375,6 @@
 	}
 }
 
-#ifdef CONFIG_PCI_MULTITHREAD_PROBE
-static int __init wait_for_probes(void)
-{
-	DEFINE_WAIT(wait);
-
-	printk(KERN_INFO "%s: waiting for %d threads\n", __FUNCTION__,
-			atomic_read(&probe_count));
-	if (!atomic_read(&probe_count))
-		return 0;
-	while (atomic_read(&probe_count)) {
-		prepare_to_wait(&probe_waitqueue, &wait, TASK_UNINTERRUPTIBLE);
-		if (atomic_read(&probe_count))
-			schedule();
-	}
-	finish_wait(&probe_waitqueue, &wait);
-	return 0;
-}
-
-core_initcall_sync(wait_for_probes);
-postcore_initcall_sync(wait_for_probes);
-arch_initcall_sync(wait_for_probes);
-subsys_initcall_sync(wait_for_probes);
-fs_initcall_sync(wait_for_probes);
-device_initcall_sync(wait_for_probes);
-late_initcall_sync(wait_for_probes);
-#endif
-
 EXPORT_SYMBOL_GPL(device_bind_driver);
 EXPORT_SYMBOL_GPL(device_release_driver);
 EXPORT_SYMBOL_GPL(device_attach);
diff --git a/drivers/base/firmware.c b/drivers/base/firmware.c
index cb1b98a..90c8629 100644
--- a/drivers/base/firmware.c
+++ b/drivers/base/firmware.c
@@ -17,13 +17,13 @@
 
 static decl_subsys(firmware, NULL, NULL);
 
-int firmware_register(struct subsystem * s)
+int firmware_register(struct kset *s)
 {
-	kset_set_kset_s(s, firmware_subsys);
+	kobj_set_kset_s(s, firmware_subsys);
 	return subsystem_register(s);
 }
 
-void firmware_unregister(struct subsystem * s)
+void firmware_unregister(struct kset *s)
 {
 	subsystem_unregister(s);
 }
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index 30480f6f..17b5ece 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -292,20 +292,22 @@
  *	@pdev:	platform device we're removing
  *
  *	Note that this function will also release all memory- and port-based
- *	resources owned by the device (@dev->resource).
+ *	resources owned by the device (@dev->resource).  This function
+ *	must _only_ be externally called in error cases.  All other usage
+ *	is a bug.
  */
 void platform_device_del(struct platform_device *pdev)
 {
 	int i;
 
 	if (pdev) {
+		device_del(&pdev->dev);
+
 		for (i = 0; i < pdev->num_resources; i++) {
 			struct resource *r = &pdev->resource[i];
 			if (r->flags & (IORESOURCE_MEM|IORESOURCE_IO))
 				release_resource(r);
 		}
-
-		device_del(&pdev->dev);
 	}
 }
 EXPORT_SYMBOL_GPL(platform_device_del);
diff --git a/drivers/base/power/shutdown.c b/drivers/base/power/shutdown.c
index 58b6f77..a47ee1b 100644
--- a/drivers/base/power/shutdown.c
+++ b/drivers/base/power/shutdown.c
@@ -16,8 +16,6 @@
 
 #define to_dev(node) container_of(node, struct device, kobj.entry)
 
-extern struct subsystem devices_subsys;
-
 
 /**
  * We handle system devices differently - we suspend and shut them
@@ -36,7 +34,7 @@
 {
 	struct device * dev, *devn;
 
-	list_for_each_entry_safe_reverse(dev, devn, &devices_subsys.kset.list,
+	list_for_each_entry_safe_reverse(dev, devn, &devices_subsys.list,
 				kobj.entry) {
 		if (dev->bus && dev->bus->shutdown) {
 			dev_dbg(dev, "shutdown\n");
diff --git a/drivers/base/sys.c b/drivers/base/sys.c
index 04e5db4..29f1291 100644
--- a/drivers/base/sys.c
+++ b/drivers/base/sys.c
@@ -25,7 +25,7 @@
 
 #include "base.h"
 
-extern struct subsystem devices_subsys;
+extern struct kset devices_subsys;
 
 #define to_sysdev(k) container_of(k, struct sys_device, kobj)
 #define to_sysdev_attr(a) container_of(a, struct sysdev_attribute, attr)
@@ -138,7 +138,7 @@
 	pr_debug("Registering sysdev class '%s'\n",
 		 kobject_name(&cls->kset.kobj));
 	INIT_LIST_HEAD(&cls->drivers);
-	cls->kset.subsys = &system_subsys;
+	cls->kset.kobj.parent = &system_subsys.kobj;
 	kset_set_kset_s(cls, system_subsys);
 	return kset_register(&cls->kset);
 }
@@ -309,7 +309,7 @@
 	pr_debug("Shutting Down System Devices\n");
 
 	down(&sysdev_drivers_lock);
-	list_for_each_entry_reverse(cls, &system_subsys.kset.list,
+	list_for_each_entry_reverse(cls, &system_subsys.list,
 				    kset.kobj.entry) {
 		struct sys_device * sysdev;
 
@@ -384,7 +384,7 @@
 
 	pr_debug("Suspending System Devices\n");
 
-	list_for_each_entry_reverse(cls, &system_subsys.kset.list,
+	list_for_each_entry_reverse(cls, &system_subsys.list,
 				    kset.kobj.entry) {
 
 		pr_debug("Suspending type '%s':\n",
@@ -457,7 +457,7 @@
 	}
 
 	/* resume other classes */
-	list_for_each_entry_continue(cls, &system_subsys.kset.list,
+	list_for_each_entry_continue(cls, &system_subsys.list,
 					kset.kobj.entry) {
 		list_for_each_entry(err_dev, &cls->kset.list, kobj.entry) {
 			pr_debug(" %s\n", kobject_name(&err_dev->kobj));
@@ -483,7 +483,7 @@
 
 	pr_debug("Resuming System Devices\n");
 
-	list_for_each_entry(cls, &system_subsys.kset.list, kset.kobj.entry) {
+	list_for_each_entry(cls, &system_subsys.list, kset.kobj.entry) {
 		struct sys_device * sysdev;
 
 		pr_debug("Resuming type '%s':\n",
@@ -501,7 +501,7 @@
 
 int __init system_bus_init(void)
 {
-	system_subsys.kset.kobj.parent = &devices_subsys.kset.kobj;
+	system_subsys.kobj.parent = &devices_subsys.kobj;
 	return subsystem_register(&system_subsys);
 }
 
diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c
index 1a6aeac..01fbdd3 100644
--- a/drivers/block/aoe/aoecmd.c
+++ b/drivers/block/aoe/aoecmd.c
@@ -194,15 +194,15 @@
 	sl = sl_tail = NULL;
 
 	read_lock(&dev_base_lock);
-	for (ifp = dev_base; ifp; dev_put(ifp), ifp = ifp->next) {
+	for_each_netdev(ifp) {
 		dev_hold(ifp);
 		if (!is_aoe_netif(ifp))
-			continue;
+			goto cont;
 
 		skb = new_skb(sizeof *h + sizeof *ch);
 		if (skb == NULL) {
 			printk(KERN_INFO "aoe: skb alloc failure\n");
-			continue;
+			goto cont;
 		}
 		skb_put(skb, sizeof *h + sizeof *ch);
 		skb->dev = ifp;
@@ -221,6 +221,8 @@
 
 		skb->next = sl;
 		sl = skb;
+cont:
+		dev_put(ifp);
 	}
 	read_unlock(&dev_base_lock);
 
diff --git a/drivers/char/agp/ali-agp.c b/drivers/char/agp/ali-agp.c
index 5b684fd..4941ddb 100644
--- a/drivers/char/agp/ali-agp.c
+++ b/drivers/char/agp/ali-agp.c
@@ -145,6 +145,7 @@
 	void *addr = agp_generic_alloc_page(agp_bridge);
 	u32 temp;
 
+	global_flush_tlb();
 	if (!addr)
 		return NULL;
 
@@ -160,6 +161,7 @@
 	if (addr) {
 		global_cache_flush();	/* is this really needed?  --hch */
 		agp_generic_destroy_page(addr);
+		global_flush_tlb();
 	}
 }
 
diff --git a/drivers/char/agp/alpha-agp.c b/drivers/char/agp/alpha-agp.c
index b0acf41c..aa8f3a3 100644
--- a/drivers/char/agp/alpha-agp.c
+++ b/drivers/char/agp/alpha-agp.c
@@ -173,7 +173,7 @@
 	/*
 	 * Build a fake pci_dev struct
 	 */
-	pdev = kmalloc(sizeof(struct pci_dev), GFP_KERNEL);
+	pdev = alloc_pci_dev();
 	if (!pdev)
 		return -ENOMEM;
 	pdev->vendor = 0xffff;
diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c
index f902d71..45aeb91 100644
--- a/drivers/char/agp/generic.c
+++ b/drivers/char/agp/generic.c
@@ -51,28 +51,6 @@
  */
 EXPORT_SYMBOL_GPL(agp_memory_reserved);
 
-#if defined(CONFIG_X86)
-int map_page_into_agp(struct page *page)
-{
-	int i;
-	i = change_page_attr(page, 1, PAGE_KERNEL_NOCACHE);
-	/* Caller's responsibility to call global_flush_tlb() for
-	 * performance reasons */
-	return i;
-}
-EXPORT_SYMBOL_GPL(map_page_into_agp);
-
-int unmap_page_from_agp(struct page *page)
-{
-	int i;
-	i = change_page_attr(page, 1, PAGE_KERNEL);
-	/* Caller's responsibility to call global_flush_tlb() for
-	 * performance reasons */
-	return i;
-}
-EXPORT_SYMBOL_GPL(unmap_page_from_agp);
-#endif
-
 /*
  * Generic routines for handling agp_memory structures -
  * They use the basic page allocation routines to do the brunt of the work.
diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c
index 55392a4..9c69f2e 100644
--- a/drivers/char/agp/intel-agp.c
+++ b/drivers/char/agp/intel-agp.c
@@ -186,8 +186,9 @@
 		return NULL;
 
 	if (change_page_attr(page, 4, PAGE_KERNEL_NOCACHE) < 0) {
+		change_page_attr(page, 4, PAGE_KERNEL);
 		global_flush_tlb();
-		__free_page(page);
+		__free_pages(page, 2);
 		return NULL;
 	}
 	global_flush_tlb();
@@ -209,7 +210,7 @@
 	global_flush_tlb();
 	put_page(page);
 	unlock_page(page);
-	free_pages((unsigned long)addr, 2);
+	__free_pages(page, 2);
 	atomic_dec(&agp_bridge->current_memory_agp);
 }
 
@@ -315,9 +316,6 @@
 	struct agp_memory *new;
 	void *addr;
 
-	if (pg_count != 1 && pg_count != 4)
-		return NULL;
-
 	switch (pg_count) {
 	case 1: addr = agp_bridge->driver->agp_alloc_page(agp_bridge);
 		global_flush_tlb();
diff --git a/drivers/char/agp/nvidia-agp.c b/drivers/char/agp/nvidia-agp.c
index 0c9dab5..6cd7373 100644
--- a/drivers/char/agp/nvidia-agp.c
+++ b/drivers/char/agp/nvidia-agp.c
@@ -320,11 +320,11 @@
 	u8 cap_ptr;
 
 	nvidia_private.dev_1 =
-		pci_find_slot((unsigned int)pdev->bus->number, PCI_DEVFN(0, 1));
+		pci_get_bus_and_slot((unsigned int)pdev->bus->number, PCI_DEVFN(0, 1));
 	nvidia_private.dev_2 =
-		pci_find_slot((unsigned int)pdev->bus->number, PCI_DEVFN(0, 2));
+		pci_get_bus_and_slot((unsigned int)pdev->bus->number, PCI_DEVFN(0, 2));
 	nvidia_private.dev_3 =
-		pci_find_slot((unsigned int)pdev->bus->number, PCI_DEVFN(30, 0));
+		pci_get_bus_and_slot((unsigned int)pdev->bus->number, PCI_DEVFN(30, 0));
 
 	if (!nvidia_private.dev_1 || !nvidia_private.dev_2 || !nvidia_private.dev_3) {
 		printk(KERN_INFO PFX "Detected an NVIDIA nForce/nForce2 "
@@ -443,6 +443,9 @@
 static void __exit agp_nvidia_cleanup(void)
 {
 	pci_unregister_driver(&agp_nvidia_pci_driver);
+	pci_dev_put(nvidia_private.dev_1);
+	pci_dev_put(nvidia_private.dev_2);
+	pci_dev_put(nvidia_private.dev_3);
 }
 
 module_init(agp_nvidia_init);
diff --git a/drivers/char/agp/parisc-agp.c b/drivers/char/agp/parisc-agp.c
index 3d83b46..f4562cc 100644
--- a/drivers/char/agp/parisc-agp.c
+++ b/drivers/char/agp/parisc-agp.c
@@ -329,7 +329,7 @@
 	struct agp_bridge_data *bridge;
 	int error = 0;
 
-	fake_bridge_dev = kmalloc(sizeof (struct pci_dev), GFP_KERNEL);
+	fake_bridge_dev = alloc_pci_dev();
 	if (!fake_bridge_dev) {
 		error = -ENOMEM;
 		goto fail;
diff --git a/drivers/char/agp/sgi-agp.c b/drivers/char/agp/sgi-agp.c
index ee8f50e..cda608c 100644
--- a/drivers/char/agp/sgi-agp.c
+++ b/drivers/char/agp/sgi-agp.c
@@ -47,9 +47,8 @@
 
 	nid = info->ca_closest_node;
 	page = alloc_pages_node(nid, GFP_KERNEL, 0);
-	if (page == NULL) {
-		return 0;
-	}
+	if (!page)
+		return NULL;
 
 	get_page(page);
 	SetPageLocked(page);
diff --git a/drivers/char/agp/sis-agp.c b/drivers/char/agp/sis-agp.c
index 125f428..eb1a1c7 100644
--- a/drivers/char/agp/sis-agp.c
+++ b/drivers/char/agp/sis-agp.c
@@ -143,96 +143,6 @@
 	.agp_type_to_mask_type  = agp_generic_type_to_mask_type,
 };
 
-static struct agp_device_ids sis_agp_device_ids[] __devinitdata =
-{
-	{
-		.device_id	= PCI_DEVICE_ID_SI_5591_AGP,
-		.chipset_name	= "5591",
-	},
-	{
-		.device_id	= PCI_DEVICE_ID_SI_530,
-		.chipset_name	= "530",
-	},
-	{
-		.device_id	= PCI_DEVICE_ID_SI_540,
-		.chipset_name	= "540",
-	},
-	{
-		.device_id	= PCI_DEVICE_ID_SI_550,
-		.chipset_name	= "550",
-	},
-	{
-		.device_id	= PCI_DEVICE_ID_SI_620,
-		.chipset_name	= "620",
-	},
-	{
-		.device_id	= PCI_DEVICE_ID_SI_630,
-		.chipset_name	= "630",
-	},
-	{
-		.device_id	= PCI_DEVICE_ID_SI_635,
-		.chipset_name	= "635",
-	},
-	{
-		.device_id	= PCI_DEVICE_ID_SI_645,
-		.chipset_name	= "645",
-	},
-	{
-		.device_id	= PCI_DEVICE_ID_SI_646,
-		.chipset_name	= "646",
-	},
-	{
-		.device_id	= PCI_DEVICE_ID_SI_648,
-		.chipset_name	= "648",
-	},
-	{
-		.device_id	= PCI_DEVICE_ID_SI_650,
-		.chipset_name	= "650",
-	},
-	{
-		.device_id  = PCI_DEVICE_ID_SI_651,
-		.chipset_name   = "651",
-	},
-	{
-		.device_id	= PCI_DEVICE_ID_SI_655,
-		.chipset_name	= "655",
-	},
-	{
-		.device_id	= PCI_DEVICE_ID_SI_661,
-		.chipset_name	= "661",
-	},
-	{
-		.device_id	= PCI_DEVICE_ID_SI_730,
-		.chipset_name	= "730",
-	},
-	{
-		.device_id	= PCI_DEVICE_ID_SI_735,
-		.chipset_name	= "735",
-	},
-	{
-		.device_id	= PCI_DEVICE_ID_SI_740,
-		.chipset_name	= "740",
-	},
-	{
-		.device_id	= PCI_DEVICE_ID_SI_741,
-		.chipset_name	= "741",
-	},
-	{
-		.device_id	= PCI_DEVICE_ID_SI_745,
-		.chipset_name	= "745",
-	},
-	{
-		.device_id	= PCI_DEVICE_ID_SI_746,
-		.chipset_name	= "746",
-	},
-	{
-		.device_id	= PCI_DEVICE_ID_SI_760,
-		.chipset_name	= "760",
-	},
-	{ }, /* dummy final entry, always present */
-};
-
-
 // chipsets that require the 'delay hack'
 static int sis_broken_chipsets[] __devinitdata = {
 	PCI_DEVICE_ID_SI_648,
@@ -269,29 +179,15 @@
 static int __devinit agp_sis_probe(struct pci_dev *pdev,
 				   const struct pci_device_id *ent)
 {
-	struct agp_device_ids *devs = sis_agp_device_ids;
 	struct agp_bridge_data *bridge;
 	u8 cap_ptr;
-	int j;
 
 	cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP);
 	if (!cap_ptr)
 		return -ENODEV;
 
-	/* probe for known chipsets */
-	for (j = 0; devs[j].chipset_name; j++) {
-		if (pdev->device == devs[j].device_id) {
-			printk(KERN_INFO PFX "Detected SiS %s chipset\n",
-					devs[j].chipset_name);
-			goto found;
-		}
-	}
 
-	printk(KERN_ERR PFX "Unsupported SiS chipset (device id: %04x)\n",
-		    pdev->device);
-	return -ENODEV;
-
-found:
+	printk(KERN_INFO PFX "Detected SiS chipset - id:%i\n", pdev->device);
 	bridge = agp_alloc_bridge();
 	if (!bridge)
 		return -ENOMEM;
@@ -320,12 +216,172 @@
 
 static struct pci_device_id agp_sis_pci_table[] = {
 	{
-	.class		= (PCI_CLASS_BRIDGE_HOST << 8),
-	.class_mask	= ~0,
-	.vendor		= PCI_VENDOR_ID_SI,
-	.device		= PCI_ANY_ID,
-	.subvendor	= PCI_ANY_ID,
-	.subdevice	= PCI_ANY_ID,
+		.class		= (PCI_CLASS_BRIDGE_HOST << 8),
+		.class_mask	= ~0,
+		.vendor		= PCI_VENDOR_ID_SI,
+		.device		= PCI_DEVICE_ID_SI_5591_AGP,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+	},
+	{
+		.class		= (PCI_CLASS_BRIDGE_HOST << 8),
+		.class_mask	= ~0,
+		.vendor		= PCI_VENDOR_ID_SI,
+		.device		= PCI_DEVICE_ID_SI_530,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+	},
+	{
+		.class		= (PCI_CLASS_BRIDGE_HOST << 8),
+		.class_mask	= ~0,
+		.vendor		= PCI_VENDOR_ID_SI,
+		.device		= PCI_DEVICE_ID_SI_540,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+	},
+	{
+		.class		= (PCI_CLASS_BRIDGE_HOST << 8),
+		.class_mask	= ~0,
+		.vendor		= PCI_VENDOR_ID_SI,
+		.device		= PCI_DEVICE_ID_SI_550,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+	},
+	{
+		.class		= (PCI_CLASS_BRIDGE_HOST << 8),
+		.class_mask	= ~0,
+		.vendor		= PCI_VENDOR_ID_SI,
+		.device		= PCI_DEVICE_ID_SI_620,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+	},
+	{
+		.class		= (PCI_CLASS_BRIDGE_HOST << 8),
+		.class_mask	= ~0,
+		.vendor		= PCI_VENDOR_ID_SI,
+		.device		= PCI_DEVICE_ID_SI_630,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+	},
+	{
+		.class		= (PCI_CLASS_BRIDGE_HOST << 8),
+		.class_mask	= ~0,
+		.vendor		= PCI_VENDOR_ID_SI,
+		.device		= PCI_DEVICE_ID_SI_635,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+	},
+	{
+		.class		= (PCI_CLASS_BRIDGE_HOST << 8),
+		.class_mask	= ~0,
+		.vendor		= PCI_VENDOR_ID_SI,
+		.device		= PCI_DEVICE_ID_SI_645,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+	},
+	{
+		.class		= (PCI_CLASS_BRIDGE_HOST << 8),
+		.class_mask	= ~0,
+		.vendor		= PCI_VENDOR_ID_SI,
+		.device		= PCI_DEVICE_ID_SI_646,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+	},
+	{
+		.class		= (PCI_CLASS_BRIDGE_HOST << 8),
+		.class_mask	= ~0,
+		.vendor		= PCI_VENDOR_ID_SI,
+		.device		= PCI_DEVICE_ID_SI_648,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+	},
+	{
+		.class		= (PCI_CLASS_BRIDGE_HOST << 8),
+		.class_mask	= ~0,
+		.vendor		= PCI_VENDOR_ID_SI,
+		.device		= PCI_DEVICE_ID_SI_650,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+	},
+	{
+		.class		= (PCI_CLASS_BRIDGE_HOST << 8),
+		.class_mask	= ~0,
+		.vendor		= PCI_VENDOR_ID_SI,
+		.device		= PCI_DEVICE_ID_SI_651,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+	},
+	{
+		.class		= (PCI_CLASS_BRIDGE_HOST << 8),
+		.class_mask	= ~0,
+		.vendor		= PCI_VENDOR_ID_SI,
+		.device		= PCI_DEVICE_ID_SI_655,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+	},
+	{
+		.class		= (PCI_CLASS_BRIDGE_HOST << 8),
+		.class_mask	= ~0,
+		.vendor		= PCI_VENDOR_ID_SI,
+		.device		= PCI_DEVICE_ID_SI_661,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+	},
+	{
+		.class		= (PCI_CLASS_BRIDGE_HOST << 8),
+		.class_mask	= ~0,
+		.vendor		= PCI_VENDOR_ID_SI,
+		.device		= PCI_DEVICE_ID_SI_730,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+	},
+	{
+		.class		= (PCI_CLASS_BRIDGE_HOST << 8),
+		.class_mask	= ~0,
+		.vendor		= PCI_VENDOR_ID_SI,
+		.device		= PCI_DEVICE_ID_SI_735,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+	},
+	{
+		.class		= (PCI_CLASS_BRIDGE_HOST << 8),
+		.class_mask	= ~0,
+		.vendor		= PCI_VENDOR_ID_SI,
+		.device		= PCI_DEVICE_ID_SI_740,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+	},
+	{
+		.class		= (PCI_CLASS_BRIDGE_HOST << 8),
+		.class_mask	= ~0,
+		.vendor		= PCI_VENDOR_ID_SI,
+		.device		= PCI_DEVICE_ID_SI_741,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+	},
+	{
+		.class		= (PCI_CLASS_BRIDGE_HOST << 8),
+		.class_mask	= ~0,
+		.vendor		= PCI_VENDOR_ID_SI,
+		.device		= PCI_DEVICE_ID_SI_745,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+	},
+	{
+		.class		= (PCI_CLASS_BRIDGE_HOST << 8),
+		.class_mask	= ~0,
+		.vendor		= PCI_VENDOR_ID_SI,
+		.device		= PCI_DEVICE_ID_SI_746,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+	},
+	{
+		.class		= (PCI_CLASS_BRIDGE_HOST << 8),
+		.class_mask	= ~0,
+		.vendor		= PCI_VENDOR_ID_SI,
+		.device		= PCI_DEVICE_ID_SI_760,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
 	},
 	{ }
 };
diff --git a/drivers/char/agp/sworks-agp.c b/drivers/char/agp/sworks-agp.c
index 55212a3..551ef25 100644
--- a/drivers/char/agp/sworks-agp.c
+++ b/drivers/char/agp/sworks-agp.c
@@ -455,15 +455,6 @@
 	u32 temp, temp2;
 	u8 cap_ptr = 0;
 
-	/* Everything is on func 1 here so we are hardcoding function one */
-	bridge_dev = pci_find_slot((unsigned int)pdev->bus->number,
-			PCI_DEVFN(0, 1));
-	if (!bridge_dev) {
-		printk(KERN_INFO PFX "Detected a Serverworks chipset "
-		       "but could not find the secondary device.\n");
-		return -ENODEV;
-	}
-
 	cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP);
 
 	switch (pdev->device) {
@@ -483,6 +474,15 @@
 		return -ENODEV;
 	}
 
+	/* Everything is on func 1 here so we are hardcoding function one */
+	bridge_dev = pci_get_bus_and_slot((unsigned int)pdev->bus->number,
+			PCI_DEVFN(0, 1));
+	if (!bridge_dev) {
+		printk(KERN_INFO PFX "Detected a Serverworks chipset "
+		       "but could not find the secondary device.\n");
+		return -ENODEV;
+	}
+
 	serverworks_private.svrwrks_dev = bridge_dev;
 	serverworks_private.gart_addr_ofs = 0x10;
 
@@ -515,7 +515,7 @@
 
 	bridge->driver = &sworks_driver;
 	bridge->dev_private_data = &serverworks_private,
-	bridge->dev = pdev;
+	bridge->dev = pci_dev_get(pdev);
 
 	pci_set_drvdata(pdev, bridge);
 	return agp_add_bridge(bridge);
@@ -525,8 +525,11 @@
 {
 	struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
 
+	pci_dev_put(bridge->dev);
 	agp_remove_bridge(bridge);
 	agp_put_bridge(bridge);
+	pci_dev_put(serverworks_private.svrwrks_dev);
+	serverworks_private.svrwrks_dev = NULL;
 }
 
 static struct pci_device_id agp_serverworks_pci_table[] = {
diff --git a/drivers/char/hw_random/via-rng.c b/drivers/char/hw_random/via-rng.c
index 9ebf84d..ec435cb 100644
--- a/drivers/char/hw_random/via-rng.c
+++ b/drivers/char/hw_random/via-rng.c
@@ -26,7 +26,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/pci.h>
 #include <linux/hw_random.h>
 #include <asm/io.h>
 #include <asm/msr.h>
diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c
index cb8d691..c06e86a 100644
--- a/drivers/char/keyboard.c
+++ b/drivers/char/keyboard.c
@@ -41,7 +41,6 @@
 #include <linux/input.h>
 #include <linux/reboot.h>
 
-static void kbd_disconnect(struct input_handle *handle);
 extern void ctrl_alt_del(void);
 
 /*
@@ -159,65 +158,41 @@
 static int sysrq_alt;
 
 /*
- * Translation of scancodes to keycodes. We set them on only the first attached
- * keyboard - for per-keyboard setting, /dev/input/event is more useful.
+ * Translation of scancodes to keycodes. We set them on only the first
+ * keyboard in the list that accepts the scancode and keycode.
+ * Explanation for not choosing the first attached keyboard anymore:
+ *  USB keyboards for example have two event devices: one for all "normal"
+ *  keys and one for extra function keys (like "volume up", "make coffee",
+ *  etc.). So this means that scancodes for the extra function keys won't
+ *  be valid for the first event device, but will be for the second.
  */
 int getkeycode(unsigned int scancode)
 {
-	struct list_head *node;
-	struct input_dev *dev = NULL;
+	struct input_handle *handle;
+	int keycode;
+	int error = -ENODEV;
 
-	list_for_each(node, &kbd_handler.h_list) {
-		struct input_handle *handle = to_handle_h(node);
-		if (handle->dev->keycodesize) {
-			dev = handle->dev;
-			break;
-		}
+	list_for_each_entry(handle, &kbd_handler.h_list, h_node) {
+		error = handle->dev->getkeycode(handle->dev, scancode, &keycode);
+		if (!error)
+			return keycode;
 	}
 
-	if (!dev)
-		return -ENODEV;
-
-	if (scancode >= dev->keycodemax)
-		return -EINVAL;
-
-	return INPUT_KEYCODE(dev, scancode);
+	return error;
 }
 
 int setkeycode(unsigned int scancode, unsigned int keycode)
 {
-	struct list_head *node;
-	struct input_dev *dev = NULL;
-	unsigned int i, oldkey;
+	struct input_handle *handle;
+	int error = -ENODEV;
 
-	list_for_each(node, &kbd_handler.h_list) {
-		struct input_handle *handle = to_handle_h(node);
-		if (handle->dev->keycodesize) {
-			dev = handle->dev;
+	list_for_each_entry(handle, &kbd_handler.h_list, h_node) {
+		error = handle->dev->setkeycode(handle->dev, scancode, keycode);
+		if (!error)
 			break;
-		}
 	}
 
-	if (!dev)
-		return -ENODEV;
-
-	if (scancode >= dev->keycodemax)
-		return -EINVAL;
-	if (keycode < 0 || keycode > KEY_MAX)
-		return -EINVAL;
-	if (dev->keycodesize < sizeof(keycode) && (keycode >> (dev->keycodesize * 8)))
-		return -EINVAL;
-
-	oldkey = SET_INPUT_KEYCODE(dev, scancode, keycode);
-
-	clear_bit(oldkey, dev->keybit);
-	set_bit(keycode, dev->keybit);
-
-	for (i = 0; i < dev->keycodemax; i++)
-		if (INPUT_KEYCODE(dev,i) == oldkey)
-			set_bit(oldkey, dev->keybit);
-
-	return 0;
+	return error;
 }
 
 /*
@@ -225,10 +200,9 @@
  */
 static void kd_nosound(unsigned long ignored)
 {
-	struct list_head *node;
+	struct input_handle *handle;
 
-	list_for_each(node, &kbd_handler.h_list) {
-		struct input_handle *handle = to_handle_h(node);
+	list_for_each_entry(handle, &kbd_handler.h_list, h_node) {
 		if (test_bit(EV_SND, handle->dev->evbit)) {
 			if (test_bit(SND_TONE, handle->dev->sndbit))
 				input_inject_event(handle, EV_SND, SND_TONE, 0);
@@ -1161,7 +1135,7 @@
 
 	if ((raw_mode = (kbd->kbdmode == VC_RAW)) && !hw_raw)
 		if (emulate_raw(vc, keycode, !down << 7))
-			if (keycode < BTN_MISC)
+			if (keycode < BTN_MISC && printk_ratelimit())
 				printk(KERN_WARNING "keyboard.c: can't emulate rawmode for keycode %d\n", keycode);
 
 #ifdef CONFIG_MAGIC_SYSRQ	       /* Handle the SysRq Hack */
@@ -1285,11 +1259,11 @@
  * likes it, it can open it and get events from it. In this (kbd_connect)
  * function, we should decide which VT to bind that keyboard to initially.
  */
-static struct input_handle *kbd_connect(struct input_handler *handler,
-					struct input_dev *dev,
-					const struct input_device_id *id)
+static int kbd_connect(struct input_handler *handler, struct input_dev *dev,
+			const struct input_device_id *id)
 {
 	struct input_handle *handle;
+	int error;
 	int i;
 
 	for (i = KEY_RESERVED; i < BTN_MISC; i++)
@@ -1297,24 +1271,37 @@
 			break;
 
 	if (i == BTN_MISC && !test_bit(EV_SND, dev->evbit))
-		return NULL;
+		return -ENODEV;
 
 	handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL);
 	if (!handle)
-		return NULL;
+		return -ENOMEM;
 
 	handle->dev = dev;
 	handle->handler = handler;
 	handle->name = "kbd";
 
-	input_open_device(handle);
+	error = input_register_handle(handle);
+	if (error)
+		goto err_free_handle;
 
-	return handle;
+	error = input_open_device(handle);
+	if (error)
+		goto err_unregister_handle;
+
+	return 0;
+
+ err_unregister_handle:
+	input_unregister_handle(handle);
+ err_free_handle:
+	kfree(handle);
+	return error;
 }
 
 static void kbd_disconnect(struct input_handle *handle)
 {
 	input_close_device(handle);
+	input_unregister_handle(handle);
 	kfree(handle);
 }
 
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c
index 157b1d0..13808f6 100644
--- a/drivers/char/pcmcia/synclink_cs.c
+++ b/drivers/char/pcmcia/synclink_cs.c
@@ -42,7 +42,6 @@
 #include <linux/timer.h>
 #include <linux/time.h>
 #include <linux/interrupt.h>
-#include <linux/pci.h>
 #include <linux/tty.h>
 #include <linux/tty_flip.h>
 #include <linux/serial.h>
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index bb9a43c..9f273f0 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -19,7 +19,6 @@
  * 
  */
 #include <linux/module.h>
-#include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/fs.h>
 #include <linux/sched.h>
diff --git a/drivers/char/watchdog/sc1200wdt.c b/drivers/char/watchdog/sc1200wdt.c
index 1e4a8d7..2f7ba7a 100644
--- a/drivers/char/watchdog/sc1200wdt.c
+++ b/drivers/char/watchdog/sc1200wdt.c
@@ -38,7 +38,6 @@
 #include <linux/init.h>
 #include <linux/pnp.h>
 #include <linux/fs.h>
-#include <linux/pci.h>
 
 #include <asm/semaphore.h>
 #include <asm/io.h>
diff --git a/drivers/char/watchdog/scx200_wdt.c b/drivers/char/watchdog/scx200_wdt.c
index fc0e034..d4fd0fa 100644
--- a/drivers/char/watchdog/scx200_wdt.c
+++ b/drivers/char/watchdog/scx200_wdt.c
@@ -25,7 +25,7 @@
 #include <linux/notifier.h>
 #include <linux/reboot.h>
 #include <linux/fs.h>
-#include <linux/pci.h>
+#include <linux/ioport.h>
 #include <linux/scx200.h>
 
 #include <asm/uaccess.h>
diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig
index d155e81..993fa7b 100644
--- a/drivers/cpufreq/Kconfig
+++ b/drivers/cpufreq/Kconfig
@@ -9,6 +9,9 @@
 	  clock speed, you need to either enable a dynamic cpufreq governor
 	  (see below) after boot, or use a userspace tool.
 
+	  To compile this driver as a module, choose M here: the
+	  module will be called cpufreq.
+
 	  For details, take a look at <file:Documentation/cpu-freq>.
 
 	  If in doubt, say N.
@@ -16,7 +19,7 @@
 if CPU_FREQ
 
 config CPU_FREQ_TABLE
-       tristate
+	tristate
 
 config CPU_FREQ_DEBUG
 	bool "Enable CPUfreq debugging"
@@ -32,19 +35,26 @@
 	       4 to activate CPUfreq governor debugging
 
 config CPU_FREQ_STAT
-       tristate "CPU frequency translation statistics"
-       select CPU_FREQ_TABLE
-       default y
-       help
-         This driver exports CPU frequency statistics information through sysfs
-         file system
+	tristate "CPU frequency translation statistics"
+	select CPU_FREQ_TABLE
+	default y
+	help
+	  This driver exports CPU frequency statistics information through sysfs
+	  file system.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called cpufreq_stats.
+
+	  If in doubt, say N.
 
 config CPU_FREQ_STAT_DETAILS
-       bool "CPU frequency translation statistics details"
-       depends on CPU_FREQ_STAT
-       help
-         This will show detail CPU frequency translation table in sysfs file
-         system
+	bool "CPU frequency translation statistics details"
+	depends on CPU_FREQ_STAT
+	help
+	  This will show detail CPU frequency translation table in sysfs file
+	  system.
+
+	  If in doubt, say N.
 
 # Note that it is not currently possible to set the other governors (such as ondemand)
 # as the default, since if they fail to initialise, cpufreq will be
@@ -78,29 +88,38 @@
 endchoice
 
 config CPU_FREQ_GOV_PERFORMANCE
-       tristate "'performance' governor"
-       help
+	tristate "'performance' governor"
+	help
 	  This cpufreq governor sets the frequency statically to the
 	  highest available CPU frequency.
 
+	  To compile this driver as a module, choose M here: the
+	  module will be called cpufreq_performance.
+
 	  If in doubt, say Y.
 
 config CPU_FREQ_GOV_POWERSAVE
-       tristate "'powersave' governor"
-       help
+	tristate "'powersave' governor"
+	help
 	  This cpufreq governor sets the frequency statically to the
 	  lowest available CPU frequency.
 
+	  To compile this driver as a module, choose M here: the
+	  module will be called cpufreq_powersave.
+
 	  If in doubt, say Y.
 
 config CPU_FREQ_GOV_USERSPACE
-       tristate "'userspace' governor for userspace frequency scaling"
-       help
+	tristate "'userspace' governor for userspace frequency scaling"
+	help
 	  Enable this cpufreq governor when you either want to set the
 	  CPU frequency manually or when an userspace program shall
 	  be able to set the CPU dynamically, like on LART 
 	  <http://www.lartmaker.nl/>.
 
+	  To compile this driver as a module, choose M here: the
+	  module will be called cpufreq_userspace.
+
 	  For details, take a look at <file:Documentation/cpu-freq/>.
 
 	  If in doubt, say Y.
@@ -116,6 +135,9 @@
 	  do fast frequency switching (i.e, very low latency frequency
 	  transitions). 
 
+	  To compile this driver as a module, choose M here: the
+	  module will be called cpufreq_ondemand.
+
 	  For details, take a look at linux/Documentation/cpu-freq.
 
 	  If in doubt, say N.
@@ -136,6 +158,9 @@
 	  step-by-step latency issues between the minimum and maximum frequency
 	  transitions in the CPU) you will probably want to use this governor.
 
+	  To compile this driver as a module, choose M here: the
+	  module will be called cpufreq_conservative.
+
 	  For details, take a look at linux/Documentation/cpu-freq.
 
 	  If in doubt, say N.
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 3162010..893dbaf 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -768,6 +768,9 @@
 		unlock_policy_rwsem_write(cpu);
 		goto err_out;
 	}
+	policy->user_policy.min = policy->cpuinfo.min_freq;
+	policy->user_policy.max = policy->cpuinfo.max_freq;
+	policy->user_policy.governor = policy->governor;
 
 #ifdef CONFIG_SMP
 	for_each_cpu_mask(j, policy->cpus) {
@@ -858,10 +861,13 @@
 
 	policy->governor = NULL; /* to assure that the starting sequence is
 				  * run in cpufreq_set_policy */
-	unlock_policy_rwsem_write(cpu);
 
 	/* set default policy */
-	ret = cpufreq_set_policy(&new_policy);
+	ret = __cpufreq_set_policy(policy, &new_policy);
+	policy->user_policy.policy = policy->policy;
+
+	unlock_policy_rwsem_write(cpu);
+
 	if (ret) {
 		dprintk("setting policy failed\n");
 		goto err_out_unregister;
@@ -1620,43 +1626,6 @@
 }
 
 /**
- *	cpufreq_set_policy - set a new CPUFreq policy
- *	@policy: policy to be set.
- *
- *	Sets a new CPU frequency and voltage scaling policy.
- */
-int cpufreq_set_policy(struct cpufreq_policy *policy)
-{
-	int ret = 0;
-	struct cpufreq_policy *data;
-
-	if (!policy)
-		return -EINVAL;
-
-	data = cpufreq_cpu_get(policy->cpu);
-	if (!data)
-		return -EINVAL;
-
-	if (unlikely(lock_policy_rwsem_write(policy->cpu)))
-		return -EINVAL;
-
-
-	ret = __cpufreq_set_policy(data, policy);
-	data->user_policy.min = data->min;
-	data->user_policy.max = data->max;
-	data->user_policy.policy = data->policy;
-	data->user_policy.governor = data->governor;
-
-	unlock_policy_rwsem_write(policy->cpu);
-
-	cpufreq_cpu_put(data);
-
-	return ret;
-}
-EXPORT_SYMBOL(cpufreq_set_policy);
-
-
-/**
  *	cpufreq_update_policy - re-evaluate an existing cpufreq policy
  *	@cpu: CPU which shall be re-evaluated
  *
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index ff8c4be..f21fe66 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -1,10 +1,10 @@
 menu "Hardware crypto devices"
 
 config CRYPTO_DEV_PADLOCK
-	tristate "Support for VIA PadLock ACE"
+	bool "Support for VIA PadLock ACE"
 	depends on X86_32
 	select CRYPTO_ALGAPI
-	default m
+	default y
 	help
 	  Some VIA processors come with an integrated crypto engine
 	  (so called VIA PadLock ACE, Advanced Cryptography Engine)
@@ -14,16 +14,6 @@
 	  The instructions are used only when the CPU supports them.
 	  Otherwise software encryption is used.
 
-	  Selecting M for this option will compile a helper module
-	  padlock.ko that should autoload all below configured
-	  algorithms. Don't worry if your hardware does not support
-	  some or all of them. In such case padlock.ko will
-	  simply write a single line into the kernel log informing
-	  about its failure but everything will keep working fine.
-
-	  If you are unsure, say M. The compiled module will be
-	  called padlock.ko
-
 config CRYPTO_DEV_PADLOCK_AES
 	tristate "PadLock driver for AES algorithm"
 	depends on CRYPTO_DEV_PADLOCK
@@ -55,7 +45,7 @@
 
 config CRYPTO_DEV_GEODE
 	tristate "Support for the Geode LX AES engine"
-	depends on CRYPTO && X86_32 && PCI
+	depends on X86_32 && PCI
 	select CRYPTO_ALGAPI
 	select CRYPTO_BLKCIPHER
 	default m
diff --git a/drivers/crypto/Makefile b/drivers/crypto/Makefile
index 6059cf8..d070030 100644
--- a/drivers/crypto/Makefile
+++ b/drivers/crypto/Makefile
@@ -1,4 +1,3 @@
-obj-$(CONFIG_CRYPTO_DEV_PADLOCK) += padlock.o
 obj-$(CONFIG_CRYPTO_DEV_PADLOCK_AES) += padlock-aes.o
 obj-$(CONFIG_CRYPTO_DEV_PADLOCK_SHA) += padlock-sha.o
 obj-$(CONFIG_CRYPTO_DEV_GEODE) += geode-aes.o
diff --git a/drivers/crypto/padlock.c b/drivers/crypto/padlock.c
deleted file mode 100644
index d6d7dd5..0000000
--- a/drivers/crypto/padlock.c
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Cryptographic API.
- *
- * Support for VIA PadLock hardware crypto engine.
- *
- * Copyright (c) 2006  Michal Ludvig <michal@logix.cz>
- *
- * This program is free software; you can redistribute it and/or 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/init.h>
-#include <linux/errno.h>
-#include <linux/crypto.h>
-#include <linux/cryptohash.h>
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/scatterlist.h>
-#include "padlock.h"
-
-static int __init padlock_init(void)
-{
-	int success = 0;
-
-	if (crypto_has_cipher("aes-padlock", 0, 0))
-		success++;
-
-	if (crypto_has_hash("sha1-padlock", 0, 0))
-		success++;
-
-	if (crypto_has_hash("sha256-padlock", 0, 0))
-		success++;
-
-	if (!success) {
-		printk(KERN_WARNING PFX "No VIA PadLock drivers have been loaded.\n");
-		return -ENODEV;
-	}
-
-	printk(KERN_NOTICE PFX "%d drivers are available.\n", success);
-
-	return 0;
-}
-
-static void __exit padlock_fini(void)
-{
-}
-
-module_init(padlock_init);
-module_exit(padlock_fini);
-
-MODULE_DESCRIPTION("Load all configured PadLock algorithms.");
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Michal Ludvig");
-
diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c
index c6281cc..1324984 100644
--- a/drivers/firmware/efivars.c
+++ b/drivers/firmware/efivars.c
@@ -409,7 +409,7 @@
 };
 
 static ssize_t
-dummy(struct subsystem *sub, char *buf)
+dummy(struct kset *kset, char *buf)
 {
 	return -ENODEV;
 }
@@ -422,7 +422,7 @@
 
 
 static ssize_t
-efivar_create(struct subsystem *sub, const char *buf, size_t count)
+efivar_create(struct kset *kset, const char *buf, size_t count)
 {
 	struct efi_variable *new_var = (struct efi_variable *)buf;
 	struct efivar_entry *search_efivar, *n;
@@ -480,7 +480,7 @@
 }
 
 static ssize_t
-efivar_delete(struct subsystem *sub, const char *buf, size_t count)
+efivar_delete(struct kset *kset, const char *buf, size_t count)
 {
 	struct efi_variable *del_var = (struct efi_variable *)buf;
 	struct efivar_entry *search_efivar, *n;
@@ -551,11 +551,11 @@
  * the efivars driver
  */
 static ssize_t
-systab_read(struct subsystem *entry, char *buf)
+systab_read(struct kset *kset, char *buf)
 {
 	char *str = buf;
 
-	if (!entry || !buf)
+	if (!kset || !buf)
 		return -EINVAL;
 
 	if (efi.mps != EFI_INVALID_TABLE_ADDR)
@@ -687,7 +687,7 @@
 		goto out_free;
 	}
 
-	kset_set_kset_s(&vars_subsys, efi_subsys);
+	kobj_set_kset_s(&vars_subsys, efi_subsys);
 
 	error = subsystem_register(&vars_subsys);
 
diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig
index 11935f6..434a61b 100644
--- a/drivers/i2c/Kconfig
+++ b/drivers/i2c/Kconfig
@@ -2,9 +2,7 @@
 # I2C subsystem configuration
 #
 
-menu "I2C support"
-
-config I2C
+menuconfig I2C
 	tristate "I2C support"
 	---help---
 	  I2C (pronounce: I-square-C) is a slow serial bus protocol used in
@@ -22,9 +20,14 @@
 	  This I2C support can also be built as a module.  If so, the module
 	  will be called i2c-core.
 
+if I2C
+
+config I2C_BOARDINFO
+	boolean
+	default y
+
 config I2C_CHARDEV
 	tristate "I2C device interface"
-	depends on I2C
 	help
 	  Say Y here to use i2c-* device files, usually found in the /dev
 	  directory on your system.  They make it possible to have user-space
@@ -40,7 +43,6 @@
 
 config I2C_DEBUG_CORE
 	bool "I2C Core debugging messages"
-	depends on I2C
 	help
 	  Say Y here if you want the I2C core to produce a bunch of debug
 	  messages to the system log.  Select this if you are having a
@@ -48,7 +50,6 @@
 
 config I2C_DEBUG_ALGO
 	bool "I2C Algorithm debugging messages"
-	depends on I2C
 	help
 	  Say Y here if you want the I2C algorithm drivers to produce a bunch
 	  of debug messages to the system log.  Select this if you are having
@@ -57,7 +58,6 @@
 
 config I2C_DEBUG_BUS
 	bool "I2C Bus debugging messages"
-	depends on I2C
 	help
 	  Say Y here if you want the I2C bus drivers to produce a bunch of
 	  debug messages to the system log.  Select this if you are having
@@ -66,12 +66,10 @@
 
 config I2C_DEBUG_CHIP
 	bool "I2C Chip debugging messages"
-	depends on I2C
 	help
 	  Say Y here if you want the I2C chip drivers to produce a bunch of
 	  debug messages to the system log.  Select this if you are having
 	  a problem with I2C support and want to see more of what is going
 	  on.
 
-endmenu
-
+endif # I2C
diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile
index 71c5a85..ba26e6c 100644
--- a/drivers/i2c/Makefile
+++ b/drivers/i2c/Makefile
@@ -2,6 +2,7 @@
 # Makefile for the i2c core.
 #
 
+obj-$(CONFIG_I2C_BOARDINFO)	+= i2c-boardinfo.o
 obj-$(CONFIG_I2C)		+= i2c-core.o
 obj-$(CONFIG_I2C_CHARDEV)	+= i2c-dev.o
 obj-y				+= busses/ chips/ algos/
diff --git a/drivers/i2c/algos/Kconfig b/drivers/i2c/algos/Kconfig
index af02034..5889907 100644
--- a/drivers/i2c/algos/Kconfig
+++ b/drivers/i2c/algos/Kconfig
@@ -3,11 +3,9 @@
 #
 
 menu "I2C Algorithms"
-	depends on I2C
 
 config I2C_ALGOBIT
 	tristate "I2C bit-banging interfaces"
-	depends on I2C
 	help
 	  This allows you to use a range of I2C adapters called bit-banging
 	  adapters.  Say Y if you own an I2C adapter belonging to this class
@@ -18,7 +16,6 @@
 
 config I2C_ALGOPCF
 	tristate "I2C PCF 8584 interfaces"
-	depends on I2C
 	help
 	  This allows you to use a range of I2C adapters called PCF adapters.
 	  Say Y if you own an I2C adapter belonging to this class and then say
@@ -29,7 +26,6 @@
 
 config I2C_ALGOPCA
 	tristate "I2C PCA 9564 interfaces"
-	depends on I2C
 	help
 	  This allows you to use a range of I2C adapters called PCA adapters.
 	  Say Y if you own an I2C adapter belonging to this class and then say
@@ -40,11 +36,11 @@
 
 config I2C_ALGO8XX
 	tristate "MPC8xx CPM I2C interface"
-	depends on 8xx && I2C
+	depends on 8xx
 
 config I2C_ALGO_SGI
 	tristate "I2C SGI interfaces"
-	depends on I2C && (SGI_IP22 || SGI_IP32 || X86_VISWS)
+	depends on SGI_IP22 || SGI_IP32 || X86_VISWS
 	help
 	  Supports the SGI interfaces like the ones found on SGI Indy VINO
 	  or SGI O2 MACE.
diff --git a/drivers/i2c/algos/i2c-algo-bit.c b/drivers/i2c/algos/i2c-algo-bit.c
index 95aa539..8a5f582 100644
--- a/drivers/i2c/algos/i2c-algo-bit.c
+++ b/drivers/i2c/algos/i2c-algo-bit.c
@@ -33,19 +33,30 @@
 
 
 /* ----- global defines ----------------------------------------------- */
-#define DEB(x) if (i2c_debug>=1) x;
-#define DEB2(x) if (i2c_debug>=2) x;
-#define DEBSTAT(x) if (i2c_debug>=3) x; /* print several statistical values*/
-#define DEBPROTO(x) if (i2c_debug>=9) { x; }
- 	/* debug the protocol by showing transferred bits */
 
+#ifdef DEBUG
+#define bit_dbg(level, dev, format, args...) \
+	do { \
+		if (i2c_debug >= level) \
+			dev_dbg(dev, format, ##args); \
+	} while (0)
+#else
+#define bit_dbg(level, dev, format, args...) \
+	do {} while (0)
+#endif /* DEBUG */
 
 /* ----- global variables ---------------------------------------------	*/
 
-/* module parameters:
- */
-static int i2c_debug;
 static int bit_test;	/* see if the line-setting functions work	*/
+module_param(bit_test, bool, 0);
+MODULE_PARM_DESC(bit_test, "Test the lines of the bus to see if it is stuck");
+
+#ifdef DEBUG
+static int i2c_debug = 1;
+module_param(i2c_debug, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(i2c_debug,
+		 "debug level - 0 off; 1 normal; 2 verbose; 3 very verbose");
+#endif
 
 /* --- setting states on the bus with the right timing: ---------------	*/
 
@@ -57,19 +68,19 @@
 static inline void sdalo(struct i2c_algo_bit_data *adap)
 {
 	setsda(adap,0);
-	udelay(adap->udelay);
+	udelay((adap->udelay + 1) / 2);
 }
 
 static inline void sdahi(struct i2c_algo_bit_data *adap)
 {
 	setsda(adap,1);
-	udelay(adap->udelay);
+	udelay((adap->udelay + 1) / 2);
 }
 
 static inline void scllo(struct i2c_algo_bit_data *adap)
 {
 	setscl(adap,0);
-	udelay(adap->udelay);
+	udelay(adap->udelay / 2);
 }
 
 /*
@@ -98,7 +109,11 @@
 		}
 		cond_resched();
 	}
-	DEBSTAT(printk(KERN_DEBUG "needed %ld jiffies\n", jiffies-start));
+#ifdef DEBUG
+	if (jiffies != start && i2c_debug >= 3)
+		pr_debug("i2c-algo-bit: needed %ld jiffies for SCL to go "
+			 "high\n", jiffies - start);
+#endif
 
 done:
 	udelay(adap->udelay);
@@ -110,30 +125,29 @@
 static void i2c_start(struct i2c_algo_bit_data *adap) 
 {
 	/* assert: scl, sda are high */
-	DEBPROTO(printk("S "));
-	sdalo(adap);
+	setsda(adap, 0);
+	udelay(adap->udelay);
 	scllo(adap);
 }
 
 static void i2c_repstart(struct i2c_algo_bit_data *adap) 
 {
-	/* scl, sda may not be high */
-	DEBPROTO(printk(" Sr "));
-	setsda(adap,1);
+	/* assert: scl is low */
+	sdahi(adap);
 	sclhi(adap);
-	
-	sdalo(adap);
+	setsda(adap, 0);
+	udelay(adap->udelay);
 	scllo(adap);
 }
 
 
 static void i2c_stop(struct i2c_algo_bit_data *adap) 
 {
-	DEBPROTO(printk("P\n"));
 	/* assert: scl is low */
 	sdalo(adap);
 	sclhi(adap); 
-	sdahi(adap);
+	setsda(adap, 1);
+	udelay(adap->udelay);
 }
 
 
@@ -145,7 +159,7 @@
  * 0 if the device did not ack
  * -ETIMEDOUT if an error occurred (while raising the scl line)
  */
-static int i2c_outb(struct i2c_adapter *i2c_adap, char c)
+static int i2c_outb(struct i2c_adapter *i2c_adap, unsigned char c)
 {
 	int i;
 	int sb;
@@ -154,34 +168,32 @@
 
 	/* assert: scl is low */
 	for ( i=7 ; i>=0 ; i-- ) {
-		sb = c & ( 1 << i );
+		sb = (c >> i) & 1;
 		setsda(adap,sb);
-		udelay(adap->udelay);
-		DEBPROTO(printk(KERN_DEBUG "%d",sb!=0));
+		udelay((adap->udelay + 1) / 2);
 		if (sclhi(adap)<0) { /* timed out */
-			sdahi(adap); /* we don't want to block the net */
-			DEB2(printk(KERN_DEBUG " i2c_outb: 0x%02x, timeout at bit #%d\n", c&0xff, i));
+			bit_dbg(1, &i2c_adap->dev, "i2c_outb: 0x%02x, "
+				"timeout at bit #%d\n", (int)c, i);
 			return -ETIMEDOUT;
 		};
 		/* do arbitration here: 
 		 * if ( sb && ! getsda(adap) ) -> ouch! Get out of here.
 		 */
-		setscl(adap, 0 );
-		udelay(adap->udelay);
+		scllo(adap);
 	}
 	sdahi(adap);
 	if (sclhi(adap)<0){ /* timeout */
-	    DEB2(printk(KERN_DEBUG " i2c_outb: 0x%02x, timeout at ack\n", c&0xff));
-	    return -ETIMEDOUT;
+		bit_dbg(1, &i2c_adap->dev, "i2c_outb: 0x%02x, "
+			"timeout at ack\n", (int)c);
+		return -ETIMEDOUT;
 	};
 	/* read ack: SDA should be pulled down by slave */
-	ack=getsda(adap);	/* ack: sda is pulled low ->success.	 */
-	DEB2(printk(KERN_DEBUG " i2c_outb: 0x%02x , getsda() = %d\n", c & 0xff, ack));
+	ack = !getsda(adap);    /* ack: sda is pulled low -> success */
+	bit_dbg(2, &i2c_adap->dev, "i2c_outb: 0x%02x %s\n", (int)c,
+		ack ? "A" : "NA");
 
-	DEBPROTO( printk(KERN_DEBUG "[%2.2x]",c&0xff) );
-	DEBPROTO(if (0==ack){ printk(KERN_DEBUG " A ");} else printk(KERN_DEBUG " NA ") );
 	scllo(adap);
-	return 0==ack;		/* return 1 if device acked	 */
+	return ack;
 	/* assert: scl is low (sda undef) */
 }
 
@@ -198,19 +210,18 @@
 	sdahi(adap);
 	for (i=0;i<8;i++) {
 		if (sclhi(adap)<0) { /* timeout */
-			DEB2(printk(KERN_DEBUG " i2c_inb: timeout at bit #%d\n", 7-i));
+			bit_dbg(1, &i2c_adap->dev, "i2c_inb: timeout at bit "
+				"#%d\n", 7 - i);
 			return -ETIMEDOUT;
 		};
 		indata *= 2;
 		if ( getsda(adap) ) 
 			indata |= 0x01;
-		scllo(adap);
+		setscl(adap, 0);
+		udelay(i == 7 ? adap->udelay / 2 : adap->udelay);
 	}
 	/* assert: scl is low */
-	DEB2(printk(KERN_DEBUG "i2c_inb: 0x%02x\n", indata & 0xff));
-
-	DEBPROTO(printk(KERN_DEBUG " 0x%02x", indata & 0xff));
-	return (int) (indata & 0xff);
+	return indata;
 }
 
 /*
@@ -221,73 +232,67 @@
 	int scl,sda;
 
 	if (adap->getscl==NULL)
-		printk(KERN_INFO "i2c-algo-bit.o: Testing SDA only, "
-			"SCL is not readable.\n");
+		pr_info("%s: Testing SDA only, SCL is not readable\n", name);
 
 	sda=getsda(adap);
 	scl=(adap->getscl==NULL?1:getscl(adap));
-	printk(KERN_DEBUG "i2c-algo-bit.o: (0) scl=%d, sda=%d\n",scl,sda);
 	if (!scl || !sda ) {
-		printk(KERN_WARNING "i2c-algo-bit.o: %s seems to be busy.\n", name);
+		printk(KERN_WARNING "%s: bus seems to be busy\n", name);
 		goto bailout;
 	}
 
 	sdalo(adap);
 	sda=getsda(adap);
 	scl=(adap->getscl==NULL?1:getscl(adap));
-	printk(KERN_DEBUG "i2c-algo-bit.o: (1) scl=%d, sda=%d\n",scl,sda);
 	if ( 0 != sda ) {
-		printk(KERN_WARNING "i2c-algo-bit.o: SDA stuck high!\n");
+		printk(KERN_WARNING "%s: SDA stuck high!\n", name);
 		goto bailout;
 	}
 	if ( 0 == scl ) {
-		printk(KERN_WARNING "i2c-algo-bit.o: SCL unexpected low "
-			"while pulling SDA low!\n");
+		printk(KERN_WARNING "%s: SCL unexpected low "
+		       "while pulling SDA low!\n", name);
 		goto bailout;
 	}		
 
 	sdahi(adap);
 	sda=getsda(adap);
 	scl=(adap->getscl==NULL?1:getscl(adap));
-	printk(KERN_DEBUG "i2c-algo-bit.o: (2) scl=%d, sda=%d\n",scl,sda);
 	if ( 0 == sda ) {
-		printk(KERN_WARNING "i2c-algo-bit.o: SDA stuck low!\n");
+		printk(KERN_WARNING "%s: SDA stuck low!\n", name);
 		goto bailout;
 	}
 	if ( 0 == scl ) {
-		printk(KERN_WARNING "i2c-algo-bit.o: SCL unexpected low "
-			"while pulling SDA high!\n");
+		printk(KERN_WARNING "%s: SCL unexpected low "
+		       "while pulling SDA high!\n", name);
 		goto bailout;
 	}
 
 	scllo(adap);
 	sda=getsda(adap);
 	scl=(adap->getscl==NULL?0:getscl(adap));
-	printk(KERN_DEBUG "i2c-algo-bit.o: (3) scl=%d, sda=%d\n",scl,sda);
 	if ( 0 != scl ) {
-		printk(KERN_WARNING "i2c-algo-bit.o: SCL stuck high!\n");
+		printk(KERN_WARNING "%s: SCL stuck high!\n", name);
 		goto bailout;
 	}
 	if ( 0 == sda ) {
-		printk(KERN_WARNING "i2c-algo-bit.o: SDA unexpected low "
-			"while pulling SCL low!\n");
+		printk(KERN_WARNING "%s: SDA unexpected low "
+		       "while pulling SCL low!\n", name);
 		goto bailout;
 	}
 	
 	sclhi(adap);
 	sda=getsda(adap);
 	scl=(adap->getscl==NULL?1:getscl(adap));
-	printk(KERN_DEBUG "i2c-algo-bit.o: (4) scl=%d, sda=%d\n",scl,sda);
 	if ( 0 == scl ) {
-		printk(KERN_WARNING "i2c-algo-bit.o: SCL stuck low!\n");
+		printk(KERN_WARNING "%s: SCL stuck low!\n", name);
 		goto bailout;
 	}
 	if ( 0 == sda ) {
-		printk(KERN_WARNING "i2c-algo-bit.o: SDA unexpected low "
-			"while pulling SCL high!\n");
+		printk(KERN_WARNING "%s: SDA unexpected low "
+		       "while pulling SCL high!\n", name);
 		goto bailout;
 	}
-	printk(KERN_INFO "i2c-algo-bit.o: %s passed test.\n",name);
+	pr_info("%s: Test OK\n", name);
 	return 0;
 bailout:
 	sdahi(adap);
@@ -312,44 +317,39 @@
 	int i,ret = -1;
 	for (i=0;i<=retries;i++) {
 		ret = i2c_outb(i2c_adap,addr);
-		if (ret==1)
-			break;	/* success! */
-		i2c_stop(adap);
-		udelay(5/*adap->udelay*/);
-		if (i==retries)  /* no success */
+		if (ret == 1 || i == retries)
 			break;
-		i2c_start(adap);
+		bit_dbg(3, &i2c_adap->dev, "emitting stop condition\n");
+		i2c_stop(adap);
 		udelay(adap->udelay);
+		yield();
+		bit_dbg(3, &i2c_adap->dev, "emitting start condition\n");
+		i2c_start(adap);
 	}
-	DEB2(if (i)
-	     printk(KERN_DEBUG "i2c-algo-bit.o: Used %d tries to %s client at 0x%02x : %s\n",
-		    i+1, addr & 1 ? "read" : "write", addr>>1,
-		    ret==1 ? "success" : ret==0 ? "no ack" : "failed, timeout?" )
-	    );
+	if (i && ret)
+		bit_dbg(1, &i2c_adap->dev, "Used %d tries to %s client at "
+			"0x%02x: %s\n", i + 1,
+			addr & 1 ? "read from" : "write to", addr >> 1,
+			ret == 1 ? "success" : "failed, timeout?");
 	return ret;
 }
 
 static int sendbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
 {
-	struct i2c_algo_bit_data *adap = i2c_adap->algo_data;
-	char c;
-	const char *temp = msg->buf;
+	const unsigned char *temp = msg->buf;
 	int count = msg->len;
 	unsigned short nak_ok = msg->flags & I2C_M_IGNORE_NAK; 
 	int retval;
 	int wrcount=0;
 
 	while (count > 0) {
-		c = *temp;
-		DEB2(dev_dbg(&i2c_adap->dev, "sendbytes: writing %2.2X\n", c&0xff));
-		retval = i2c_outb(i2c_adap,c);
+		retval = i2c_outb(i2c_adap, *temp);
 		if ((retval>0) || (nak_ok && (retval==0)))  { /* ok or ignored NAK */
 			count--; 
 			temp++;
 			wrcount++;
 		} else { /* arbitration or no acknowledge */
 			dev_err(&i2c_adap->dev, "sendbytes: error - bailout.\n");
-			i2c_stop(adap);
 			return (retval<0)? retval : -EFAULT;
 			        /* got a better one ?? */
 		}
@@ -362,7 +362,7 @@
 	int inval;
 	int rdcount=0;   	/* counts bytes read */
 	struct i2c_algo_bit_data *adap = i2c_adap->algo_data;
-	char *temp = msg->buf;
+	unsigned char *temp = msg->buf;
 	int count = msg->len;
 
 	while (count > 0) {
@@ -371,30 +371,44 @@
 			*temp = inval;
 			rdcount++;
 		} else {   /* read timed out */
-			printk(KERN_ERR "i2c-algo-bit.o: readbytes: i2c_inb timed out.\n");
 			break;
 		}
 
 		temp++;
 		count--;
 
-		if (msg->flags & I2C_M_NO_RD_ACK)
+		if (msg->flags & I2C_M_NO_RD_ACK) {
+			bit_dbg(2, &i2c_adap->dev, "i2c_inb: 0x%02x\n",
+				inval);
 			continue;
-
-		if ( count > 0 ) {		/* send ack */
-			sdalo(adap);
-			DEBPROTO(printk(" Am "));
-		} else {
-			sdahi(adap);	/* neg. ack on last byte */
-			DEBPROTO(printk(" NAm "));
 		}
+
+		/* assert: sda is high */
+		if (count)		/* send ack */
+			setsda(adap, 0);
+		udelay((adap->udelay + 1) / 2);
+		bit_dbg(2, &i2c_adap->dev, "i2c_inb: 0x%02x %s\n", inval,
+			count ? "A" : "NA");
 		if (sclhi(adap)<0) {	/* timeout */
-			sdahi(adap);
-			printk(KERN_ERR "i2c-algo-bit.o: readbytes: Timeout at ack\n");
+			dev_err(&i2c_adap->dev, "readbytes: timeout at ack\n");
 			return -ETIMEDOUT;
 		};
 		scllo(adap);
-		sdahi(adap);
+
+		/* Some SMBus transactions require that we receive the
+		   transaction length as the first read byte. */
+		if (rdcount == 1 && (msg->flags & I2C_M_RECV_LEN)) {
+			if (inval <= 0 || inval > I2C_SMBUS_BLOCK_MAX) {
+				dev_err(&i2c_adap->dev, "readbytes: invalid "
+					"block length (%d)\n", inval);
+				return -EREMOTEIO;
+			}
+			/* The original count value accounts for the extra
+			   bytes, that is, either 1 for a regular transaction,
+			   or 2 for a PEC transaction. */
+			count += inval;
+			msg->len += inval;
+		}
 	}
 	return rdcount;
 }
@@ -421,27 +435,31 @@
 	if ( (flags & I2C_M_TEN)  ) { 
 		/* a ten bit address */
 		addr = 0xf0 | (( msg->addr >> 7) & 0x03);
-		DEB2(printk(KERN_DEBUG "addr0: %d\n",addr));
+		bit_dbg(2, &i2c_adap->dev, "addr0: %d\n", addr);
 		/* try extended address code...*/
 		ret = try_address(i2c_adap, addr, retries);
 		if ((ret != 1) && !nak_ok)  {
-			printk(KERN_ERR "died at extended address code.\n");
+			dev_err(&i2c_adap->dev,
+				"died at extended address code\n");
 			return -EREMOTEIO;
 		}
 		/* the remaining 8 bit address */
 		ret = i2c_outb(i2c_adap,msg->addr & 0x7f);
 		if ((ret != 1) && !nak_ok) {
 			/* the chip did not ack / xmission error occurred */
-			printk(KERN_ERR "died at 2nd address code.\n");
+			dev_err(&i2c_adap->dev, "died at 2nd address code\n");
 			return -EREMOTEIO;
 		}
 		if ( flags & I2C_M_RD ) {
+			bit_dbg(3, &i2c_adap->dev, "emitting repeated "
+				"start condition\n");
 			i2c_repstart(adap);
 			/* okay, now switch into reading mode */
 			addr |= 0x01;
 			ret = try_address(i2c_adap, addr, retries);
 			if ((ret!=1) && !nak_ok) {
-				printk(KERN_ERR "died at extended address code.\n");
+				dev_err(&i2c_adap->dev,
+					"died at repeated address code\n");
 				return -EREMOTEIO;
 			}
 		}
@@ -468,44 +486,62 @@
 	int i,ret;
 	unsigned short nak_ok;
 
+	bit_dbg(3, &i2c_adap->dev, "emitting start condition\n");
 	i2c_start(adap);
 	for (i=0;i<num;i++) {
 		pmsg = &msgs[i];
 		nak_ok = pmsg->flags & I2C_M_IGNORE_NAK; 
 		if (!(pmsg->flags & I2C_M_NOSTART)) {
 			if (i) {
+				bit_dbg(3, &i2c_adap->dev, "emitting "
+					"repeated start condition\n");
 				i2c_repstart(adap);
 			}
 			ret = bit_doAddress(i2c_adap, pmsg);
 			if ((ret != 0) && !nak_ok) {
-			    DEB2(printk(KERN_DEBUG "i2c-algo-bit.o: NAK from device addr %2.2x msg #%d\n"
-					,msgs[i].addr,i));
-			    return (ret<0) ? ret : -EREMOTEIO;
+				bit_dbg(1, &i2c_adap->dev, "NAK from "
+					"device addr 0x%02x msg #%d\n",
+					msgs[i].addr, i);
+				goto bailout;
 			}
 		}
 		if (pmsg->flags & I2C_M_RD ) {
 			/* read bytes into buffer*/
 			ret = readbytes(i2c_adap, pmsg);
-			DEB2(printk(KERN_DEBUG "i2c-algo-bit.o: read %d bytes.\n",ret));
-			if (ret < pmsg->len ) {
-				return (ret<0)? ret : -EREMOTEIO;
+			if (ret >= 1)
+				bit_dbg(2, &i2c_adap->dev, "read %d byte%s\n",
+					ret, ret == 1 ? "" : "s");
+			if (ret < pmsg->len) {
+				if (ret >= 0)
+					ret = -EREMOTEIO;
+				goto bailout;
 			}
 		} else {
 			/* write bytes from buffer */
 			ret = sendbytes(i2c_adap, pmsg);
-			DEB2(printk(KERN_DEBUG "i2c-algo-bit.o: wrote %d bytes.\n",ret));
-			if (ret < pmsg->len ) {
-				return (ret<0) ? ret : -EREMOTEIO;
+			if (ret >= 1)
+				bit_dbg(2, &i2c_adap->dev, "wrote %d byte%s\n",
+					ret, ret == 1 ? "" : "s");
+			if (ret < pmsg->len) {
+				if (ret >= 0)
+					ret = -EREMOTEIO;
+				goto bailout;
 			}
 		}
 	}
+	ret = i;
+
+bailout:
+	bit_dbg(3, &i2c_adap->dev, "emitting stop condition\n");
 	i2c_stop(adap);
-	return num;
+	return ret;
 }
 
 static u32 bit_func(struct i2c_adapter *adap)
 {
 	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | 
+	       I2C_FUNC_SMBUS_READ_BLOCK_DATA |
+	       I2C_FUNC_SMBUS_BLOCK_PROC_CALL |
 	       I2C_FUNC_10BIT_ADDR | I2C_FUNC_PROTOCOL_MANGLING;
 }
 
@@ -520,7 +556,7 @@
 /* 
  * registering functions to load algorithms at runtime 
  */
-int i2c_bit_add_bus(struct i2c_adapter *adap)
+static int i2c_bit_prepare_bus(struct i2c_adapter *adap)
 {
 	struct i2c_algo_bit_data *bit_adap = adap->algo_data;
 
@@ -530,25 +566,39 @@
 			return -ENODEV;
 	}
 
-	DEB2(dev_dbg(&adap->dev, "hw routines registered.\n"));
-
 	/* register new adapter to i2c module... */
 	adap->algo = &i2c_bit_algo;
 
 	adap->timeout = 100;	/* default values, should	*/
 	adap->retries = 3;	/* be replaced by defines	*/
 
+	return 0;
+}
+
+int i2c_bit_add_bus(struct i2c_adapter *adap)
+{
+	int err;
+
+	err = i2c_bit_prepare_bus(adap);
+	if (err)
+		return err;
+
 	return i2c_add_adapter(adap);
 }
 EXPORT_SYMBOL(i2c_bit_add_bus);
 
+int i2c_bit_add_numbered_bus(struct i2c_adapter *adap)
+{
+	int err;
+
+	err = i2c_bit_prepare_bus(adap);
+	if (err)
+		return err;
+
+	return i2c_add_numbered_adapter(adap);
+}
+EXPORT_SYMBOL(i2c_bit_add_numbered_bus);
+
 MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>");
 MODULE_DESCRIPTION("I2C-Bus bit-banging algorithm");
 MODULE_LICENSE("GPL");
-
-module_param(bit_test, bool, 0);
-module_param(i2c_debug, int, S_IRUGO | S_IWUSR);
-
-MODULE_PARM_DESC(bit_test, "Test the lines of the bus to see if it is stuck");
-MODULE_PARM_DESC(i2c_debug,
-		 "debug level - 0 off; 1 normal; 2,3 more verbose; 9 bit-protocol");
diff --git a/drivers/i2c/algos/i2c-algo-sgi.c b/drivers/i2c/algos/i2c-algo-sgi.c
index ac2d505..6eaf145 100644
--- a/drivers/i2c/algos/i2c-algo-sgi.c
+++ b/drivers/i2c/algos/i2c-algo-sgi.c
@@ -1,6 +1,7 @@
 /*
- * i2c-algo-sgi.c: i2c driver algorithms for SGI adapters.
- * 
+ * i2c-algo-sgi.c: i2c driver algorithm used by the VINO (SGI Indy) and
+ * MACE (SGI O2) chips.
+ *
  * This file is subject to the terms and conditions of the GNU General Public
  * License version 2 as published by the Free Software Foundation.
  *
@@ -162,8 +163,8 @@
 	.functionality	= sgi_func,
 };
 
-/* 
- * registering functions to load algorithms at runtime 
+/*
+ * registering functions to load algorithms at runtime
  */
 int i2c_sgi_add_bus(struct i2c_adapter *adap)
 {
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index ece31d2..838dc1c 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -3,11 +3,10 @@
 #
 
 menu "I2C Hardware Bus support"
-	depends on I2C
 
 config I2C_ALI1535
 	tristate "ALI 1535"
-	depends on I2C && PCI
+	depends on 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
@@ -19,7 +18,7 @@
 
 config I2C_ALI1563
 	tristate "ALI 1563"
-	depends on I2C && PCI && EXPERIMENTAL
+	depends on PCI && EXPERIMENTAL
 	help
 	  If you say yes to this option, support will be included for the SMB
 	  Host controller on Acer Labs Inc. (ALI) M1563 South Bridges.  The SMB
@@ -31,7 +30,7 @@
 
 config I2C_ALI15X3
 	tristate "ALI 15x3"
-	depends on I2C && PCI
+	depends on 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 +40,7 @@
 
 config I2C_AMD756
 	tristate "AMD 756/766/768/8111 and nVidia nForce"
-	depends on I2C && PCI
+	depends on 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 +65,7 @@
 
 config I2C_AMD8111
 	tristate "AMD 8111"
-	depends on I2C && PCI
+	depends on PCI
 	help
 	  If you say yes to this option, support will be included for the
 	  second (SMBus 2.0) AMD 8111 mainboard I2C interface.
@@ -76,14 +75,14 @@
 
 config I2C_AT91
 	tristate "Atmel AT91 I2C Two-Wire interface (TWI)"
-	depends on I2C && ARCH_AT91 && EXPERIMENTAL
+	depends on ARCH_AT91 && EXPERIMENTAL
 	help
 	  This supports the use of the I2C interface on Atmel AT91
 	  processors.
 
 config I2C_AU1550
 	tristate "Au1550/Au1200 SMBus interface"
-	depends on I2C && (SOC_AU1550 || SOC_AU1200)
+	depends on SOC_AU1550 || SOC_AU1200
 	help
 	  If you say yes to this option, support will be included for the
 	  Au1550 and Au1200 SMBus interface.
@@ -91,9 +90,25 @@
 	  This driver can also be built as a module.  If so, the module
 	  will be called i2c-au1550.
 
+config I2C_BLACKFIN_TWI
+	tristate "Blackfin TWI I2C support"
+	depends on BF534 || BF536 || BF537
+	help
+	  This is the TWI I2C device driver for Blackfin 534/536/537.
+	  This driver can also be built as a module.  If so, the module
+	  will be called i2c-bfin-twi.
+
+config I2C_BLACKFIN_TWI_CLK_KHZ
+	int "Blackfin TWI I2C clock (kHz)"
+	depends on I2C_BLACKFIN_TWI
+	range 10 400
+	default 50
+	help
+	  The unit of the TWI clock is kHz.
+
 config I2C_ELEKTOR
 	tristate "Elektor ISA card"
-	depends on I2C && ISA && BROKEN_ON_SMP
+	depends on ISA && BROKEN_ON_SMP
 	select I2C_ALGOPCF
 	help
 	  This supports the PCF8584 ISA bus I2C adapter.  Say Y if you own
@@ -102,9 +117,17 @@
 	  This support is also available as a module.  If so, the module 
 	  will be called i2c-elektor.
 
+config I2C_GPIO
+	tristate "GPIO-based bitbanging I2C"
+	depends on GENERIC_GPIO
+	select I2C_ALGOBIT
+	help
+	  This is a very simple bitbanging I2C driver utilizing the
+	  arch-neutral GPIO API to control the SCL and SDA lines.
+
 config I2C_HYDRA
 	tristate "CHRP Apple Hydra Mac I/O I2C interface"
-	depends on I2C && PCI && PPC_CHRP && EXPERIMENTAL
+	depends on PCI && PPC_CHRP && EXPERIMENTAL
 	select I2C_ALGOBIT
 	help
 	  This supports the use of the I2C interface in the Apple Hydra Mac
@@ -116,7 +139,7 @@
 
 config I2C_I801
 	tristate "Intel 82801 (ICH)"
-	depends on I2C && PCI
+	depends on 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
@@ -139,7 +162,7 @@
 
 config I2C_I810
 	tristate "Intel 810/815"
-	depends on I2C && PCI
+	depends on PCI
 	select I2C_ALGOBIT
 	help
 	  If you say yes to this option, support will be included for the Intel
@@ -156,7 +179,7 @@
 
 config I2C_PXA
 	tristate "Intel PXA2XX I2C adapter (EXPERIMENTAL)"
-	depends on I2C && EXPERIMENTAL && ARCH_PXA
+	depends on EXPERIMENTAL && ARCH_PXA
 	help
 	  If you have devices in the PXA I2C bus, say yes to this option.
 	  This driver can also be built as a module.  If so, the module
@@ -172,7 +195,7 @@
 
 config I2C_PIIX4
 	tristate "Intel PIIX4 and compatible (ATI/Serverworks/Broadcom/SMSC)"
-	depends on I2C && PCI
+	depends on PCI
 	help
 	  If you say yes to this option, support will be included for the Intel
 	  PIIX4 family of mainboard I2C interfaces.  Specifically, the following
@@ -195,7 +218,7 @@
 
 config I2C_IBM_IIC
 	tristate "IBM PPC 4xx on-chip I2C interface"
-	depends on IBM_OCP && I2C
+	depends on IBM_OCP
 	help
 	  Say Y here if you want to use IIC peripheral found on 
 	  embedded IBM PPC 4xx based systems. 
@@ -205,7 +228,7 @@
 
 config I2C_IOP3XX
 	tristate "Intel IOPx3xx and IXP4xx on-chip I2C interface"
-	depends on (ARCH_IOP32X || ARCH_IOP33X || ARCH_IXP4XX || ARCH_IOP13XX) && I2C
+	depends on ARCH_IOP32X || ARCH_IOP33X || ARCH_IXP4XX || ARCH_IOP13XX
 	help
 	  Say Y here if you want to use the IIC bus controller on
 	  the Intel IOPx3xx I/O Processors or IXP4xx Network Processors.
@@ -215,11 +238,10 @@
 
 config I2C_ISA
 	tristate
-	depends on I2C
 
 config I2C_IXP4XX
-	tristate "IXP4xx GPIO-Based I2C Interface"
-	depends on I2C && ARCH_IXP4XX
+	tristate "IXP4xx GPIO-Based I2C Interface (DEPRECATED)"
+	depends on ARCH_IXP4XX
 	select I2C_ALGOBIT
 	help
 	  Say Y here if you have an Intel IXP4xx(420,421,422,425) based 
@@ -228,9 +250,12 @@
 	  This support is also available as a module. If so, the module
 	  will be called i2c-ixp4xx.
 
+	  This driver is deprecated and will be dropped soon. Use i2c-gpio
+	  instead.
+
 config I2C_IXP2000
-	tristate "IXP2000 GPIO-Based I2C Interface"
-	depends on I2C && ARCH_IXP2000
+	tristate "IXP2000 GPIO-Based I2C Interface (DEPRECATED)"
+	depends on ARCH_IXP2000
 	select I2C_ALGOBIT
 	help
 	  Say Y here if you have an Intel IXP2000(2400, 2800, 2850) based 
@@ -239,9 +264,12 @@
 	  This support is also available as a module. If so, the module
 	  will be called i2c-ixp2000.
 
+	  This driver is deprecated and will be dropped soon. Use i2c-gpio
+	  instead.
+
 config I2C_POWERMAC
 	tristate "Powermac I2C interface"
-	depends on I2C && PPC_PMAC
+	depends on PPC_PMAC
 	default y
 	help
 	  This exposes the various PowerMac i2c interfaces to the linux i2c
@@ -253,7 +281,7 @@
 
 config I2C_MPC
 	tristate "MPC107/824x/85xx/52xx/86xx"
-	depends on I2C && PPC32
+	depends on PPC32
 	help
 	  If you say yes to this option, support will be included for the
 	  built-in I2C interface on the MPC107/Tsi107/MPC8240/MPC8245 and
@@ -265,7 +293,7 @@
 
 config I2C_NFORCE2
 	tristate "Nvidia nForce2, nForce3 and nForce4"
-	depends on I2C && PCI
+	depends on PCI
 	help
 	  If you say yes to this option, support will be included for the Nvidia
 	  nForce2, nForce3 and nForce4 families of mainboard I2C interfaces.
@@ -275,7 +303,7 @@
 
 config I2C_OCORES
 	tristate "OpenCores I2C Controller"
-	depends on I2C && EXPERIMENTAL
+	depends on EXPERIMENTAL
 	help
 	  If you say yes to this option, support will be included for the
 	  OpenCores I2C controller. For details see
@@ -286,7 +314,7 @@
 
 config I2C_OMAP
 	tristate "OMAP I2C adapter"
-	depends on I2C && ARCH_OMAP
+	depends on ARCH_OMAP
 	default y if MACH_OMAP_H3 || MACH_OMAP_OSK
 	help
 	  If you say yes to this option, support will be included for the
@@ -296,7 +324,7 @@
 
 config I2C_PARPORT
 	tristate "Parallel port adapter"
-	depends on I2C && PARPORT
+	depends on PARPORT
 	select I2C_ALGOBIT
 	help
 	  This supports parallel port I2C adapters such as the ones made by
@@ -320,7 +348,6 @@
 
 config I2C_PARPORT_LIGHT
 	tristate "Parallel port adapter (light)"
-	depends on I2C
 	select I2C_ALGOBIT
 	help
 	  This supports parallel port I2C adapters such as the ones made by
@@ -344,13 +371,13 @@
 
 config I2C_PASEMI
 	tristate "PA Semi SMBus interface"
-	depends on PPC_PASEMI && I2C && PCI
+	depends on PPC_PASEMI && PCI
 	help
 	  Supports the PA Semi PWRficient on-chip SMBus interfaces.
 
 config I2C_PROSAVAGE
 	tristate "S3/VIA (Pro)Savage"
-	depends on I2C && PCI
+	depends on PCI
 	select I2C_ALGOBIT
 	help
 	  If you say yes to this option, support will be included for the
@@ -365,19 +392,19 @@
 
 config I2C_RPXLITE
 	tristate "Embedded Planet RPX Lite/Classic support"
-	depends on (RPXLITE || RPXCLASSIC) && I2C
+	depends on RPXLITE || RPXCLASSIC
 	select I2C_ALGO8XX
 
 config I2C_S3C2410
 	tristate "S3C2410 I2C Driver"
-	depends on I2C && ARCH_S3C2410
+	depends on ARCH_S3C2410
 	help
 	  Say Y here to include support for I2C controller in the
 	  Samsung S3C2410 based System-on-Chip devices.
 
 config I2C_SAVAGE4
 	tristate "S3 Savage 4"
-	depends on I2C && PCI && EXPERIMENTAL
+	depends on PCI && EXPERIMENTAL
 	select I2C_ALGOBIT
 	help
 	  If you say yes to this option, support will be included for the 
@@ -388,13 +415,25 @@
 
 config I2C_SIBYTE
 	tristate "SiByte SMBus interface"
-	depends on SIBYTE_SB1xxx_SOC && I2C
+	depends on SIBYTE_SB1xxx_SOC
 	help
 	  Supports the SiByte SOC on-chip I2C interfaces (2 channels).
 
+config I2C_SIMTEC
+	tristate "Simtec Generic I2C interface"
+	select I2C_ALGOBIT
+	help
+	  If you say yes to this option, support will be inclyded for
+	  the Simtec Generic I2C interface. This driver is for the
+	  simple I2C bus used on newer Simtec products for general
+	  I2C, such as DDC on the Simtec BBD2016A.
+
+	  This driver can also be build as a module. If so, the module
+	  will be called i2c-simtec.
+
 config SCx200_I2C
-	tristate "NatSemi SCx200 I2C using GPIO pins"
-	depends on SCx200_GPIO && I2C
+	tristate "NatSemi SCx200 I2C using GPIO pins (DEPRECATED)"
+	depends on SCx200_GPIO
 	select I2C_ALGOBIT
 	help
 	  Enable the use of two GPIO pins of a SCx200 processor as an I2C bus.
@@ -404,6 +443,9 @@
 	  This support is also available as a module.  If so, the module 
 	  will be called scx200_i2c.
 
+	  This driver is deprecated and will be dropped soon. Use i2c-gpio
+	  (or scx200_acb) instead.
+
 config SCx200_I2C_SCL
 	int "GPIO pin used for SCL"
 	depends on SCx200_I2C
@@ -422,7 +464,7 @@
 
 config SCx200_ACB
 	tristate "Geode ACCESS.bus support"
-	depends on X86_32 && I2C && PCI
+	depends on X86_32 && PCI
 	help
 	  Enable the use of the ACCESS.bus controllers on the Geode SCx200 and
 	  SC1100 processors and the CS5535 and CS5536 Geode companion devices.
@@ -434,7 +476,7 @@
 
 config I2C_SIS5595
 	tristate "SiS 5595"
-	depends on I2C && PCI
+	depends on PCI
 	help
 	  If you say yes to this option, support will be included for the 
 	  SiS5595 SMBus (a subset of I2C) interface.
@@ -444,7 +486,7 @@
 
 config I2C_SIS630
 	tristate "SiS 630/730"
-	depends on I2C && PCI
+	depends on PCI
 	help
 	  If you say yes to this option, support will be included for the 
 	  SiS630 and SiS730 SMBus (a subset of I2C) interface.
@@ -454,7 +496,7 @@
 
 config I2C_SIS96X
 	tristate "SiS 96x"
-	depends on I2C && PCI
+	depends on 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
@@ -472,7 +514,7 @@
 
 config I2C_STUB
 	tristate "I2C/SMBus Test Stub"
-	depends on I2C && EXPERIMENTAL && 'm'
+	depends on EXPERIMENTAL && m
 	default 'n'
 	help
 	  This module may be useful to developers of SMBus client drivers,
@@ -483,9 +525,20 @@
 
 	  If you don't know what to do here, definitely say N.
 
+config I2C_TINY_USB
+	tristate "I2C-Tiny-USB"
+	depends on USB
+	help
+	  If you say yes to this option, support will be included for the
+	  i2c-tiny-usb, a simple do-it-yourself USB to I2C interface. See
+	  http://www.harbaum.org/till/i2c_tiny_usb for hardware details.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called i2c-tiny-usb.
+
 config I2C_VERSATILE
 	tristate "ARM Versatile/Realview I2C bus support"
-	depends on I2C && (ARCH_VERSATILE || ARCH_REALVIEW)
+	depends on ARCH_VERSATILE || ARCH_REALVIEW
 	select I2C_ALGOBIT
 	help
 	  Say yes if you want to support the I2C serial bus on ARMs Versatile
@@ -496,7 +549,7 @@
 
 config I2C_ACORN
 	bool "Acorn IOC/IOMD I2C bus support"
-	depends on I2C && ARCH_ACORN
+	depends on ARCH_ACORN
 	default y
 	select I2C_ALGOBIT
 	help
@@ -506,7 +559,7 @@
 
 config I2C_VIA
 	tristate "VIA 82C586B"
-	depends on I2C && PCI && EXPERIMENTAL
+	depends on PCI && EXPERIMENTAL
 	select I2C_ALGOBIT
 	help
 	  If you say yes to this option, support will be included for the VIA
@@ -517,7 +570,7 @@
 
 config I2C_VIAPRO
 	tristate "VIA VT82C596/82C686/82xx and CX700"
-	depends on I2C && PCI
+	depends on PCI
 	help
 	  If you say yes to this option, support will be included for the VIA
 	  VT82C596 and later SMBus interface.  Specifically, the following
@@ -536,7 +589,7 @@
 
 config I2C_VOODOO3
 	tristate "Voodoo 3"
-	depends on I2C && PCI
+	depends on PCI
 	select I2C_ALGOBIT
 	help
 	  If you say yes to this option, support will be included for the
@@ -547,7 +600,7 @@
 
 config I2C_PCA_ISA
 	tristate "PCA9564 on an ISA bus"
-	depends on I2C
+	depends on ISA
 	select I2C_ALGOPCA
 	default n
 	help
@@ -564,7 +617,7 @@
 
 config I2C_MV64XXX
 	tristate "Marvell mv64xxx I2C Controller"
-	depends on I2C && MV64X60 && EXPERIMENTAL
+	depends on MV64X60 && EXPERIMENTAL
 	help
 	  If you say yes to this option, support will be included for the
 	  built-in I2C interface on the Marvell 64xxx line of host bridges.
@@ -574,7 +627,7 @@
 
 config I2C_PNX
 	tristate "I2C bus support for Philips PNX targets"
-	depends on ARCH_PNX4008 && I2C
+	depends on ARCH_PNX4008
 	help
 	  This driver supports the Philips IP3204 I2C IP block master and/or
 	  slave controller
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index 290b540..14d1432 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -10,7 +10,9 @@
 obj-$(CONFIG_I2C_AMD8111)	+= i2c-amd8111.o
 obj-$(CONFIG_I2C_AT91)		+= i2c-at91.o
 obj-$(CONFIG_I2C_AU1550)	+= i2c-au1550.o
+obj-$(CONFIG_I2C_BLACKFIN_TWI)	+= i2c-bfin-twi.o
 obj-$(CONFIG_I2C_ELEKTOR)	+= i2c-elektor.o
+obj-$(CONFIG_I2C_GPIO)		+= i2c-gpio.o
 obj-$(CONFIG_I2C_HYDRA)		+= i2c-hydra.o
 obj-$(CONFIG_I2C_I801)		+= i2c-i801.o
 obj-$(CONFIG_I2C_I810)		+= i2c-i810.o
@@ -37,10 +39,12 @@
 obj-$(CONFIG_I2C_S3C2410)	+= i2c-s3c2410.o
 obj-$(CONFIG_I2C_SAVAGE4)	+= i2c-savage4.o
 obj-$(CONFIG_I2C_SIBYTE)	+= i2c-sibyte.o
+obj-$(CONFIG_I2C_SIMTEC)	+= i2c-simtec.o
 obj-$(CONFIG_I2C_SIS5595)	+= i2c-sis5595.o
 obj-$(CONFIG_I2C_SIS630)	+= i2c-sis630.o
 obj-$(CONFIG_I2C_SIS96X)	+= i2c-sis96x.o
 obj-$(CONFIG_I2C_STUB)		+= i2c-stub.o
+obj-$(CONFIG_I2C_TINY_USB)	+= i2c-tiny-usb.o
 obj-$(CONFIG_I2C_VERSATILE)	+= i2c-versatile.o
 obj-$(CONFIG_I2C_ACORN)		+= i2c-acorn.o
 obj-$(CONFIG_I2C_VIA)		+= i2c-via.o
diff --git a/drivers/i2c/busses/i2c-ali1535.c b/drivers/i2c/busses/i2c-ali1535.c
index 1e277ba..f14372a 100644
--- a/drivers/i2c/busses/i2c-ali1535.c
+++ b/drivers/i2c/busses/i2c-ali1535.c
@@ -497,7 +497,7 @@
 	/* set up the sysfs linkage to our parent device */
 	ali1535_adapter.dev.parent = &dev->dev;
 
-	snprintf(ali1535_adapter.name, I2C_NAME_SIZE, 
+	snprintf(ali1535_adapter.name, sizeof(ali1535_adapter.name),
 		"SMBus ALI1535 adapter at %04x", ali1535_smba);
 	return i2c_add_adapter(&ali1535_adapter);
 }
diff --git a/drivers/i2c/busses/i2c-ali15x3.c b/drivers/i2c/busses/i2c-ali15x3.c
index e47fe01..93bf87d 100644
--- a/drivers/i2c/busses/i2c-ali15x3.c
+++ b/drivers/i2c/busses/i2c-ali15x3.c
@@ -492,7 +492,7 @@
 	/* set up the sysfs linkage to our parent device */
 	ali15x3_adapter.dev.parent = &dev->dev;
 
-	snprintf(ali15x3_adapter.name, I2C_NAME_SIZE,
+	snprintf(ali15x3_adapter.name, sizeof(ali15x3_adapter.name),
 		"SMBus ALI15X3 adapter at %04x", ali15x3_smba);
 	return i2c_add_adapter(&ali15x3_adapter);
 }
diff --git a/drivers/i2c/busses/i2c-amd8111.c b/drivers/i2c/busses/i2c-amd8111.c
index 0c70f82..c9fca7b 100644
--- a/drivers/i2c/busses/i2c-amd8111.c
+++ b/drivers/i2c/busses/i2c-amd8111.c
@@ -365,7 +365,7 @@
 	}
 
 	smbus->adapter.owner = THIS_MODULE;
-	snprintf(smbus->adapter.name, I2C_NAME_SIZE,
+	snprintf(smbus->adapter.name, sizeof(smbus->adapter.name),
 		"SMBus2 AMD8111 adapter at %04x", smbus->base);
 	smbus->adapter.id = I2C_HW_SMBUS_AMD8111;
 	smbus->adapter.class = I2C_CLASS_HWMON;
diff --git a/drivers/i2c/busses/i2c-at91.c b/drivers/i2c/busses/i2c-at91.c
index 67f91bd..f35156c 100644
--- a/drivers/i2c/busses/i2c-at91.c
+++ b/drivers/i2c/busses/i2c-at91.c
@@ -17,7 +17,6 @@
 #include <linux/version.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
-#include <linux/pci.h>
 #include <linux/types.h>
 #include <linux/delay.h>
 #include <linux/i2c.h>
diff --git a/drivers/i2c/busses/i2c-bfin-twi.c b/drivers/i2c/busses/i2c-bfin-twi.c
new file mode 100644
index 0000000..6311039
--- /dev/null
+++ b/drivers/i2c/busses/i2c-bfin-twi.c
@@ -0,0 +1,644 @@
+/*
+ * drivers/i2c/busses/i2c-bfin-twi.c
+ *
+ * Description: Driver for Blackfin Two Wire Interface
+ *
+ * Author:      sonicz  <sonic.zhang@analog.com>
+ *
+ * Copyright (c) 2005-2007 Analog Devices, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <linux/mm.h>
+#include <linux/timer.h>
+#include <linux/spinlock.h>
+#include <linux/completion.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+
+#include <asm/blackfin.h>
+#include <asm/irq.h>
+
+#define POLL_TIMEOUT       (2 * HZ)
+
+/* SMBus mode*/
+#define TWI_I2C_MODE_STANDARD		0x01
+#define TWI_I2C_MODE_STANDARDSUB	0x02
+#define TWI_I2C_MODE_COMBINED		0x04
+
+struct bfin_twi_iface {
+	struct mutex		twi_lock;
+	int			irq;
+	spinlock_t		lock;
+	char			read_write;
+	u8			command;
+	u8			*transPtr;
+	int			readNum;
+	int			writeNum;
+	int			cur_mode;
+	int			manual_stop;
+	int			result;
+	int			timeout_count;
+	struct timer_list	timeout_timer;
+	struct i2c_adapter	adap;
+	struct completion	complete;
+};
+
+static struct bfin_twi_iface twi_iface;
+
+static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface)
+{
+	unsigned short twi_int_status = bfin_read_TWI_INT_STAT();
+	unsigned short mast_stat = bfin_read_TWI_MASTER_STAT();
+
+	if (twi_int_status & XMTSERV) {
+		/* Transmit next data */
+		if (iface->writeNum > 0) {
+			bfin_write_TWI_XMT_DATA8(*(iface->transPtr++));
+			iface->writeNum--;
+		}
+		/* start receive immediately after complete sending in
+		 * combine mode.
+		 */
+		else if (iface->cur_mode == TWI_I2C_MODE_COMBINED) {
+			bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL()
+				| MDIR | RSTART);
+		} else if (iface->manual_stop)
+			bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL()
+				| STOP);
+		SSYNC();
+		/* Clear status */
+		bfin_write_TWI_INT_STAT(XMTSERV);
+		SSYNC();
+	}
+	if (twi_int_status & RCVSERV) {
+		if (iface->readNum > 0) {
+			/* Receive next data */
+			*(iface->transPtr) = bfin_read_TWI_RCV_DATA8();
+			if (iface->cur_mode == TWI_I2C_MODE_COMBINED) {
+				/* Change combine mode into sub mode after
+				 * read first data.
+				 */
+				iface->cur_mode = TWI_I2C_MODE_STANDARDSUB;
+				/* Get read number from first byte in block
+				 * combine mode.
+				 */
+				if (iface->readNum == 1 && iface->manual_stop)
+					iface->readNum = *iface->transPtr + 1;
+			}
+			iface->transPtr++;
+			iface->readNum--;
+		} else if (iface->manual_stop) {
+			bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL()
+				| STOP);
+			SSYNC();
+		}
+		/* Clear interrupt source */
+		bfin_write_TWI_INT_STAT(RCVSERV);
+		SSYNC();
+	}
+	if (twi_int_status & MERR) {
+		bfin_write_TWI_INT_STAT(MERR);
+		bfin_write_TWI_INT_MASK(0);
+		bfin_write_TWI_MASTER_STAT(0x3e);
+		bfin_write_TWI_MASTER_CTL(0);
+		SSYNC();
+		iface->result = -1;
+		/* if both err and complete int stats are set, return proper
+		 * results.
+		 */
+		if (twi_int_status & MCOMP) {
+			bfin_write_TWI_INT_STAT(MCOMP);
+			bfin_write_TWI_INT_MASK(0);
+			bfin_write_TWI_MASTER_CTL(0);
+			SSYNC();
+			/* If it is a quick transfer, only address bug no data,
+			 * not an err, return 1.
+			 */
+			if (iface->writeNum == 0 && (mast_stat & BUFRDERR))
+				iface->result = 1;
+			/* If address not acknowledged return -1,
+			 * else return 0.
+			 */
+			else if (!(mast_stat & ANAK))
+				iface->result = 0;
+		}
+		complete(&iface->complete);
+		return;
+	}
+	if (twi_int_status & MCOMP) {
+		bfin_write_TWI_INT_STAT(MCOMP);
+		SSYNC();
+		if (iface->cur_mode == TWI_I2C_MODE_COMBINED) {
+			if (iface->readNum == 0) {
+				/* set the read number to 1 and ask for manual
+				 * stop in block combine mode
+				 */
+				iface->readNum = 1;
+				iface->manual_stop = 1;
+				bfin_write_TWI_MASTER_CTL(
+					bfin_read_TWI_MASTER_CTL()
+					| (0xff << 6));
+			} else {
+				/* set the readd number in other
+				 * combine mode.
+				 */
+				bfin_write_TWI_MASTER_CTL(
+					(bfin_read_TWI_MASTER_CTL() &
+					(~(0xff << 6))) |
+					( iface->readNum << 6));
+			}
+			/* remove restart bit and enable master receive */
+			bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL() &
+				~RSTART);
+			bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL() |
+				MEN | MDIR);
+			SSYNC();
+		} else {
+			iface->result = 1;
+			bfin_write_TWI_INT_MASK(0);
+			bfin_write_TWI_MASTER_CTL(0);
+			SSYNC();
+			complete(&iface->complete);
+		}
+	}
+}
+
+/* Interrupt handler */
+static irqreturn_t bfin_twi_interrupt_entry(int irq, void *dev_id)
+{
+	struct bfin_twi_iface *iface = dev_id;
+	unsigned long flags;
+
+	spin_lock_irqsave(&iface->lock, flags);
+	del_timer(&iface->timeout_timer);
+	bfin_twi_handle_interrupt(iface);
+	spin_unlock_irqrestore(&iface->lock, flags);
+	return IRQ_HANDLED;
+}
+
+static void bfin_twi_timeout(unsigned long data)
+{
+	struct bfin_twi_iface *iface = (struct bfin_twi_iface *)data;
+	unsigned long flags;
+
+	spin_lock_irqsave(&iface->lock, flags);
+	bfin_twi_handle_interrupt(iface);
+	if (iface->result == 0) {
+		iface->timeout_count--;
+		if (iface->timeout_count > 0) {
+			iface->timeout_timer.expires = jiffies + POLL_TIMEOUT;
+			add_timer(&iface->timeout_timer);
+		} else {
+			iface->result = -1;
+			complete(&iface->complete);
+		}
+	}
+	spin_unlock_irqrestore(&iface->lock, flags);
+}
+
+/*
+ * Generic i2c master transfer entrypoint
+ */
+static int bfin_twi_master_xfer(struct i2c_adapter *adap,
+				struct i2c_msg *msgs, int num)
+{
+	struct bfin_twi_iface *iface = adap->algo_data;
+	struct i2c_msg *pmsg;
+	int i, ret;
+	int rc = 0;
+
+	if (!(bfin_read_TWI_CONTROL() & TWI_ENA))
+		return -ENXIO;
+
+	mutex_lock(&iface->twi_lock);
+
+	while (bfin_read_TWI_MASTER_STAT() & BUSBUSY) {
+		mutex_unlock(&iface->twi_lock);
+		yield();
+		mutex_lock(&iface->twi_lock);
+	}
+
+	ret = 0;
+	for (i = 0; rc >= 0 && i < num; i++) {
+		pmsg = &msgs[i];
+		if (pmsg->flags & I2C_M_TEN) {
+			dev_err(&(adap->dev), "i2c-bfin-twi: 10 bits addr "
+				"not supported !\n");
+			rc = -EINVAL;
+			break;
+		}
+
+		iface->cur_mode = TWI_I2C_MODE_STANDARD;
+		iface->manual_stop = 0;
+		iface->transPtr = pmsg->buf;
+		iface->writeNum = iface->readNum = pmsg->len;
+		iface->result = 0;
+		iface->timeout_count = 10;
+		/* Set Transmit device address */
+		bfin_write_TWI_MASTER_ADDR(pmsg->addr);
+
+		/* FIFO Initiation. Data in FIFO should be
+		 *  discarded before start a new operation.
+		 */
+		bfin_write_TWI_FIFO_CTL(0x3);
+		SSYNC();
+		bfin_write_TWI_FIFO_CTL(0);
+		SSYNC();
+
+		if (pmsg->flags & I2C_M_RD)
+			iface->read_write = I2C_SMBUS_READ;
+		else {
+			iface->read_write = I2C_SMBUS_WRITE;
+			/* Transmit first data */
+			if (iface->writeNum > 0) {
+				bfin_write_TWI_XMT_DATA8(*(iface->transPtr++));
+				iface->writeNum--;
+				SSYNC();
+			}
+		}
+
+		/* clear int stat */
+		bfin_write_TWI_INT_STAT(MERR|MCOMP|XMTSERV|RCVSERV);
+
+		/* Interrupt mask . Enable XMT, RCV interrupt */
+		bfin_write_TWI_INT_MASK(MCOMP | MERR |
+			((iface->read_write == I2C_SMBUS_READ)?
+			RCVSERV : XMTSERV));
+		SSYNC();
+
+		if (pmsg->len > 0 && pmsg->len <= 255)
+			bfin_write_TWI_MASTER_CTL(pmsg->len << 6);
+		else if (pmsg->len > 255) {
+			bfin_write_TWI_MASTER_CTL(0xff << 6);
+			iface->manual_stop = 1;
+		} else
+			break;
+
+		iface->timeout_timer.expires = jiffies + POLL_TIMEOUT;
+		add_timer(&iface->timeout_timer);
+
+		/* Master enable */
+		bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL() | MEN |
+			((iface->read_write == I2C_SMBUS_READ) ? MDIR : 0) |
+			((CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ>100) ? FAST : 0));
+		SSYNC();
+
+		wait_for_completion(&iface->complete);
+
+		rc = iface->result;
+		if (rc == 1)
+			ret++;
+		else if (rc == -1)
+			break;
+	}
+
+	/* Release mutex */
+	mutex_unlock(&iface->twi_lock);
+
+	return ret;
+}
+
+/*
+ * SMBus type transfer entrypoint
+ */
+
+int bfin_twi_smbus_xfer(struct i2c_adapter *adap, u16 addr,
+			unsigned short flags, char read_write,
+			u8 command, int size, union i2c_smbus_data *data)
+{
+	struct bfin_twi_iface *iface = adap->algo_data;
+	int rc = 0;
+
+	if (!(bfin_read_TWI_CONTROL() & TWI_ENA))
+		return -ENXIO;
+
+	mutex_lock(&iface->twi_lock);
+
+	while (bfin_read_TWI_MASTER_STAT() & BUSBUSY) {
+		mutex_unlock(&iface->twi_lock);
+		yield();
+		mutex_lock(&iface->twi_lock);
+	}
+
+	iface->writeNum = 0;
+	iface->readNum = 0;
+
+	/* Prepare datas & select mode */
+	switch (size) {
+	case I2C_SMBUS_QUICK:
+		iface->transPtr = NULL;
+		iface->cur_mode = TWI_I2C_MODE_STANDARD;
+		break;
+	case I2C_SMBUS_BYTE:
+		if (data == NULL)
+			iface->transPtr = NULL;
+		else {
+			if (read_write == I2C_SMBUS_READ)
+				iface->readNum = 1;
+			else
+				iface->writeNum = 1;
+			iface->transPtr = &data->byte;
+		}
+		iface->cur_mode = TWI_I2C_MODE_STANDARD;
+		break;
+	case I2C_SMBUS_BYTE_DATA:
+		if (read_write == I2C_SMBUS_READ) {
+			iface->readNum = 1;
+			iface->cur_mode = TWI_I2C_MODE_COMBINED;
+		} else {
+			iface->writeNum = 1;
+			iface->cur_mode = TWI_I2C_MODE_STANDARDSUB;
+		}
+		iface->transPtr = &data->byte;
+		break;
+	case I2C_SMBUS_WORD_DATA:
+		if (read_write == I2C_SMBUS_READ) {
+			iface->readNum = 2;
+			iface->cur_mode = TWI_I2C_MODE_COMBINED;
+		} else {
+			iface->writeNum = 2;
+			iface->cur_mode = TWI_I2C_MODE_STANDARDSUB;
+		}
+		iface->transPtr = (u8 *)&data->word;
+		break;
+	case I2C_SMBUS_PROC_CALL:
+		iface->writeNum = 2;
+		iface->readNum = 2;
+		iface->cur_mode = TWI_I2C_MODE_COMBINED;
+		iface->transPtr = (u8 *)&data->word;
+		break;
+	case I2C_SMBUS_BLOCK_DATA:
+		if (read_write == I2C_SMBUS_READ) {
+			iface->readNum = 0;
+			iface->cur_mode = TWI_I2C_MODE_COMBINED;
+		} else {
+			iface->writeNum = data->block[0] + 1;
+			iface->cur_mode = TWI_I2C_MODE_STANDARDSUB;
+		}
+		iface->transPtr = data->block;
+		break;
+	default:
+		return -1;
+	}
+
+	iface->result = 0;
+	iface->manual_stop = 0;
+	iface->read_write = read_write;
+	iface->command = command;
+	iface->timeout_count = 10;
+
+	/* FIFO Initiation. Data in FIFO should be discarded before
+	 * start a new operation.
+	 */
+	bfin_write_TWI_FIFO_CTL(0x3);
+	SSYNC();
+	bfin_write_TWI_FIFO_CTL(0);
+
+	/* clear int stat */
+	bfin_write_TWI_INT_STAT(MERR|MCOMP|XMTSERV|RCVSERV);
+
+	/* Set Transmit device address */
+	bfin_write_TWI_MASTER_ADDR(addr);
+	SSYNC();
+
+	iface->timeout_timer.expires = jiffies + POLL_TIMEOUT;
+	add_timer(&iface->timeout_timer);
+
+	switch (iface->cur_mode) {
+	case TWI_I2C_MODE_STANDARDSUB:
+		bfin_write_TWI_XMT_DATA8(iface->command);
+		bfin_write_TWI_INT_MASK(MCOMP | MERR |
+			((iface->read_write == I2C_SMBUS_READ) ?
+			RCVSERV : XMTSERV));
+		SSYNC();
+
+		if (iface->writeNum + 1 <= 255)
+			bfin_write_TWI_MASTER_CTL((iface->writeNum + 1) << 6);
+		else {
+			bfin_write_TWI_MASTER_CTL(0xff << 6);
+			iface->manual_stop = 1;
+		}
+		/* Master enable */
+		bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL() | MEN |
+			((CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ>100) ? FAST : 0));
+		break;
+	case TWI_I2C_MODE_COMBINED:
+		bfin_write_TWI_XMT_DATA8(iface->command);
+		bfin_write_TWI_INT_MASK(MCOMP | MERR | RCVSERV | XMTSERV);
+		SSYNC();
+
+		if (iface->writeNum > 0)
+			bfin_write_TWI_MASTER_CTL((iface->writeNum + 1) << 6);
+		else
+			bfin_write_TWI_MASTER_CTL(0x1 << 6);
+		/* Master enable */
+		bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL() | MEN |
+			((CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ>100) ? FAST : 0));
+		break;
+	default:
+		bfin_write_TWI_MASTER_CTL(0);
+		if (size != I2C_SMBUS_QUICK) {
+			/* Don't access xmit data register when this is a
+			 * read operation.
+			 */
+			if (iface->read_write != I2C_SMBUS_READ) {
+				if (iface->writeNum > 0) {
+					bfin_write_TWI_XMT_DATA8(*(iface->transPtr++));
+					if (iface->writeNum <= 255)
+						bfin_write_TWI_MASTER_CTL(iface->writeNum << 6);
+					else {
+						bfin_write_TWI_MASTER_CTL(0xff << 6);
+						iface->manual_stop = 1;
+					}
+					iface->writeNum--;
+				} else {
+					bfin_write_TWI_XMT_DATA8(iface->command);
+					bfin_write_TWI_MASTER_CTL(1 << 6);
+				}
+			} else {
+				if (iface->readNum > 0 && iface->readNum <= 255)
+					bfin_write_TWI_MASTER_CTL(iface->readNum << 6);
+				else if (iface->readNum > 255) {
+					bfin_write_TWI_MASTER_CTL(0xff << 6);
+					iface->manual_stop = 1;
+				} else {
+					del_timer(&iface->timeout_timer);
+					break;
+				}
+			}
+		}
+		bfin_write_TWI_INT_MASK(MCOMP | MERR |
+			((iface->read_write == I2C_SMBUS_READ) ?
+			RCVSERV : XMTSERV));
+		SSYNC();
+
+		/* Master enable */
+		bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL() | MEN |
+			((iface->read_write == I2C_SMBUS_READ) ? MDIR : 0) |
+			((CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ > 100) ? FAST : 0));
+		break;
+	}
+	SSYNC();
+
+	wait_for_completion(&iface->complete);
+
+	rc = (iface->result >= 0) ? 0 : -1;
+
+	/* Release mutex */
+	mutex_unlock(&iface->twi_lock);
+
+	return rc;
+}
+
+/*
+ * Return what the adapter supports
+ */
+static u32 bfin_twi_functionality(struct i2c_adapter *adap)
+{
+	return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
+	       I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
+	       I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_PROC_CALL |
+	       I2C_FUNC_I2C;
+}
+
+
+static struct i2c_algorithm bfin_twi_algorithm = {
+	.master_xfer   = bfin_twi_master_xfer,
+	.smbus_xfer    = bfin_twi_smbus_xfer,
+	.functionality = bfin_twi_functionality,
+};
+
+
+static int i2c_bfin_twi_suspend(struct platform_device *dev, pm_message_t state)
+{
+/*	struct bfin_twi_iface *iface = platform_get_drvdata(dev);*/
+
+	/* Disable TWI */
+	bfin_write_TWI_CONTROL(bfin_read_TWI_CONTROL() & ~TWI_ENA);
+	SSYNC();
+
+	return 0;
+}
+
+static int i2c_bfin_twi_resume(struct platform_device *dev)
+{
+/*	struct bfin_twi_iface *iface = platform_get_drvdata(dev);*/
+
+	/* Enable TWI */
+	bfin_write_TWI_CONTROL(bfin_read_TWI_CONTROL() | TWI_ENA);
+	SSYNC();
+
+	return 0;
+}
+
+static int i2c_bfin_twi_probe(struct platform_device *dev)
+{
+	struct bfin_twi_iface *iface = &twi_iface;
+	struct i2c_adapter *p_adap;
+	int rc;
+
+	mutex_init(&(iface->twi_lock));
+	spin_lock_init(&(iface->lock));
+	init_completion(&(iface->complete));
+	iface->irq = IRQ_TWI;
+
+	init_timer(&(iface->timeout_timer));
+	iface->timeout_timer.function = bfin_twi_timeout;
+	iface->timeout_timer.data = (unsigned long)iface;
+
+	p_adap = &iface->adap;
+	p_adap->id = I2C_HW_BLACKFIN;
+	strlcpy(p_adap->name, dev->name, sizeof(p_adap->name));
+	p_adap->algo = &bfin_twi_algorithm;
+	p_adap->algo_data = iface;
+	p_adap->class = I2C_CLASS_ALL;
+	p_adap->dev.parent = &dev->dev;
+
+	rc = request_irq(iface->irq, bfin_twi_interrupt_entry,
+		IRQF_DISABLED, dev->name, iface);
+	if (rc) {
+		dev_err(&(p_adap->dev), "i2c-bfin-twi: can't get IRQ %d !\n",
+			iface->irq);
+		return -ENODEV;
+	}
+
+	/* Set TWI internal clock as 10MHz */
+	bfin_write_TWI_CONTROL(((get_sclk() / 1024 / 1024 + 5) / 10) & 0x7F);
+
+	/* Set Twi interface clock as specified */
+	bfin_write_TWI_CLKDIV((( 5*1024 / CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ )
+			<< 8) | (( 5*1024 / CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ )
+			& 0xFF));
+
+	/* Enable TWI */
+	bfin_write_TWI_CONTROL(bfin_read_TWI_CONTROL() | TWI_ENA);
+	SSYNC();
+
+	rc = i2c_add_adapter(p_adap);
+	if (rc < 0)
+		free_irq(iface->irq, iface);
+	else
+		platform_set_drvdata(dev, iface);
+
+	return rc;
+}
+
+static int i2c_bfin_twi_remove(struct platform_device *pdev)
+{
+	struct bfin_twi_iface *iface = platform_get_drvdata(pdev);
+
+	platform_set_drvdata(pdev, NULL);
+
+	i2c_del_adapter(&(iface->adap));
+	free_irq(iface->irq, iface);
+
+	return 0;
+}
+
+static struct platform_driver i2c_bfin_twi_driver = {
+	.probe		= i2c_bfin_twi_probe,
+	.remove		= i2c_bfin_twi_remove,
+	.suspend	= i2c_bfin_twi_suspend,
+	.resume		= i2c_bfin_twi_resume,
+	.driver		= {
+		.name	= "i2c-bfin-twi",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init i2c_bfin_twi_init(void)
+{
+	pr_info("I2C: Blackfin I2C TWI driver\n");
+
+	return platform_driver_register(&i2c_bfin_twi_driver);
+}
+
+static void __exit i2c_bfin_twi_exit(void)
+{
+	platform_driver_unregister(&i2c_bfin_twi_driver);
+}
+
+MODULE_AUTHOR("Sonic Zhang <sonic.zhang@analog.com>");
+MODULE_DESCRIPTION("I2C-Bus adapter routines for Blackfin TWI");
+MODULE_LICENSE("GPL");
+
+module_init(i2c_bfin_twi_init);
+module_exit(i2c_bfin_twi_exit);
diff --git a/drivers/i2c/busses/i2c-elektor.c b/drivers/i2c/busses/i2c-elektor.c
index 8349674..804f0a5 100644
--- a/drivers/i2c/busses/i2c-elektor.c
+++ b/drivers/i2c/busses/i2c-elektor.c
@@ -35,6 +35,7 @@
 #include <linux/pci.h>
 #include <linux/wait.h>
 
+#include <linux/isa.h>
 #include <linux/i2c.h>
 #include <linux/i2c-algo-pcf.h>
 
@@ -207,7 +208,7 @@
 	.name		= "i2c-elektor",
 };
 
-static int __init i2c_pcfisa_init(void)
+static int __devinit elektor_match(struct device *dev, unsigned int id)
 {
 #ifdef __alpha__
 	/* check to see we have memory mapped PCF8584 connected to the
@@ -222,9 +223,8 @@
 			/* yeap, we've found cypress, let's check config */
 			if (!pci_read_config_byte(cy693_dev, 0x47, &config)) {
 
-				pr_debug("%s: found cy82c693, config "
-					 "register 0x47 = 0x%02x\n",
-					 pcf_isa_ops.name, config);
+				dev_dbg(dev, "found cy82c693, config "
+					"register 0x47 = 0x%02x\n", config);
 
 				/* UP2000 board has this register set to 0xe1,
 				   but the most significant bit as seems can be
@@ -244,9 +244,9 @@
 					   8.25 MHz (PCI/4) clock
 					   (this can be read from cypress) */
 					clock = I2C_PCF_CLK | I2C_PCF_TRNS90;
-					pr_info("%s: found API UP2000 like "
-						"board, will probe PCF8584 "
-						"later\n", pcf_isa_ops.name);
+					dev_info(dev, "found API UP2000 like "
+						 "board, will probe PCF8584 "
+						 "later\n");
 				}
 			}
 			pci_dev_put(cy693_dev);
@@ -256,22 +256,27 @@
 
 	/* sanity checks for mmapped I/O */
 	if (mmapped && base < 0xc8000) {
-		printk(KERN_ERR "%s: incorrect base address (%#x) specified "
-		       "for mmapped I/O\n", pcf_isa_ops.name, base);
-		return -ENODEV;
+		dev_err(dev, "incorrect base address (%#x) specified "
+		       "for mmapped I/O\n", base);
+		return 0;
 	}
 
 	if (base == 0) {
 		base = DEFAULT_BASE;
 	}
+	return 1;
+}
 
+static int __devinit elektor_probe(struct device *dev, unsigned int id)
+{
 	init_waitqueue_head(&pcf_wait);
 	if (pcf_isa_init())
 		return -ENODEV;
+	pcf_isa_ops.dev.parent = dev;
 	if (i2c_pcf_add_bus(&pcf_isa_ops) < 0)
 		goto fail;
 
-	dev_info(&pcf_isa_ops.dev, "found device at %#x\n", base);
+	dev_info(dev, "found device at %#x\n", base);
 
 	return 0;
 
@@ -291,7 +296,7 @@
 	return -ENODEV;
 }
 
-static void i2c_pcfisa_exit(void)
+static int __devexit elektor_remove(struct device *dev, unsigned int id)
 {
 	i2c_del_adapter(&pcf_isa_ops);
 
@@ -307,6 +312,28 @@
 		iounmap(base_iomem);
 		release_mem_region(base, 2);
 	}
+
+	return 0;
+}
+
+static struct isa_driver i2c_elektor_driver = {
+	.match		= elektor_match,
+	.probe		= elektor_probe,
+	.remove		= __devexit_p(elektor_remove),
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= "i2c-elektor",
+	},
+};
+
+static int __init i2c_pcfisa_init(void)
+{
+	return isa_register_driver(&i2c_elektor_driver, 1);
+}
+
+static void __exit i2c_pcfisa_exit(void)
+{
+	isa_unregister_driver(&i2c_elektor_driver);
 }
 
 MODULE_AUTHOR("Hans Berglund <hb@spacetec.no>");
diff --git a/drivers/i2c/busses/i2c-gpio.c b/drivers/i2c/busses/i2c-gpio.c
new file mode 100644
index 0000000..a7dd546
--- /dev/null
+++ b/drivers/i2c/busses/i2c-gpio.c
@@ -0,0 +1,215 @@
+/*
+ * Bitbanging I2C bus driver using the GPIO API
+ *
+ * Copyright (C) 2007 Atmel Corporation
+ *
+ * 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/i2c.h>
+#include <linux/i2c-algo-bit.h>
+#include <linux/i2c-gpio.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <asm/gpio.h>
+
+/* Toggle SDA by changing the direction of the pin */
+static void i2c_gpio_setsda_dir(void *data, int state)
+{
+	struct i2c_gpio_platform_data *pdata = data;
+
+	if (state)
+		gpio_direction_input(pdata->sda_pin);
+	else
+		gpio_direction_output(pdata->sda_pin, 0);
+}
+
+/*
+ * Toggle SDA by changing the output value of the pin. This is only
+ * valid for pins configured as open drain (i.e. setting the value
+ * high effectively turns off the output driver.)
+ */
+static void i2c_gpio_setsda_val(void *data, int state)
+{
+	struct i2c_gpio_platform_data *pdata = data;
+
+	gpio_set_value(pdata->sda_pin, state);
+}
+
+/* Toggle SCL by changing the direction of the pin. */
+static void i2c_gpio_setscl_dir(void *data, int state)
+{
+	struct i2c_gpio_platform_data *pdata = data;
+
+	if (state)
+		gpio_direction_input(pdata->scl_pin);
+	else
+		gpio_direction_output(pdata->scl_pin, 0);
+}
+
+/*
+ * Toggle SCL by changing the output value of the pin. This is used
+ * for pins that are configured as open drain and for output-only
+ * pins. The latter case will break the i2c protocol, but it will
+ * often work in practice.
+ */
+static void i2c_gpio_setscl_val(void *data, int state)
+{
+	struct i2c_gpio_platform_data *pdata = data;
+
+	gpio_set_value(pdata->scl_pin, state);
+}
+
+int i2c_gpio_getsda(void *data)
+{
+	struct i2c_gpio_platform_data *pdata = data;
+
+	return gpio_get_value(pdata->sda_pin);
+}
+
+int i2c_gpio_getscl(void *data)
+{
+	struct i2c_gpio_platform_data *pdata = data;
+
+	return gpio_get_value(pdata->scl_pin);
+}
+
+static int __init i2c_gpio_probe(struct platform_device *pdev)
+{
+	struct i2c_gpio_platform_data *pdata;
+	struct i2c_algo_bit_data *bit_data;
+	struct i2c_adapter *adap;
+	int ret;
+
+	pdata = pdev->dev.platform_data;
+	if (!pdata)
+		return -ENXIO;
+
+	ret = -ENOMEM;
+	adap = kzalloc(sizeof(struct i2c_adapter), GFP_KERNEL);
+	if (!adap)
+		goto err_alloc_adap;
+	bit_data = kzalloc(sizeof(struct i2c_algo_bit_data), GFP_KERNEL);
+	if (!bit_data)
+		goto err_alloc_bit_data;
+
+	ret = gpio_request(pdata->sda_pin, "sda");
+	if (ret)
+		goto err_request_sda;
+	ret = gpio_request(pdata->scl_pin, "scl");
+	if (ret)
+		goto err_request_scl;
+
+	if (pdata->sda_is_open_drain) {
+		gpio_direction_output(pdata->sda_pin, 1);
+		bit_data->setsda = i2c_gpio_setsda_val;
+	} else {
+		gpio_direction_input(pdata->sda_pin);
+		bit_data->setsda = i2c_gpio_setsda_dir;
+	}
+
+	if (pdata->scl_is_open_drain || pdata->scl_is_output_only) {
+		gpio_direction_output(pdata->scl_pin, 1);
+		bit_data->setscl = i2c_gpio_setscl_val;
+	} else {
+		gpio_direction_input(pdata->scl_pin);
+		bit_data->setscl = i2c_gpio_setscl_dir;
+	}
+
+	if (!pdata->scl_is_output_only)
+		bit_data->getscl = i2c_gpio_getscl;
+	bit_data->getsda = i2c_gpio_getsda;
+
+	if (pdata->udelay)
+		bit_data->udelay = pdata->udelay;
+	else if (pdata->scl_is_output_only)
+		bit_data->udelay = 50;			/* 10 kHz */
+	else
+		bit_data->udelay = 5;			/* 100 kHz */
+
+	if (pdata->timeout)
+		bit_data->timeout = pdata->timeout;
+	else
+		bit_data->timeout = HZ / 10;		/* 100 ms */
+
+	bit_data->data = pdata;
+
+	adap->owner = THIS_MODULE;
+	snprintf(adap->name, sizeof(adap->name), "i2c-gpio%d", pdev->id);
+	adap->algo_data = bit_data;
+	adap->dev.parent = &pdev->dev;
+
+	ret = i2c_bit_add_bus(adap);
+	if (ret)
+		goto err_add_bus;
+
+	platform_set_drvdata(pdev, adap);
+
+	dev_info(&pdev->dev, "using pins %u (SDA) and %u (SCL%s)\n",
+		 pdata->sda_pin, pdata->scl_pin,
+		 pdata->scl_is_output_only
+		 ? ", no clock stretching" : "");
+
+	return 0;
+
+err_add_bus:
+	gpio_free(pdata->scl_pin);
+err_request_scl:
+	gpio_free(pdata->sda_pin);
+err_request_sda:
+	kfree(bit_data);
+err_alloc_bit_data:
+	kfree(adap);
+err_alloc_adap:
+	return ret;
+}
+
+static int __exit i2c_gpio_remove(struct platform_device *pdev)
+{
+	struct i2c_gpio_platform_data *pdata;
+	struct i2c_adapter *adap;
+
+	adap = platform_get_drvdata(pdev);
+	pdata = pdev->dev.platform_data;
+
+	i2c_del_adapter(adap);
+	gpio_free(pdata->scl_pin);
+	gpio_free(pdata->sda_pin);
+	kfree(adap->algo_data);
+	kfree(adap);
+
+	return 0;
+}
+
+static struct platform_driver i2c_gpio_driver = {
+	.driver		= {
+		.name	= "i2c-gpio",
+		.owner	= THIS_MODULE,
+	},
+	.remove		= __exit_p(i2c_gpio_remove),
+};
+
+static int __init i2c_gpio_init(void)
+{
+	int ret;
+
+	ret = platform_driver_probe(&i2c_gpio_driver, i2c_gpio_probe);
+	if (ret)
+		printk(KERN_ERR "i2c-gpio: probe failed: %d\n", ret);
+
+	return ret;
+}
+module_init(i2c_gpio_init);
+
+static void __exit i2c_gpio_exit(void)
+{
+	platform_driver_unregister(&i2c_gpio_driver);
+}
+module_exit(i2c_gpio_exit);
+
+MODULE_AUTHOR("Haavard Skinnemoen <hskinnemoen@atmel.com>");
+MODULE_DESCRIPTION("Platform-independent bitbanging I2C driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
index a320e7d..611b571 100644
--- a/drivers/i2c/busses/i2c-i801.c
+++ b/drivers/i2c/busses/i2c-i801.c
@@ -527,7 +527,7 @@
 	/* set up the sysfs linkage to our parent device */
 	i801_adapter.dev.parent = &dev->dev;
 
-	snprintf(i801_adapter.name, I2C_NAME_SIZE,
+	snprintf(i801_adapter.name, sizeof(i801_adapter.name),
 		"SMBus I801 adapter at %04lx", i801_smba);
 	err = i2c_add_adapter(&i801_adapter);
 	if (err) {
diff --git a/drivers/i2c/busses/i2c-isa.c b/drivers/i2c/busses/i2c-isa.c
index 5f33bc9..b0e1370 100644
--- a/drivers/i2c/busses/i2c-isa.c
+++ b/drivers/i2c/busses/i2c-isa.c
@@ -41,6 +41,10 @@
 #include <linux/platform_device.h>
 #include <linux/completion.h>
 
+/* Exported by i2c-core for i2c-isa only */
+extern void i2c_adapter_dev_release(struct device *dev);
+extern struct class i2c_adapter_class;
+
 static u32 isa_func(struct i2c_adapter *adapter);
 
 /* This is the actual algorithm we define */
@@ -64,16 +68,6 @@
 }
 
 
-/* Copied from i2c-core */
-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);
-}
-static DEVICE_ATTR(name, S_IRUGO, show_adapter_name, NULL);
-
-
 /* We implement an interface which resembles i2c_{add,del}_driver,
    but for i2c-isa drivers. We don't have to remember and handle lists
    of drivers and adapters so this is much more simple, of course. */
@@ -139,41 +133,18 @@
 	isa_adapter.nr = ANY_I2C_ISA_BUS;
 	isa_adapter.dev.parent = &platform_bus;
 	sprintf(isa_adapter.dev.bus_id, "i2c-%d", isa_adapter.nr);
-	isa_adapter.dev.driver = &i2c_adapter_driver;
 	isa_adapter.dev.release = &i2c_adapter_dev_release;
+	isa_adapter.dev.class = &i2c_adapter_class;
 	err = device_register(&isa_adapter.dev);
 	if (err) {
 		printk(KERN_ERR "i2c-isa: Failed to register device\n");
 		goto exit;
 	}
-	err = device_create_file(&isa_adapter.dev, &dev_attr_name);
-	if (err) {
-		printk(KERN_ERR "i2c-isa: Failed to create name file\n");
-		goto exit_unregister;
-	}
-
-	/* Add this adapter to the i2c_adapter class */
-	memset(&isa_adapter.class_dev, 0x00, sizeof(struct class_device));
-	isa_adapter.class_dev.dev = &isa_adapter.dev;
-	isa_adapter.class_dev.class = &i2c_adapter_class;
-	strlcpy(isa_adapter.class_dev.class_id, isa_adapter.dev.bus_id,
-		BUS_ID_SIZE);
-	err = class_device_register(&isa_adapter.class_dev);
-	if (err) {
-		printk(KERN_ERR "i2c-isa: Failed to register class device\n");
-		goto exit_remove_name;
-	}
 
 	dev_dbg(&isa_adapter.dev, "%s registered\n", isa_adapter.name);
 
 	return 0;
 
-exit_remove_name:
-	device_remove_file(&isa_adapter.dev, &dev_attr_name);
-exit_unregister:
-	init_completion(&isa_adapter.dev_released); /* Needed? */
-	device_unregister(&isa_adapter.dev);
-	wait_for_completion(&isa_adapter.dev_released);
 exit:
 	return err;
 }
@@ -201,15 +172,11 @@
 	/* Clean up the sysfs representation */
 	dev_dbg(&isa_adapter.dev, "Unregistering from sysfs\n");
 	init_completion(&isa_adapter.dev_released);
-	init_completion(&isa_adapter.class_dev_released);
-	class_device_unregister(&isa_adapter.class_dev);
-	device_remove_file(&isa_adapter.dev, &dev_attr_name);
 	device_unregister(&isa_adapter.dev);
 
 	/* Wait for sysfs to drop all references */
 	dev_dbg(&isa_adapter.dev, "Waiting for sysfs completion\n");
 	wait_for_completion(&isa_adapter.dev_released);
-	wait_for_completion(&isa_adapter.class_dev_released);
 
 	dev_dbg(&isa_adapter.dev, "%s unregistered\n", isa_adapter.name);
 }
diff --git a/drivers/i2c/busses/i2c-ixp2000.c b/drivers/i2c/busses/i2c-ixp2000.c
index efa3ecc..6352121 100644
--- a/drivers/i2c/busses/i2c-ixp2000.c
+++ b/drivers/i2c/busses/i2c-ixp2000.c
@@ -118,7 +118,7 @@
 
 	drv_data->adapter.id = I2C_HW_B_IXP2000,
 	strlcpy(drv_data->adapter.name, plat_dev->dev.driver->name,
-		I2C_NAME_SIZE);
+		sizeof(drv_data->adapter.name));
 	drv_data->adapter.algo_data = &drv_data->algo_data,
 
 	drv_data->adapter.dev.parent = &plat_dev->dev;
diff --git a/drivers/i2c/busses/i2c-ixp4xx.c b/drivers/i2c/busses/i2c-ixp4xx.c
index 08e89b8..069ed7f 100644
--- a/drivers/i2c/busses/i2c-ixp4xx.c
+++ b/drivers/i2c/busses/i2c-ixp4xx.c
@@ -127,7 +127,7 @@
 	drv_data->adapter.id = I2C_HW_B_IXP4XX;
 	drv_data->adapter.class = I2C_CLASS_HWMON;
 	strlcpy(drv_data->adapter.name, plat_dev->dev.driver->name,
-		I2C_NAME_SIZE);
+		sizeof(drv_data->adapter.name));
 	drv_data->adapter.algo_data = &drv_data->algo_data;
 
 	drv_data->adapter.dev.parent = &plat_dev->dev;
diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
index ee65aa1b..c6b6898 100644
--- a/drivers/i2c/busses/i2c-mpc.c
+++ b/drivers/i2c/busses/i2c-mpc.c
@@ -17,7 +17,6 @@
 #include <linux/module.h>
 #include <linux/sched.h>
 #include <linux/init.h>
-#include <linux/pci.h>
 #include <linux/platform_device.h>
 
 #include <asm/io.h>
diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c
index a3283b9..a55b333 100644
--- a/drivers/i2c/busses/i2c-mv64xxx.c
+++ b/drivers/i2c/busses/i2c-mv64xxx.c
@@ -508,7 +508,7 @@
 	}
 
 	strlcpy(drv_data->adapter.name, MV64XXX_I2C_CTLR_NAME " adapter",
-		I2C_NAME_SIZE);
+		sizeof(drv_data->adapter.name));
 
 	init_waitqueue_head(&drv_data->waitq);
 	spin_lock_init(&drv_data->lock);
diff --git a/drivers/i2c/busses/i2c-nforce2.c b/drivers/i2c/busses/i2c-nforce2.c
index 1514ec5..3cd0d63 100644
--- a/drivers/i2c/busses/i2c-nforce2.c
+++ b/drivers/i2c/busses/i2c-nforce2.c
@@ -33,6 +33,8 @@
     nForce4 MCP-04		0034
     nForce4 MCP51		0264
     nForce4 MCP55		0368
+    nForce MCP61		03EB
+    nForce MCP65		0446
 
     This driver supports the 2 SMBuses that are included in the MCP of the
     nForce2/3/4/5xx chipsets.
@@ -200,6 +202,8 @@
 	{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SMBUS) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SMBUS) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SMBUS) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SMBUS) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_SMBUS) },
 	{ 0 }
 };
 
@@ -240,7 +244,7 @@
 	smbus->adapter.algo = &smbus_algorithm;
 	smbus->adapter.algo_data = smbus;
 	smbus->adapter.dev.parent = &dev->dev;
-	snprintf(smbus->adapter.name, I2C_NAME_SIZE,
+	snprintf(smbus->adapter.name, sizeof(smbus->adapter.name),
 		"SMBus nForce2 adapter at %04x", smbus->base);
 
 	error = i2c_add_adapter(&smbus->adapter);
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index bcd8367..e471e3b 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -605,7 +605,8 @@
 	adap->dev.parent = &pdev->dev;
 
 	/* i2c device drivers may be active on return from add_adapter() */
-	r = i2c_add_adapter(adap);
+	adap->nr = pdev->id;
+	r = i2c_add_numbered_adapter(adap);
 	if (r) {
 		dev_err(dev->dev, "failure adding adapter\n");
 		goto err_free_irq;
diff --git a/drivers/i2c/busses/i2c-parport-light.c b/drivers/i2c/busses/i2c-parport-light.c
index 4bc4281..49a95e2 100644
--- a/drivers/i2c/busses/i2c-parport-light.c
+++ b/drivers/i2c/busses/i2c-parport-light.c
@@ -1,7 +1,7 @@
 /* ------------------------------------------------------------------------ *
- * i2c-parport.c I2C bus over parallel port                                 *
+ * i2c-parport-light.c I2C bus over parallel port                           *
  * ------------------------------------------------------------------------ *
-   Copyright (C) 2003-2004 Jean Delvare <khali@linux-fr.org>
+   Copyright (C) 2003-2007 Jean Delvare <khali@linux-fr.org>
    
    Based on older i2c-velleman.c driver
    Copyright (C) 1995-2000 Simon G. Vogl
@@ -27,6 +27,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
+#include <linux/platform_device.h>
 #include <linux/ioport.h>
 #include <linux/i2c.h>
 #include <linux/i2c-algo-bit.h>
@@ -34,6 +35,9 @@
 #include "i2c-parport.h"
 
 #define DEFAULT_BASE 0x378
+#define DRVNAME "i2c-parport-light"
+
+static struct platform_device *pdev;
 
 static u16 base;
 module_param(base, ushort, 0);
@@ -106,7 +110,7 @@
 	.timeout	= HZ,
 }; 
 
-/* ----- I2c structure ---------------------------------------------------- */
+/* ----- Driver registration ---------------------------------------------- */
 
 static struct i2c_adapter parport_adapter = {
 	.owner		= THIS_MODULE,
@@ -116,30 +120,14 @@
 	.name		= "Parallel port adapter (light)",
 };
 
-/* ----- Module loading, unloading and information ------------------------ */
-
-static int __init i2c_parport_init(void)
+static int __devinit i2c_parport_probe(struct platform_device *pdev)
 {
-	if (type < 0) {
-		printk(KERN_WARNING "i2c-parport: adapter type unspecified\n");
-		return -ENODEV;
-	}
+	int err;
+	struct resource *res;
 
-	if (type >= ARRAY_SIZE(adapter_parm)) {
-		printk(KERN_WARNING "i2c-parport: invalid type (%d)\n", type);
-		return -ENODEV;
-	}
-
-	if (base == 0) {
-		printk(KERN_INFO "i2c-parport: using default base 0x%x\n", DEFAULT_BASE);
-		base = DEFAULT_BASE;
-	}
-
-	if (!request_region(base, 3, "i2c-parport"))
-		return -ENODEV;
-
-        if (!adapter_parm[type].getscl.val)
-		parport_algo_data.getscl = NULL;
+	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+	if (!request_region(res->start, res->end - res->start + 1, DRVNAME))
+		return -EBUSY;
 
 	/* Reset hardware to a sane state (SCL and SDA high) */
 	parport_setsda(NULL, 1);
@@ -148,23 +136,125 @@
 	if (adapter_parm[type].init.val)
 		line_set(1, &adapter_parm[type].init);
 
-	if (i2c_bit_add_bus(&parport_adapter) < 0) {
-		printk(KERN_ERR "i2c-parport: Unable to register with I2C\n");
-		release_region(base, 3);
-		return -ENODEV;
+	parport_adapter.dev.parent = &pdev->dev;
+	err = i2c_bit_add_bus(&parport_adapter);
+	if (err) {
+		dev_err(&pdev->dev, "Unable to register with I2C\n");
+		goto exit_region;
 	}
-
 	return 0;
+
+exit_region:
+	release_region(res->start, res->end - res->start + 1);
+	return err;
 }
 
-static void __exit i2c_parport_exit(void)
+static int __devexit i2c_parport_remove(struct platform_device *pdev)
 {
+	struct resource *res;
+
+	i2c_del_adapter(&parport_adapter);
+
 	/* Un-init if needed (power off...) */
 	if (adapter_parm[type].init.val)
 		line_set(0, &adapter_parm[type].init);
 
-	i2c_del_adapter(&parport_adapter);
-	release_region(base, 3);
+	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+	release_region(res->start, res->end - res->start + 1);
+	return 0;
+}
+
+static struct platform_driver i2c_parport_driver = {
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= DRVNAME,
+	},
+	.probe		= i2c_parport_probe,
+	.remove		= __devexit_p(i2c_parport_remove),
+};
+
+static int __init i2c_parport_device_add(u16 address)
+{
+	struct resource res = {
+		.start	= address,
+		.end	= address + 2,
+		.name	= DRVNAME,
+		.flags	= IORESOURCE_IO,
+	};
+	int err;
+
+	pdev = platform_device_alloc(DRVNAME, -1);
+	if (!pdev) {
+		err = -ENOMEM;
+		printk(KERN_ERR DRVNAME ": Device allocation failed\n");
+		goto exit;
+	}
+
+	err = platform_device_add_resources(pdev, &res, 1);
+	if (err) {
+		printk(KERN_ERR DRVNAME ": Device resource addition failed "
+		       "(%d)\n", err);
+		goto exit_device_put;
+	}
+
+	err = platform_device_add(pdev);
+	if (err) {
+		printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
+		       err);
+		goto exit_device_put;
+	}
+
+	return 0;
+
+exit_device_put:
+	platform_device_put(pdev);
+exit:
+	return err;
+}
+
+static int __init i2c_parport_init(void)
+{
+	int err;
+
+	if (type < 0) {
+		printk(KERN_ERR DRVNAME ": adapter type unspecified\n");
+		return -ENODEV;
+	}
+
+	if (type >= ARRAY_SIZE(adapter_parm)) {
+		printk(KERN_ERR DRVNAME ": invalid type (%d)\n", type);
+		return -ENODEV;
+	}
+
+	if (base == 0) {
+		pr_info(DRVNAME ": using default base 0x%x\n", DEFAULT_BASE);
+		base = DEFAULT_BASE;
+	}
+
+        if (!adapter_parm[type].getscl.val)
+		parport_algo_data.getscl = NULL;
+
+	/* Sets global pdev as a side effect */
+	err = i2c_parport_device_add(base);
+	if (err)
+		goto exit;
+
+	err = platform_driver_register(&i2c_parport_driver);
+	if (err)
+		goto exit_device;
+
+	return 0;
+
+exit_device:
+	platform_device_unregister(pdev);
+exit:
+	return err;
+}
+
+static void __exit i2c_parport_exit(void)
+{
+	platform_driver_unregister(&i2c_parport_driver);
+	platform_device_unregister(pdev);
 }
 
 MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>");
diff --git a/drivers/i2c/busses/i2c-parport.c b/drivers/i2c/busses/i2c-parport.c
index 66696a4..8c95370 100644
--- a/drivers/i2c/busses/i2c-parport.c
+++ b/drivers/i2c/busses/i2c-parport.c
@@ -1,7 +1,7 @@
 /* ------------------------------------------------------------------------ *
  * i2c-parport.c I2C bus over parallel port                                 *
  * ------------------------------------------------------------------------ *
-   Copyright (C) 2003-2004 Jean Delvare <khali@linux-fr.org>
+   Copyright (C) 2003-2007 Jean Delvare <khali@linux-fr.org>
    
    Based on older i2c-philips-par.c driver
    Copyright (C) 1995-2000 Simon G. Vogl
@@ -137,19 +137,12 @@
 	.setscl		= parport_setscl,
 	.getsda		= parport_getsda,
 	.getscl		= parport_getscl,
-	.udelay		= 60,
+	.udelay		= 10, /* ~50 kbps */
 	.timeout	= HZ,
 }; 
 
 /* ----- I2c and parallel port call-back functions and structures --------- */
 
-static struct i2c_adapter parport_adapter = {
-	.owner		= THIS_MODULE,
-	.class		= I2C_CLASS_HWMON,
-	.id		= I2C_HW_B_LP,
-	.name		= "Parallel port adapter",
-};
-
 static void i2c_parport_attach (struct parport *port)
 {
 	struct i2c_par *adapter;
@@ -169,10 +162,17 @@
 	}
 
 	/* Fill the rest of the structure */
-	adapter->adapter = parport_adapter;
+	adapter->adapter.owner = THIS_MODULE;
+	adapter->adapter.class = I2C_CLASS_HWMON;
+	adapter->adapter.id = I2C_HW_B_LP;
+	strlcpy(adapter->adapter.name, "Parallel port adapter",
+		sizeof(adapter->adapter.name));
 	adapter->algo_data = parport_algo_data;
-	if (!adapter_parm[type].getscl.val)
+	/* Slow down if we can't sense SCL */
+	if (!adapter_parm[type].getscl.val) {
 		adapter->algo_data.getscl = NULL;
+		adapter->algo_data.udelay = 50; /* ~10 kbps */
+	}
 	adapter->algo_data.data = port;
 	adapter->adapter.algo_data = &adapter->algo_data;
 
@@ -214,11 +214,12 @@
 	for (prev = NULL, adapter = adapter_list; adapter;
 	     prev = adapter, adapter = adapter->next) {
 		if (adapter->pdev->port == port) {
+			i2c_del_adapter(&adapter->adapter);
+
 			/* Un-init if needed (power off...) */
 			if (adapter_parm[type].init.val)
 				line_set(port, 0, &adapter_parm[type].init);
 				
-			i2c_del_adapter(&adapter->adapter);
 			parport_unregister_device(adapter->pdev);
 			if (prev)
 				prev->next = adapter->next;
diff --git a/drivers/i2c/busses/i2c-pasemi.c b/drivers/i2c/busses/i2c-pasemi.c
index bf89eee..58e3271 100644
--- a/drivers/i2c/busses/i2c-pasemi.c
+++ b/drivers/i2c/busses/i2c-pasemi.c
@@ -358,7 +358,7 @@
 	}
 
 	smbus->adapter.owner = THIS_MODULE;
-	snprintf(smbus->adapter.name, I2C_NAME_SIZE,
+	snprintf(smbus->adapter.name, sizeof(smbus->adapter.name),
 		 "PA Semi SMBus adapter at 0x%lx", smbus->base);
 	smbus->adapter.class = I2C_CLASS_HWMON;
 	smbus->adapter.algo = &smbus_algorithm;
diff --git a/drivers/i2c/busses/i2c-pca-isa.c b/drivers/i2c/busses/i2c-pca-isa.c
index cc6536a..5161aaf 100644
--- a/drivers/i2c/busses/i2c-pca-isa.c
+++ b/drivers/i2c/busses/i2c-pca-isa.c
@@ -25,9 +25,9 @@
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
-#include <linux/pci.h>
 #include <linux/wait.h>
 
+#include <linux/isa.h>
 #include <linux/i2c.h>
 #include <linux/i2c-algo-pca.h>
 
@@ -119,27 +119,26 @@
 	.name		= "PCA9564 ISA Adapter",
 };
 
-static int __init pca_isa_init(void)
+static int __devinit pca_isa_probe(struct device *dev, unsigned int id)
 {
-
 	init_waitqueue_head(&pca_wait);
 
-	printk(KERN_INFO "i2c-pca-isa: i/o base %#08lx. irq %d\n", base, irq);
+	dev_info(dev, "i/o base %#08lx. irq %d\n", base, irq);
 
 	if (!request_region(base, IO_SIZE, "i2c-pca-isa")) {
-		printk(KERN_ERR "i2c-pca-isa: I/O address %#08lx is in use.\n", base);
+		dev_err(dev, "I/O address %#08lx is in use\n", base);
 		goto out;
 	}
 
 	if (irq > -1) {
 		if (request_irq(irq, pca_handler, 0, "i2c-pca-isa", &pca_isa_ops) < 0) {
-			printk(KERN_ERR "i2c-pca-isa: Request irq%d failed\n", irq);
+			dev_err(dev, "Request irq%d failed\n", irq);
 			goto out_region;
 		}
 	}
 
 	if (i2c_pca_add_bus(&pca_isa_ops) < 0) {
-		printk(KERN_ERR "i2c-pca-isa: Failed to add i2c bus\n");
+		dev_err(dev, "Failed to add i2c bus\n");
 		goto out_irq;
 	}
 
@@ -154,7 +153,7 @@
 	return -ENODEV;
 }
 
-static void pca_isa_exit(void)
+static int __devexit pca_isa_remove(struct device *dev, unsigned int id)
 {
 	i2c_del_adapter(&pca_isa_ops);
 
@@ -163,6 +162,27 @@
 		free_irq(irq, &pca_isa_ops);
 	}
 	release_region(base, IO_SIZE);
+
+	return 0;
+}
+
+static struct isa_driver pca_isa_driver = {
+	.probe		= pca_isa_probe,
+	.remove		= __devexit_p(pca_isa_remove),
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= "i2c-pca-isa",
+	}
+};
+
+static int __init pca_isa_init(void)
+{
+	return isa_register_driver(&pca_isa_driver, 1);
+}
+
+static void __exit pca_isa_exit(void)
+{
+	isa_unregister_driver(&pca_isa_driver);
 }
 
 MODULE_AUTHOR("Ian Campbell <icampbell@arcom.com>");
diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c
index 21b1809..5a52bf5e 100644
--- a/drivers/i2c/busses/i2c-piix4.c
+++ b/drivers/i2c/busses/i2c-piix4.c
@@ -428,7 +428,7 @@
 	/* set up the sysfs linkage to our parent device */
 	piix4_adapter.dev.parent = &dev->dev;
 
-	snprintf(piix4_adapter.name, I2C_NAME_SIZE,
+	snprintf(piix4_adapter.name, sizeof(piix4_adapter.name),
 		"SMBus PIIX4 adapter at %04x", piix4_smba);
 
 	if ((retval = i2c_add_adapter(&piix4_adapter))) {
diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c
index 14e83d0..c059b27 100644
--- a/drivers/i2c/busses/i2c-pxa.c
+++ b/drivers/i2c/busses/i2c-pxa.c
@@ -539,6 +539,18 @@
 	writel(icr | ICR_START | ICR_TB, _ICR(i2c));
 }
 
+static inline void i2c_pxa_stop_message(struct pxa_i2c *i2c)
+{
+	u32 icr;
+
+	/*
+	 * Clear the STOP and ACK flags
+	 */
+	icr = readl(_ICR(i2c));
+	icr &= ~(ICR_STOP | ICR_ACKNAK);
+	writel(icr, _IRC(i2c));
+}
+
 /*
  * We are protected by the adapter bus mutex.
  */
@@ -581,6 +593,7 @@
 	 * The rest of the processing occurs in the interrupt handler.
 	 */
 	timeout = wait_event_timeout(i2c->wait, i2c->msg_num == 0, HZ * 5);
+	i2c_pxa_stop_message(i2c);
 
 	/*
 	 * We place the return code in i2c->msg_idx.
@@ -825,7 +838,7 @@
 };
 
 static struct pxa_i2c i2c_pxa = {
-	.lock	= SPIN_LOCK_UNLOCKED,
+	.lock	= __SPIN_LOCK_UNLOCKED(i2c_pxa.lock),
 	.adap	= {
 		.owner		= THIS_MODULE,
 		.algo		= &i2c_pxa_algorithm,
diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c
index 556f244..e68a96f 100644
--- a/drivers/i2c/busses/i2c-s3c2410.c
+++ b/drivers/i2c/busses/i2c-s3c2410.c
@@ -61,6 +61,8 @@
 	unsigned int		msg_idx;
 	unsigned int		msg_ptr;
 
+	unsigned int		tx_setup;
+
 	enum s3c24xx_i2c_state	state;
 
 	void __iomem		*regs;
@@ -199,8 +201,11 @@
 	dev_dbg(i2c->dev, "START: %08lx to IICSTAT, %02x to DS\n", stat, addr);
 	writeb(addr, i2c->regs + S3C2410_IICDS);
 	
-	// delay a bit and reset iiccon before setting start (per samsung)
-	udelay(1);
+	/* delay here to ensure the data byte has gotten onto the bus
+	 * before the transaction is started */
+
+	ndelay(i2c->tx_setup);
+
 	dev_dbg(i2c->dev, "iiccon, %08lx\n", iiccon);
 	writel(iiccon, i2c->regs + S3C2410_IICCON);
 	
@@ -322,7 +327,15 @@
 		if (!is_msgend(i2c)) {
 			byte = i2c->msg->buf[i2c->msg_ptr++];
 			writeb(byte, i2c->regs + S3C2410_IICDS);
-			
+
+			/* delay after writing the byte to allow the
+			 * data setup time on the bus, as writing the
+			 * data to the register causes the first bit
+			 * to appear on SDA, and SCL will change as
+			 * soon as the interrupt is acknowledged */
+
+			ndelay(i2c->tx_setup);
+
 		} else if (!is_lastmsg(i2c)) {
 			/* we need to go to the next i2c message */
 
@@ -570,9 +583,10 @@
 };
 
 static struct s3c24xx_i2c s3c24xx_i2c = {
-	.lock	= SPIN_LOCK_UNLOCKED,
-	.wait	= __WAIT_QUEUE_HEAD_INITIALIZER(s3c24xx_i2c.wait),
-	.adap	= {
+	.lock		= __SPIN_LOCK_UNLOCKED(s3c24xx_i2c.lock),
+	.wait		= __WAIT_QUEUE_HEAD_INITIALIZER(s3c24xx_i2c.wait),
+	.tx_setup	= 50,
+	.adap		= {
 		.name			= "s3c2410-i2c",
 		.owner			= THIS_MODULE,
 		.algo			= &s3c24xx_i2c_algorithm,
@@ -731,26 +745,6 @@
 	return 0;
 }
 
-static void s3c24xx_i2c_free(struct s3c24xx_i2c *i2c)
-{
-	if (i2c->clk != NULL && !IS_ERR(i2c->clk)) {
-		clk_disable(i2c->clk);
-		clk_put(i2c->clk);
-		i2c->clk = NULL;
-	}
-
-	if (i2c->regs != NULL) {
-		iounmap(i2c->regs);
-		i2c->regs = NULL;
-	}
-
-	if (i2c->ioarea != NULL) {
-		release_resource(i2c->ioarea);
-		kfree(i2c->ioarea);
-		i2c->ioarea = NULL;
-	}
-}
-
 /* s3c24xx_i2c_probe
  *
  * called by the bus driver when a suitable device is found
@@ -769,7 +763,7 @@
 	if (IS_ERR(i2c->clk)) {
 		dev_err(&pdev->dev, "cannot get clock\n");
 		ret = -ENOENT;
-		goto out;
+		goto err_noclk;
 	}
 
 	dev_dbg(&pdev->dev, "clock source %p\n", i2c->clk);
@@ -782,7 +776,7 @@
 	if (res == NULL) {
 		dev_err(&pdev->dev, "cannot find IO resource\n");
 		ret = -ENOENT;
-		goto out;
+		goto err_clk;
 	}
 
 	i2c->ioarea = request_mem_region(res->start, (res->end-res->start)+1,
@@ -791,7 +785,7 @@
 	if (i2c->ioarea == NULL) {
 		dev_err(&pdev->dev, "cannot request IO\n");
 		ret = -ENXIO;
-		goto out;
+		goto err_clk;
 	}
 
 	i2c->regs = ioremap(res->start, (res->end-res->start)+1);
@@ -799,7 +793,7 @@
 	if (i2c->regs == NULL) {
 		dev_err(&pdev->dev, "cannot map IO\n");
 		ret = -ENXIO;
-		goto out;
+		goto err_ioarea;
 	}
 
 	dev_dbg(&pdev->dev, "registers %p (%p, %p)\n", i2c->regs, i2c->ioarea, res);
@@ -813,7 +807,7 @@
 
 	ret = s3c24xx_i2c_init(i2c);
 	if (ret != 0)
-		goto out;
+		goto err_iomap;
 
 	/* find the IRQ for this unit (note, this relies on the init call to
 	 * ensure no current IRQs pending 
@@ -823,7 +817,7 @@
 	if (res == NULL) {
 		dev_err(&pdev->dev, "cannot find IRQ\n");
 		ret = -ENOENT;
-		goto out;
+		goto err_iomap;
 	}
 
 	ret = request_irq(res->start, s3c24xx_i2c_irq, IRQF_DISABLED,
@@ -831,7 +825,7 @@
 
 	if (ret != 0) {
 		dev_err(&pdev->dev, "cannot claim IRQ\n");
-		goto out;
+		goto err_iomap;
 	}
 
 	i2c->irq = res;
@@ -841,17 +835,29 @@
 	ret = i2c_add_adapter(&i2c->adap);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "failed to add bus to i2c core\n");
-		goto out;
+		goto err_irq;
 	}
 
 	platform_set_drvdata(pdev, i2c);
 
 	dev_info(&pdev->dev, "%s: S3C I2C adapter\n", i2c->adap.dev.bus_id);
+	return 0;
 
- out:
-	if (ret < 0)
-		s3c24xx_i2c_free(i2c);
+ err_irq:
+	free_irq(i2c->irq->start, i2c);
 
+ err_iomap:
+	iounmap(i2c->regs);
+
+ err_ioarea:
+	release_resource(i2c->ioarea);
+	kfree(i2c->ioarea);
+
+ err_clk:
+	clk_disable(i2c->clk);
+	clk_put(i2c->clk);
+
+ err_noclk:
 	return ret;
 }
 
@@ -863,11 +869,17 @@
 static int s3c24xx_i2c_remove(struct platform_device *pdev)
 {
 	struct s3c24xx_i2c *i2c = platform_get_drvdata(pdev);
-	
-	if (i2c != NULL) {
-		s3c24xx_i2c_free(i2c);
-		platform_set_drvdata(pdev, NULL);
-	}
+
+	i2c_del_adapter(&i2c->adap);
+	free_irq(i2c->irq->start, i2c);
+
+	clk_disable(i2c->clk);
+	clk_put(i2c->clk);
+
+	iounmap(i2c->regs);
+
+	release_resource(i2c->ioarea);
+	kfree(i2c->ioarea);
 
 	return 0;
 }
diff --git a/drivers/i2c/busses/i2c-simtec.c b/drivers/i2c/busses/i2c-simtec.c
new file mode 100644
index 0000000..10af8d3
--- /dev/null
+++ b/drivers/i2c/busses/i2c-simtec.c
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 2005 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * Simtec Generic I2C Controller
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+
+#include <asm/io.h>
+
+struct simtec_i2c_data {
+	struct resource		*ioarea;
+	void __iomem		*reg;
+	struct i2c_adapter	 adap;
+	struct i2c_algo_bit_data bit;
+};
+
+#define CMD_SET_SDA	(1<<2)
+#define CMD_SET_SCL	(1<<3)
+
+#define STATE_SDA	(1<<0)
+#define STATE_SCL	(1<<1)
+
+/* i2c bit-bus functions */
+
+static void simtec_i2c_setsda(void *pw, int state)
+{
+	struct simtec_i2c_data *pd = pw;
+	writeb(CMD_SET_SDA | (state ? STATE_SDA : 0), pd->reg);
+}
+
+static void simtec_i2c_setscl(void *pw, int state)
+{
+	struct simtec_i2c_data *pd = pw;
+	writeb(CMD_SET_SCL | (state ? STATE_SCL : 0), pd->reg);
+}
+
+static int simtec_i2c_getsda(void *pw)
+{
+	struct simtec_i2c_data *pd = pw;
+	return readb(pd->reg) & STATE_SDA ? 1 : 0;
+}
+
+static int simtec_i2c_getscl(void *pw)
+{
+	struct simtec_i2c_data *pd = pw;
+	return readb(pd->reg) & STATE_SCL ? 1 : 0;
+}
+
+/* device registration */
+
+static int simtec_i2c_probe(struct platform_device *dev)
+{
+	struct simtec_i2c_data *pd;
+	struct resource *res;
+	int size;
+	int ret;
+
+	pd = kzalloc(sizeof(struct simtec_i2c_data), GFP_KERNEL);
+	if (pd == NULL) {
+		dev_err(&dev->dev, "cannot allocate private data\n");
+		return -ENOMEM;
+	}
+
+	platform_set_drvdata(dev, pd);
+
+	res = platform_get_resource(dev, IORESOURCE_MEM, 0);
+	if (res == NULL) {
+		dev_err(&dev->dev, "cannot find IO resource\n");
+		ret = -ENOENT;
+		goto err;
+	}
+
+	size = (res->end-res->start)+1;
+
+	pd->ioarea = request_mem_region(res->start, size, dev->name);
+	if (pd->ioarea == NULL) {
+		dev_err(&dev->dev, "cannot request IO\n");
+		ret = -ENXIO;
+		goto err;
+	}
+
+	pd->reg = ioremap(res->start, size);
+	if (pd->reg == NULL) {
+		dev_err(&dev->dev, "cannot map IO\n");
+		ret = -ENXIO;
+		goto err_res;
+	}
+
+	/* setup the private data */
+
+	pd->adap.owner = THIS_MODULE;
+	pd->adap.algo_data = &pd->bit;
+	pd->adap.dev.parent = &dev->dev;
+
+	strlcpy(pd->adap.name, "Simtec I2C", sizeof(pd->adap.name));
+
+	pd->bit.data = pd;
+	pd->bit.setsda = simtec_i2c_setsda;
+	pd->bit.setscl = simtec_i2c_setscl;
+	pd->bit.getsda = simtec_i2c_getsda;
+	pd->bit.getscl = simtec_i2c_getscl;
+	pd->bit.timeout = HZ;
+	pd->bit.udelay = 20;
+
+	ret = i2c_bit_add_bus(&pd->adap);
+	if (ret)
+		goto err_all;
+
+	return 0;
+
+ err_all:
+	iounmap(pd->reg);
+
+ err_res:
+	release_resource(pd->ioarea);
+	kfree(pd->ioarea);
+
+ err:
+	kfree(pd);
+	return ret;
+}
+
+static int simtec_i2c_remove(struct platform_device *dev)
+{
+	struct simtec_i2c_data *pd = platform_get_drvdata(dev);
+
+	i2c_del_adapter(&pd->adap);
+
+	iounmap(pd->reg);
+	release_resource(pd->ioarea);
+	kfree(pd->ioarea);
+	kfree(pd);
+
+	return 0;
+}
+
+
+/* device driver */
+
+static struct platform_driver simtec_i2c_driver = {
+	.driver		= {
+		.name		= "simtec-i2c",
+		.owner		= THIS_MODULE,
+	},
+	.probe		= simtec_i2c_probe,
+	.remove		= simtec_i2c_remove,
+};
+
+static int __init i2c_adap_simtec_init(void)
+{
+	return platform_driver_register(&simtec_i2c_driver);
+}
+
+static void __exit i2c_adap_simtec_exit(void)
+{
+	platform_driver_unregister(&simtec_i2c_driver);
+}
+
+module_init(i2c_adap_simtec_init);
+module_exit(i2c_adap_simtec_exit);
+
+MODULE_DESCRIPTION("Simtec Generic I2C Bus driver");
+MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/i2c/busses/i2c-sis96x.c b/drivers/i2c/busses/i2c-sis96x.c
index 4157b0c..dc235bb 100644
--- a/drivers/i2c/busses/i2c-sis96x.c
+++ b/drivers/i2c/busses/i2c-sis96x.c
@@ -300,7 +300,7 @@
 	/* set up the sysfs linkage to our parent device */
 	sis96x_adapter.dev.parent = &dev->dev;
 
-	snprintf(sis96x_adapter.name, I2C_NAME_SIZE,
+	snprintf(sis96x_adapter.name, sizeof(sis96x_adapter.name),
 		"SiS96x SMBus adapter at 0x%04x", sis96x_smbus_base);
 
 	if ((retval = i2c_add_adapter(&sis96x_adapter))) {
diff --git a/drivers/i2c/busses/i2c-tiny-usb.c b/drivers/i2c/busses/i2c-tiny-usb.c
new file mode 100644
index 0000000..9079990
--- /dev/null
+++ b/drivers/i2c/busses/i2c-tiny-usb.c
@@ -0,0 +1,277 @@
+/*
+ * driver for the i2c-tiny-usb adapter - 1.0
+ * http://www.harbaum.org/till/i2c_tiny_usb
+ *
+ * Copyright (C) 2006-2007 Till Harbaum (Till@Harbaum.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, version 2.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+
+/* include interfaces to usb layer */
+#include <linux/usb.h>
+
+/* include interface to i2c layer */
+#include <linux/i2c.h>
+
+/* commands via USB, must match command ids in the firmware */
+#define CMD_ECHO		0
+#define CMD_GET_FUNC		1
+#define CMD_SET_DELAY		2
+#define CMD_GET_STATUS		3
+
+#define CMD_I2C_IO		4
+#define CMD_I2C_IO_BEGIN	(1<<0)
+#define CMD_I2C_IO_END		(1<<1)
+
+/* i2c bit delay, default is 10us -> 100kHz */
+static int delay = 10;
+module_param(delay, int, 0);
+MODULE_PARM_DESC(delay, "bit delay in microseconds, "
+		 "e.g. 10 for 100kHz (default is 100kHz)");
+
+static int usb_read(struct i2c_adapter *adapter, int cmd,
+		    int value, int index, void *data, int len);
+
+static int usb_write(struct i2c_adapter *adapter, int cmd,
+		     int value, int index, void *data, int len);
+
+/* ----- begin of i2c layer ---------------------------------------------- */
+
+#define STATUS_IDLE		0
+#define STATUS_ADDRESS_ACK	1
+#define STATUS_ADDRESS_NAK	2
+
+static int usb_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num)
+{
+	unsigned char status;
+	struct i2c_msg *pmsg;
+	int i;
+
+	dev_dbg(&adapter->dev, "master xfer %d messages:\n", num);
+
+	for (i = 0 ; i < num ; i++) {
+		int cmd = CMD_I2C_IO;
+
+		if (i == 0)
+			cmd |= CMD_I2C_IO_BEGIN;
+
+		if (i == num-1)
+			cmd |= CMD_I2C_IO_END;
+
+		pmsg = &msgs[i];
+
+		dev_dbg(&adapter->dev,
+			"  %d: %s (flags %d) %d bytes to 0x%02x\n",
+			i, pmsg->flags & I2C_M_RD ? "read" : "write",
+			pmsg->flags, pmsg->len, pmsg->addr);
+
+		/* and directly send the message */
+		if (pmsg->flags & I2C_M_RD) {
+			/* read data */
+			if (usb_read(adapter, cmd,
+				     pmsg->flags, pmsg->addr,
+				     pmsg->buf, pmsg->len) != pmsg->len) {
+				dev_err(&adapter->dev,
+					"failure reading data\n");
+				return -EREMOTEIO;
+			}
+		} else {
+			/* write data */
+			if (usb_write(adapter, cmd,
+				      pmsg->flags, pmsg->addr,
+				      pmsg->buf, pmsg->len) != pmsg->len) {
+				dev_err(&adapter->dev,
+					"failure writing data\n");
+				return -EREMOTEIO;
+			}
+		}
+
+		/* read status */
+		if (usb_read(adapter, CMD_GET_STATUS, 0, 0, &status, 1) != 1) {
+			dev_err(&adapter->dev, "failure reading status\n");
+			return -EREMOTEIO;
+		}
+
+		dev_dbg(&adapter->dev, "  status = %d\n", status);
+		if (status == STATUS_ADDRESS_NAK)
+			return -EREMOTEIO;
+	}
+
+	return i;
+}
+
+static u32 usb_func(struct i2c_adapter *adapter)
+{
+	u32 func;
+
+	/* get functionality from adapter */
+	if (usb_read(adapter, CMD_GET_FUNC, 0, 0, &func, sizeof(func)) !=
+	    sizeof(func)) {
+		dev_err(&adapter->dev, "failure reading functionality\n");
+		return 0;
+	}
+
+	return func;
+}
+
+/* This is the actual algorithm we define */
+static const struct i2c_algorithm usb_algorithm = {
+	.master_xfer	= usb_xfer,
+	.functionality	= usb_func,
+};
+
+/* ----- end of i2c layer ------------------------------------------------ */
+
+/* ----- begin of usb layer ---------------------------------------------- */
+
+/* The usb i2c interface uses a vid/pid pair donated by */
+/* Future Technology Devices International Ltd. */
+static struct usb_device_id i2c_tiny_usb_table [] = {
+	{ USB_DEVICE(0x0403, 0xc631) },
+	{ }			/* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(usb, i2c_tiny_usb_table);
+
+/* Structure to hold all of our device specific stuff */
+struct i2c_tiny_usb {
+	struct usb_device *usb_dev; /* the usb device for this device */
+	struct usb_interface *interface; /* the interface for this device */
+	struct i2c_adapter adapter; /* i2c related things */
+};
+
+static int usb_read(struct i2c_adapter *adapter, int cmd,
+		    int value, int index, void *data, int len)
+{
+	struct i2c_tiny_usb *dev = (struct i2c_tiny_usb *)adapter->algo_data;
+
+	/* do control transfer */
+	return usb_control_msg(dev->usb_dev, usb_rcvctrlpipe(dev->usb_dev, 0),
+			       cmd, USB_TYPE_VENDOR | USB_RECIP_INTERFACE |
+			       USB_DIR_IN, value, index, data, len, 2000);
+}
+
+static int usb_write(struct i2c_adapter *adapter, int cmd,
+		     int value, int index, void *data, int len)
+{
+	struct i2c_tiny_usb *dev = (struct i2c_tiny_usb *)adapter->algo_data;
+
+	/* do control transfer */
+	return usb_control_msg(dev->usb_dev, usb_sndctrlpipe(dev->usb_dev, 0),
+			       cmd, USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
+			       value, index, data, len, 2000);
+}
+
+static void i2c_tiny_usb_free(struct i2c_tiny_usb *dev)
+{
+	usb_put_dev(dev->usb_dev);
+	kfree(dev);
+}
+
+static int i2c_tiny_usb_probe(struct usb_interface *interface,
+			      const struct usb_device_id *id)
+{
+	struct i2c_tiny_usb *dev;
+	int retval = -ENOMEM;
+	u16 version;
+
+	dev_dbg(&interface->dev, "probing usb device\n");
+
+	/* allocate memory for our device state and initialize it */
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+	if (dev == NULL) {
+		dev_err(&interface->dev, "Out of memory\n");
+		goto error;
+	}
+
+	dev->usb_dev = usb_get_dev(interface_to_usbdev(interface));
+	dev->interface = interface;
+
+	/* save our data pointer in this interface device */
+	usb_set_intfdata(interface, dev);
+
+	version = le16_to_cpu(dev->usb_dev->descriptor.bcdDevice);
+	dev_info(&interface->dev,
+		 "version %x.%02x found at bus %03d address %03d\n",
+		 version >> 8, version & 0xff,
+		 dev->usb_dev->bus->busnum, dev->usb_dev->devnum);
+
+	/* setup i2c adapter description */
+	dev->adapter.owner = THIS_MODULE;
+	dev->adapter.class = I2C_CLASS_HWMON;
+	dev->adapter.algo = &usb_algorithm;
+	dev->adapter.algo_data = dev;
+	snprintf(dev->adapter.name, I2C_NAME_SIZE,
+		 "i2c-tiny-usb at bus %03d device %03d",
+		 dev->usb_dev->bus->busnum, dev->usb_dev->devnum);
+
+	if (usb_write(&dev->adapter, CMD_SET_DELAY,
+		      cpu_to_le16(delay), 0, NULL, 0) != 0) {
+		dev_err(&dev->adapter.dev,
+			"failure setting delay to %dus\n", delay);
+		retval = -EIO;
+		goto error;
+	}
+
+	dev->adapter.dev.parent = &dev->interface->dev;
+
+	/* and finally attach to i2c layer */
+	i2c_add_adapter(&dev->adapter);
+
+	/* inform user about successful attachment to i2c layer */
+	dev_info(&dev->adapter.dev, "connected i2c-tiny-usb device\n");
+
+	return 0;
+
+ error:
+	if (dev)
+		i2c_tiny_usb_free(dev);
+
+	return retval;
+}
+
+static void i2c_tiny_usb_disconnect(struct usb_interface *interface)
+{
+	struct i2c_tiny_usb *dev = usb_get_intfdata(interface);
+
+	i2c_del_adapter(&dev->adapter);
+	usb_set_intfdata(interface, NULL);
+	i2c_tiny_usb_free(dev);
+
+	dev_dbg(&interface->dev, "disconnected\n");
+}
+
+static struct usb_driver i2c_tiny_usb_driver = {
+	.name		= "i2c-tiny-usb",
+	.probe		= i2c_tiny_usb_probe,
+	.disconnect	= i2c_tiny_usb_disconnect,
+	.id_table	= i2c_tiny_usb_table,
+};
+
+static int __init usb_i2c_tiny_usb_init(void)
+{
+	/* register this driver with the USB subsystem */
+	return usb_register(&i2c_tiny_usb_driver);
+}
+
+static void __exit usb_i2c_tiny_usb_exit(void)
+{
+	/* deregister this driver with the USB subsystem */
+	usb_deregister(&i2c_tiny_usb_driver);
+}
+
+module_init(usb_i2c_tiny_usb_init);
+module_exit(usb_i2c_tiny_usb_exit);
+
+/* ----- end of usb layer ------------------------------------------------ */
+
+MODULE_AUTHOR("Till Harbaum <Till@Harbaum.org>");
+MODULE_DESCRIPTION("i2c-tiny-usb driver v1.0");
+MODULE_LICENSE("GPL");
diff --git a/drivers/i2c/busses/i2c-viapro.c b/drivers/i2c/busses/i2c-viapro.c
index 03c5fc8..7a2bc06 100644
--- a/drivers/i2c/busses/i2c-viapro.c
+++ b/drivers/i2c/busses/i2c-viapro.c
@@ -404,7 +404,7 @@
 	}
 
 	vt596_adapter.dev.parent = &pdev->dev;
-	snprintf(vt596_adapter.name, I2C_NAME_SIZE,
+	snprintf(vt596_adapter.name, sizeof(vt596_adapter.name),
 		 "SMBus Via Pro adapter at %04x", vt596_smba);
 
 	vt596_pdev = pci_dev_get(pdev);
diff --git a/drivers/i2c/busses/scx200_acb.c b/drivers/i2c/busses/scx200_acb.c
index 0b082c5..0db56e7 100644
--- a/drivers/i2c/busses/scx200_acb.c
+++ b/drivers/i2c/busses/scx200_acb.c
@@ -441,7 +441,7 @@
 
 	adapter = &iface->adapter;
 	i2c_set_adapdata(adapter, iface);
-	snprintf(adapter->name, I2C_NAME_SIZE, "%s ACB%d", text, index);
+	snprintf(adapter->name, sizeof(adapter->name), "%s ACB%d", text, index);
 	adapter->owner = THIS_MODULE;
 	adapter->id = I2C_HW_SMBUS_SCX200;
 	adapter->algo = &scx200_acb_algorithm;
@@ -599,6 +599,7 @@
 		else {
 			int i;
 
+			pci_dev_put(pdev);
 			for (i = 0; i < MAX_DEVICES; ++i) {
 				if (base[i] == 0)
 					continue;
diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig
index 87ee3ce..ea085a0 100644
--- a/drivers/i2c/chips/Kconfig
+++ b/drivers/i2c/chips/Kconfig
@@ -3,11 +3,10 @@
 #
 
 menu "Miscellaneous I2C Chip support"
-	depends on I2C
 
 config SENSORS_DS1337
 	tristate "Dallas Semiconductor DS1337 and DS1339 Real Time Clock"
-	depends on I2C && EXPERIMENTAL
+	depends on EXPERIMENTAL
 	help
 	  If you say yes here you get support for Dallas Semiconductor
 	  DS1337 and DS1339 real-time clock chips.
@@ -17,7 +16,7 @@
 
 config SENSORS_DS1374
 	tristate "Maxim/Dallas Semiconductor DS1374 Real Time Clock"
-	depends on I2C && EXPERIMENTAL
+	depends on EXPERIMENTAL
 	help
 	  If you say yes here you get support for Dallas Semiconductor
 	  DS1374 real-time clock chips.
@@ -27,7 +26,7 @@
 
 config SENSORS_EEPROM
 	tristate "EEPROM reader"
-	depends on I2C && EXPERIMENTAL
+	depends on EXPERIMENTAL
 	help
 	  If you say yes here you get read-only access to the EEPROM data
 	  available on modern memory DIMMs and Sony Vaio laptops.  Such
@@ -38,7 +37,7 @@
 
 config SENSORS_PCF8574
 	tristate "Philips PCF8574 and PCF8574A"
-	depends on I2C && EXPERIMENTAL
+	depends on EXPERIMENTAL
 	default n
 	help
 	  If you say yes here you get support for Philips PCF8574 and 
@@ -52,7 +51,7 @@
 
 config SENSORS_PCA9539
 	tristate "Philips PCA9539 16-bit I/O port"
-	depends on I2C && EXPERIMENTAL
+	depends on EXPERIMENTAL
 	help
 	  If you say yes here you get support for the Philips PCA9539
 	  16-bit I/O port.
@@ -62,7 +61,7 @@
 
 config SENSORS_PCF8591
 	tristate "Philips PCF8591"
-	depends on I2C && EXPERIMENTAL
+	depends on EXPERIMENTAL
 	default n
 	help
 	  If you say yes here you get support for Philips PCF8591 chips.
@@ -75,7 +74,7 @@
 
 config ISP1301_OMAP
 	tristate "Philips ISP1301 with OMAP OTG"
-	depends on I2C && ARCH_OMAP_OTG
+	depends on ARCH_OMAP_OTG
 	help
 	  If you say yes here you get support for the Philips ISP1301
 	  USB-On-The-Go transceiver working with the OMAP OTG controller.
@@ -90,7 +89,7 @@
 # and having mostly OMAP-specific board support
 config TPS65010
 	tristate "TPS6501x Power Management chips"
-	depends on I2C && ARCH_OMAP
+	depends on 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
@@ -103,7 +102,7 @@
 
 config SENSORS_M41T00
 	tristate "ST M41T00 RTC chip"
-	depends on I2C && PPC32
+	depends on PPC32
 	help
 	  If you say yes here you get support for the ST M41T00 RTC chip.
 
@@ -112,7 +111,7 @@
 
 config SENSORS_MAX6875
 	tristate "Maxim MAX6875 Power supply supervisor"
-	depends on I2C && EXPERIMENTAL
+	depends on EXPERIMENTAL
 	help
 	  If you say yes here you get support for the Maxim MAX6875
 	  EEPROM-programmable, quad power-supply sequencer/supervisor.
diff --git a/drivers/i2c/i2c-boardinfo.c b/drivers/i2c/i2c-boardinfo.c
new file mode 100644
index 0000000..ffb35f0
--- /dev/null
+++ b/drivers/i2c/i2c-boardinfo.c
@@ -0,0 +1,90 @@
+/*
+ * i2c-boardinfo.h - collect pre-declarations of I2C devices
+ *
+ * This program is free software; you can redistribute it and/or 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/i2c.h>
+
+#include "i2c-core.h"
+
+
+/* These symbols are exported ONLY FOR the i2c core.
+ * No other users will be supported.
+ */
+DEFINE_MUTEX(__i2c_board_lock);
+EXPORT_SYMBOL_GPL(__i2c_board_lock);
+
+LIST_HEAD(__i2c_board_list);
+EXPORT_SYMBOL_GPL(__i2c_board_list);
+
+int __i2c_first_dynamic_bus_num;
+EXPORT_SYMBOL_GPL(__i2c_first_dynamic_bus_num);
+
+
+/**
+ * i2c_register_board_info - statically declare I2C devices
+ * @busnum: identifies the bus to which these devices belong
+ * @info: vector of i2c device descriptors
+ * @len: how many descriptors in the vector; may be zero to reserve
+ *	the specified bus number.
+ *
+ * Systems using the Linux I2C driver stack can declare tables of board info
+ * while they initialize.  This should be done in board-specific init code
+ * near arch_initcall() time, or equivalent, before any I2C adapter driver is
+ * registered.  For example, mainboard init code could define several devices,
+ * as could the init code for each daughtercard in a board stack.
+ *
+ * The I2C devices will be created later, after the adapter for the relevant
+ * bus has been registered.  After that moment, standard driver model tools
+ * are used to bind "new style" I2C drivers to the devices.  The bus number
+ * for any device declared using this routine is not available for dynamic
+ * allocation.
+ *
+ * The board info passed can safely be __initdata, but be careful of embedded
+ * pointers (for platform_data, functions, etc) since that won't be copied.
+ */
+int __init
+i2c_register_board_info(int busnum,
+	struct i2c_board_info const *info, unsigned len)
+{
+	int status;
+
+	mutex_lock(&__i2c_board_lock);
+
+	/* dynamic bus numbers will be assigned after the last static one */
+	if (busnum >= __i2c_first_dynamic_bus_num)
+		__i2c_first_dynamic_bus_num = busnum + 1;
+
+	for (status = 0; len; len--, info++) {
+		struct i2c_devinfo	*devinfo;
+
+		devinfo = kzalloc(sizeof(*devinfo), GFP_KERNEL);
+		if (!devinfo) {
+			pr_debug("i2c-core: can't register boardinfo!\n");
+			status = -ENOMEM;
+			break;
+		}
+
+		devinfo->busnum = busnum;
+		devinfo->board_info = *info;
+		list_add_tail(&devinfo->list, &__i2c_board_list);
+	}
+
+	mutex_unlock(&__i2c_board_lock);
+
+	return status;
+}
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 21fe140..64f8e56 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -35,29 +35,92 @@
 #include <linux/completion.h>
 #include <asm/uaccess.h>
 
+#include "i2c-core.h"
+
 
 static LIST_HEAD(adapters);
 static LIST_HEAD(drivers);
 static DEFINE_MUTEX(core_lists);
 static DEFINE_IDR(i2c_adapter_idr);
 
+#define is_newstyle_driver(d) ((d)->probe || (d)->remove)
 
 /* ------------------------------------------------------------------------- */
 
-/* match always succeeds, as we want the probe() to tell if we really accept this match */
 static int i2c_device_match(struct device *dev, struct device_driver *drv)
 {
-	return 1;
+	struct i2c_client	*client = to_i2c_client(dev);
+	struct i2c_driver	*driver = to_i2c_driver(drv);
+
+	/* make legacy i2c drivers bypass driver model probing entirely;
+	 * such drivers scan each i2c adapter/bus themselves.
+	 */
+	if (!is_newstyle_driver(driver))
+		return 0;
+
+	/* new style drivers use the same kind of driver matching policy
+	 * as platform devices or SPI:  compare device and driver IDs.
+	 */
+	return strcmp(client->driver_name, drv->name) == 0;
 }
 
+#ifdef	CONFIG_HOTPLUG
+
+/* uevent helps with hotplug: modprobe -q $(MODALIAS) */
+static int i2c_device_uevent(struct device *dev, char **envp, int num_envp,
+		      char *buffer, int buffer_size)
+{
+	struct i2c_client	*client = to_i2c_client(dev);
+	int			i = 0, length = 0;
+
+	/* by definition, legacy drivers can't hotplug */
+	if (dev->driver || !client->driver_name)
+		return 0;
+
+	if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length,
+			"MODALIAS=%s", client->driver_name))
+		return -ENOMEM;
+	envp[i] = NULL;
+	dev_dbg(dev, "uevent\n");
+	return 0;
+}
+
+#else
+#define i2c_device_uevent	NULL
+#endif	/* CONFIG_HOTPLUG */
+
 static int i2c_device_probe(struct device *dev)
 {
-	return -ENODEV;
+	struct i2c_client	*client = to_i2c_client(dev);
+	struct i2c_driver	*driver = to_i2c_driver(dev->driver);
+
+	if (!driver->probe)
+		return -ENODEV;
+	client->driver = driver;
+	dev_dbg(dev, "probe\n");
+	return driver->probe(client);
 }
 
 static int i2c_device_remove(struct device *dev)
 {
-	return 0;
+	struct i2c_client	*client = to_i2c_client(dev);
+	struct i2c_driver	*driver;
+	int			status;
+
+	if (!dev->driver)
+		return 0;
+
+	driver = to_i2c_driver(dev->driver);
+	if (driver->remove) {
+		dev_dbg(dev, "remove\n");
+		status = driver->remove(client);
+	} else {
+		dev->driver = NULL;
+		status = 0;
+	}
+	if (status == 0)
+		client->driver = NULL;
+	return status;
 }
 
 static void i2c_device_shutdown(struct device *dev)
@@ -95,122 +158,184 @@
 	return driver->resume(to_i2c_client(dev));
 }
 
-struct bus_type i2c_bus_type = {
-	.name		= "i2c",
-	.match		= i2c_device_match,
-	.probe		= i2c_device_probe,
-	.remove		= i2c_device_remove,
-	.shutdown	= i2c_device_shutdown,
-	.suspend	= i2c_device_suspend,
-	.resume		= i2c_device_resume,
-};
-
-/* ------------------------------------------------------------------------- */
-
-void i2c_adapter_dev_release(struct device *dev)
-{
-	struct i2c_adapter *adap = dev_to_i2c_adapter(dev);
-	complete(&adap->dev_released);
-}
-
-struct device_driver i2c_adapter_driver = {
-	.owner = THIS_MODULE,
-	.name =	"i2c_adapter",
-	.bus = &i2c_bus_type,
-};
-
-/* ------------------------------------------------------------------------- */
-
-/* I2C bus adapters -- one roots each I2C or SMBUS segment */
-
-static void i2c_adapter_class_dev_release(struct class_device *dev)
-{
-	struct i2c_adapter *adap = class_dev_to_i2c_adapter(dev);
-	complete(&adap->class_dev_released);
-}
-
-static ssize_t i2c_adapter_show_name(struct class_device *cdev, char *buf)
-{
-	struct i2c_adapter *adap = class_dev_to_i2c_adapter(cdev);
-	return sprintf(buf, "%s\n", adap->name);
-}
-
-static struct class_device_attribute i2c_adapter_attrs[] = {
-	__ATTR(name, S_IRUGO, i2c_adapter_show_name, NULL),
-	{ },
-};
-
-struct class i2c_adapter_class = {
-	.owner			= THIS_MODULE,
-	.name			= "i2c-adapter",
-	.class_dev_attrs	= i2c_adapter_attrs,
-	.release		= &i2c_adapter_class_dev_release,
-};
-
-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);
-}
-static DEVICE_ATTR(name, S_IRUGO, show_adapter_name, NULL);
-
-
 static void i2c_client_release(struct device *dev)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	complete(&client->released);
 }
 
+static void i2c_client_dev_release(struct device *dev)
+{
+	kfree(to_i2c_client(dev));
+}
+
 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);
 }
 
-/*
- * We can't use the DEVICE_ATTR() macro here, as we used the same name for
- * an i2c adapter attribute (above).
- */
-static struct device_attribute dev_attr_client_name =
-	__ATTR(name, S_IRUGO, &show_client_name, NULL);
-
-
-/* ---------------------------------------------------
- * registering functions
- * ---------------------------------------------------
- */
-
-/* -----
- * i2c_add_adapter is called from within the algorithm layer,
- * when a new hw adapter registers. A new device is register to be
- * available for clients.
- */
-int i2c_add_adapter(struct i2c_adapter *adap)
+static ssize_t show_modalias(struct device *dev, struct device_attribute *attr, char *buf)
 {
-	int id, res = 0;
+	struct i2c_client *client = to_i2c_client(dev);
+	return client->driver_name
+		? sprintf(buf, "%s\n", client->driver_name)
+		: 0;
+}
+
+static struct device_attribute i2c_dev_attrs[] = {
+	__ATTR(name, S_IRUGO, show_client_name, NULL),
+	/* modalias helps coldplug:  modprobe $(cat .../modalias) */
+	__ATTR(modalias, S_IRUGO, show_modalias, NULL),
+	{ },
+};
+
+struct bus_type i2c_bus_type = {
+	.name		= "i2c",
+	.dev_attrs	= i2c_dev_attrs,
+	.match		= i2c_device_match,
+	.uevent		= i2c_device_uevent,
+	.probe		= i2c_device_probe,
+	.remove		= i2c_device_remove,
+	.shutdown	= i2c_device_shutdown,
+	.suspend	= i2c_device_suspend,
+	.resume		= i2c_device_resume,
+};
+EXPORT_SYMBOL_GPL(i2c_bus_type);
+
+/**
+ * i2c_new_device - instantiate an i2c device for use with a new style driver
+ * @adap: the adapter managing the device
+ * @info: describes one I2C device; bus_num is ignored
+ *
+ * Create a device to work with a new style i2c driver, where binding is
+ * handled through driver model probe()/remove() methods.  This call is not
+ * appropriate for use by mainboad initialization logic, which usually runs
+ * during an arch_initcall() long before any i2c_adapter could exist.
+ *
+ * This returns the new i2c client, which may be saved for later use with
+ * i2c_unregister_device(); or NULL to indicate an error.
+ */
+struct i2c_client *
+i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info)
+{
+	struct i2c_client	*client;
+	int			status;
+
+	client = kzalloc(sizeof *client, GFP_KERNEL);
+	if (!client)
+		return NULL;
+
+	client->adapter = adap;
+
+	client->dev.platform_data = info->platform_data;
+	client->flags = info->flags;
+	client->addr = info->addr;
+	client->irq = info->irq;
+
+	strlcpy(client->driver_name, info->driver_name,
+		sizeof(client->driver_name));
+	strlcpy(client->name, info->type, sizeof(client->name));
+
+	/* a new style driver may be bound to this device when we
+	 * return from this function, or any later moment (e.g. maybe
+	 * hotplugging will load the driver module).  and the device
+	 * refcount model is the standard driver model one.
+	 */
+	status = i2c_attach_client(client);
+	if (status < 0) {
+		kfree(client);
+		client = NULL;
+	}
+	return client;
+}
+EXPORT_SYMBOL_GPL(i2c_new_device);
+
+
+/**
+ * i2c_unregister_device - reverse effect of i2c_new_device()
+ * @client: value returned from i2c_new_device()
+ */
+void i2c_unregister_device(struct i2c_client *client)
+{
+	struct i2c_adapter	*adapter = client->adapter;
+	struct i2c_driver	*driver = client->driver;
+
+	if (driver && !is_newstyle_driver(driver)) {
+		dev_err(&client->dev, "can't unregister devices "
+			"with legacy drivers\n");
+		WARN_ON(1);
+		return;
+	}
+
+	mutex_lock(&adapter->clist_lock);
+	list_del(&client->list);
+	mutex_unlock(&adapter->clist_lock);
+
+	device_unregister(&client->dev);
+}
+EXPORT_SYMBOL_GPL(i2c_unregister_device);
+
+
+/* ------------------------------------------------------------------------- */
+
+/* I2C bus adapters -- one roots each I2C or SMBUS segment */
+
+void i2c_adapter_dev_release(struct device *dev)
+{
+	struct i2c_adapter *adap = to_i2c_adapter(dev);
+	complete(&adap->dev_released);
+}
+EXPORT_SYMBOL_GPL(i2c_adapter_dev_release);	/* exported to i2c-isa */
+
+static ssize_t
+show_adapter_name(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct i2c_adapter *adap = to_i2c_adapter(dev);
+	return sprintf(buf, "%s\n", adap->name);
+}
+
+static struct device_attribute i2c_adapter_attrs[] = {
+	__ATTR(name, S_IRUGO, show_adapter_name, NULL),
+	{ },
+};
+
+struct class i2c_adapter_class = {
+	.owner			= THIS_MODULE,
+	.name			= "i2c-adapter",
+	.dev_attrs		= i2c_adapter_attrs,
+};
+EXPORT_SYMBOL_GPL(i2c_adapter_class);		/* exported to i2c-isa */
+
+static void i2c_scan_static_board_info(struct i2c_adapter *adapter)
+{
+	struct i2c_devinfo	*devinfo;
+
+	mutex_lock(&__i2c_board_lock);
+	list_for_each_entry(devinfo, &__i2c_board_list, list) {
+		if (devinfo->busnum == adapter->nr
+				&& !i2c_new_device(adapter,
+						&devinfo->board_info))
+			printk(KERN_ERR "i2c-core: can't create i2c%d-%04x\n",
+				i2c_adapter_id(adapter),
+				devinfo->board_info.addr);
+	}
+	mutex_unlock(&__i2c_board_lock);
+}
+
+static int i2c_register_adapter(struct i2c_adapter *adap)
+{
+	int res = 0;
 	struct list_head   *item;
 	struct i2c_driver  *driver;
 
-	mutex_lock(&core_lists);
-
-	if (idr_pre_get(&i2c_adapter_idr, GFP_KERNEL) == 0) {
-		res = -ENOMEM;
-		goto out_unlock;
-	}
-
-	res = idr_get_new(&i2c_adapter_idr, adap, &id);
-	if (res < 0) {
-		if (res == -EAGAIN)
-			res = -ENOMEM;
-		goto out_unlock;
-	}
-
-	adap->nr =  id & MAX_ID_MASK;
 	mutex_init(&adap->bus_lock);
 	mutex_init(&adap->clist_lock);
-	list_add_tail(&adap->list,&adapters);
 	INIT_LIST_HEAD(&adap->clients);
 
+	mutex_lock(&core_lists);
+	list_add_tail(&adap->list, &adapters);
+
 	/* Add the adapter to the driver core.
 	 * If the parent pointer is not set up,
 	 * we add this adapter to the host bus.
@@ -221,27 +346,19 @@
 			 "physical device\n", adap->name);
 	}
 	sprintf(adap->dev.bus_id, "i2c-%d", adap->nr);
-	adap->dev.driver = &i2c_adapter_driver;
 	adap->dev.release = &i2c_adapter_dev_release;
+	adap->dev.class = &i2c_adapter_class;
 	res = device_register(&adap->dev);
 	if (res)
 		goto out_list;
-	res = device_create_file(&adap->dev, &dev_attr_name);
-	if (res)
-		goto out_unregister;
-
-	/* Add this adapter to the i2c_adapter class */
-	memset(&adap->class_dev, 0x00, sizeof(struct class_device));
-	adap->class_dev.dev = &adap->dev;
-	adap->class_dev.class = &i2c_adapter_class;
-	strlcpy(adap->class_dev.class_id, adap->dev.bus_id, BUS_ID_SIZE);
-	res = class_device_register(&adap->class_dev);
-	if (res)
-		goto out_remove_name;
 
 	dev_dbg(&adap->dev, "adapter [%s] registered\n", adap->name);
 
-	/* inform drivers of new adapters */
+	/* create pre-declared device nodes for new-style drivers */
+	if (adap->nr < __i2c_first_dynamic_bus_num)
+		i2c_scan_static_board_info(adap);
+
+	/* let legacy drivers scan this bus for matching devices */
 	list_for_each(item,&drivers) {
 		driver = list_entry(item, struct i2c_driver, list);
 		if (driver->attach_adapter)
@@ -253,18 +370,98 @@
 	mutex_unlock(&core_lists);
 	return res;
 
-out_remove_name:
-	device_remove_file(&adap->dev, &dev_attr_name);
-out_unregister:
-	init_completion(&adap->dev_released); /* Needed? */
-	device_unregister(&adap->dev);
-	wait_for_completion(&adap->dev_released);
 out_list:
 	list_del(&adap->list);
 	idr_remove(&i2c_adapter_idr, adap->nr);
 	goto out_unlock;
 }
 
+/**
+ * i2c_add_adapter - declare i2c adapter, use dynamic bus number
+ * @adapter: the adapter to add
+ *
+ * This routine is used to declare an I2C adapter when its bus number
+ * doesn't matter.  Examples: for I2C adapters dynamically added by
+ * USB links or PCI plugin cards.
+ *
+ * When this returns zero, a new bus number was allocated and stored
+ * in adap->nr, and the specified adapter became available for clients.
+ * Otherwise, a negative errno value is returned.
+ */
+int i2c_add_adapter(struct i2c_adapter *adapter)
+{
+	int	id, res = 0;
+
+retry:
+	if (idr_pre_get(&i2c_adapter_idr, GFP_KERNEL) == 0)
+		return -ENOMEM;
+
+	mutex_lock(&core_lists);
+	/* "above" here means "above or equal to", sigh */
+	res = idr_get_new_above(&i2c_adapter_idr, adapter,
+				__i2c_first_dynamic_bus_num, &id);
+	mutex_unlock(&core_lists);
+
+	if (res < 0) {
+		if (res == -EAGAIN)
+			goto retry;
+		return res;
+	}
+
+	adapter->nr = id;
+	return i2c_register_adapter(adapter);
+}
+EXPORT_SYMBOL(i2c_add_adapter);
+
+/**
+ * i2c_add_numbered_adapter - declare i2c adapter, use static bus number
+ * @adap: the adapter to register (with adap->nr initialized)
+ *
+ * This routine is used to declare an I2C adapter when its bus number
+ * matters.  Example: for I2C adapters from system-on-chip CPUs, or
+ * otherwise built in to the system's mainboard, and where i2c_board_info
+ * is used to properly configure I2C devices.
+ *
+ * If no devices have pre-been declared for this bus, then be sure to
+ * register the adapter before any dynamically allocated ones.  Otherwise
+ * the required bus ID may not be available.
+ *
+ * When this returns zero, the specified adapter became available for
+ * clients using the bus number provided in adap->nr.  Also, the table
+ * of I2C devices pre-declared using i2c_register_board_info() is scanned,
+ * and the appropriate driver model device nodes are created.  Otherwise, a
+ * negative errno value is returned.
+ */
+int i2c_add_numbered_adapter(struct i2c_adapter *adap)
+{
+	int	id;
+	int	status;
+
+	if (adap->nr & ~MAX_ID_MASK)
+		return -EINVAL;
+
+retry:
+	if (idr_pre_get(&i2c_adapter_idr, GFP_KERNEL) == 0)
+		return -ENOMEM;
+
+	mutex_lock(&core_lists);
+	/* "above" here means "above or equal to", sigh;
+	 * we need the "equal to" result to force the result
+	 */
+	status = idr_get_new_above(&i2c_adapter_idr, adap, adap->nr, &id);
+	if (status == 0 && id != adap->nr) {
+		status = -EBUSY;
+		idr_remove(&i2c_adapter_idr, id);
+	}
+	mutex_unlock(&core_lists);
+	if (status == -EAGAIN)
+		goto retry;
+
+	if (status == 0)
+		status = i2c_register_adapter(adap);
+	return status;
+}
+EXPORT_SYMBOL_GPL(i2c_add_numbered_adapter);
 
 int i2c_del_adapter(struct i2c_adapter *adap)
 {
@@ -302,9 +499,19 @@
 	/* detach any active clients. This must be done first, because
 	 * 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);
+		struct i2c_driver	*driver;
 
-		if ((res=client->driver->detach_client(client))) {
+		client = list_entry(item, struct i2c_client, list);
+		driver = client->driver;
+
+		/* new style, follow standard driver model */
+		if (!driver || is_newstyle_driver(driver)) {
+			i2c_unregister_device(client);
+			continue;
+		}
+
+		/* legacy drivers create and remove clients themselves */
+		if ((res = driver->detach_client(client))) {
 			dev_err(&adap->dev, "detach_client failed for client "
 				"[%s] at address 0x%02x\n", client->name,
 				client->addr);
@@ -314,17 +521,13 @@
 
 	/* clean up the sysfs representation */
 	init_completion(&adap->dev_released);
-	init_completion(&adap->class_dev_released);
-	class_device_unregister(&adap->class_dev);
-	device_remove_file(&adap->dev, &dev_attr_name);
 	device_unregister(&adap->dev);
 	list_del(&adap->list);
 
 	/* wait for sysfs to drop all references */
 	wait_for_completion(&adap->dev_released);
-	wait_for_completion(&adap->class_dev_released);
 
-	/* free dynamically allocated bus id */
+	/* free bus id */
 	idr_remove(&i2c_adapter_idr, adap->nr);
 
 	dev_dbg(&adap->dev, "adapter [%s] unregistered\n", adap->name);
@@ -333,24 +536,42 @@
 	mutex_unlock(&core_lists);
 	return res;
 }
+EXPORT_SYMBOL(i2c_del_adapter);
 
 
-/* -----
- * What follows is the "upwards" interface: commands for talking to clients,
- * which implement the functions to access the physical information of the
- * chips.
+/* ------------------------------------------------------------------------- */
+
+/*
+ * An i2c_driver is used with one or more i2c_client (device) nodes to access
+ * i2c slave chips, on a bus instance associated with some i2c_adapter.  There
+ * are two models for binding the driver to its device:  "new style" drivers
+ * follow the standard Linux driver model and just respond to probe() calls
+ * issued if the driver core sees they match(); "legacy" drivers create device
+ * nodes themselves.
  */
 
 int i2c_register_driver(struct module *owner, struct i2c_driver *driver)
 {
-	struct list_head   *item;
-	struct i2c_adapter *adapter;
 	int res;
 
+	/* new style driver methods can't mix with legacy ones */
+	if (is_newstyle_driver(driver)) {
+		if (driver->attach_adapter || driver->detach_adapter
+				|| driver->detach_client) {
+			printk(KERN_WARNING
+					"i2c-core: driver [%s] is confused\n",
+					driver->driver.name);
+			return -EINVAL;
+		}
+	}
+
 	/* add the driver to the list of i2c drivers in the driver core */
 	driver->driver.owner = owner;
 	driver->driver.bus = &i2c_bus_type;
 
+	/* for new style drivers, when registration returns the driver core
+	 * will have called probe() for all matching-but-unbound devices.
+	 */
 	res = driver_register(&driver->driver);
 	if (res)
 		return res;
@@ -360,10 +581,11 @@
 	list_add_tail(&driver->list,&drivers);
 	pr_debug("i2c-core: driver [%s] registered\n", driver->driver.name);
 
-	/* now look for instances of driver on our adapters */
+	/* legacy drivers scan i2c busses directly */
 	if (driver->attach_adapter) {
-		list_for_each(item,&adapters) {
-			adapter = list_entry(item, struct i2c_adapter, list);
+		struct i2c_adapter *adapter;
+
+		list_for_each_entry(adapter, &adapters, list) {
 			driver->attach_adapter(adapter);
 		}
 	}
@@ -373,16 +595,22 @@
 }
 EXPORT_SYMBOL(i2c_register_driver);
 
-int i2c_del_driver(struct i2c_driver *driver)
+/**
+ * i2c_del_driver - unregister I2C driver
+ * @driver: the driver being unregistered
+ */
+void i2c_del_driver(struct i2c_driver *driver)
 {
 	struct list_head   *item1, *item2, *_n;
 	struct i2c_client  *client;
 	struct i2c_adapter *adap;
 
-	int res = 0;
-
 	mutex_lock(&core_lists);
 
+	/* new-style driver? */
+	if (is_newstyle_driver(driver))
+		goto unregister;
+
 	/* Have a look at each adapter, if clients of this driver are still
 	 * attached. If so, detach them to be able to kill the driver
 	 * afterwards.
@@ -390,11 +618,10 @@
 	list_for_each(item1,&adapters) {
 		adap = list_entry(item1, struct i2c_adapter, list);
 		if (driver->detach_adapter) {
-			if ((res = driver->detach_adapter(adap))) {
+			if (driver->detach_adapter(adap)) {
 				dev_err(&adap->dev, "detach_adapter failed "
 					"for driver [%s]\n",
 					driver->driver.name);
-				goto out_unlock;
 			}
 		} else {
 			list_for_each_safe(item2, _n, &adap->clients) {
@@ -404,25 +631,26 @@
 				dev_dbg(&adap->dev, "detaching client [%s] "
 					"at 0x%02x\n", client->name,
 					client->addr);
-				if ((res = driver->detach_client(client))) {
+				if (driver->detach_client(client)) {
 					dev_err(&adap->dev, "detach_client "
 						"failed for client [%s] at "
 						"0x%02x\n", client->name,
 						client->addr);
-					goto out_unlock;
 				}
 			}
 		}
 	}
 
+ unregister:
 	driver_unregister(&driver->driver);
 	list_del(&driver->list);
 	pr_debug("i2c-core: driver [%s] unregistered\n", driver->driver.name);
 
- out_unlock:
 	mutex_unlock(&core_lists);
-	return 0;
 }
+EXPORT_SYMBOL(i2c_del_driver);
+
+/* ------------------------------------------------------------------------- */
 
 static int __i2c_check_addr(struct i2c_adapter *adapter, unsigned int addr)
 {
@@ -447,6 +675,7 @@
 
 	return rval;
 }
+EXPORT_SYMBOL(i2c_check_addr);
 
 int i2c_attach_client(struct i2c_client *client)
 {
@@ -463,9 +692,15 @@
 	client->usage_count = 0;
 
 	client->dev.parent = &client->adapter->dev;
-	client->dev.driver = &client->driver->driver;
 	client->dev.bus = &i2c_bus_type;
-	client->dev.release = &i2c_client_release;
+
+	if (client->driver)
+		client->dev.driver = &client->driver->driver;
+
+	if (client->driver && !is_newstyle_driver(client->driver))
+		client->dev.release = i2c_client_release;
+	else
+		client->dev.release = i2c_client_dev_release;
 
 	snprintf(&client->dev.bus_id[0], sizeof(client->dev.bus_id),
 		"%d-%04x", i2c_adapter_id(adapter), client->addr);
@@ -474,9 +709,6 @@
 	res = device_register(&client->dev);
 	if (res)
 		goto out_list;
-	res = device_create_file(&client->dev, &dev_attr_client_name);
-	if (res)
-		goto out_unregister;
 	mutex_unlock(&adapter->clist_lock);
 
 	if (adapter->client_register)  {
@@ -489,10 +721,6 @@
 
 	return 0;
 
-out_unregister:
-	init_completion(&client->released); /* Needed? */
-	device_unregister(&client->dev);
-	wait_for_completion(&client->released);
 out_list:
 	list_del(&client->list);
 	dev_err(&adapter->dev, "Failed to attach i2c client %s at 0x%02x "
@@ -501,7 +729,7 @@
 	mutex_unlock(&adapter->clist_lock);
 	return res;
 }
-
+EXPORT_SYMBOL(i2c_attach_client);
 
 int i2c_detach_client(struct i2c_client *client)
 {
@@ -527,7 +755,6 @@
 	mutex_lock(&adapter->clist_lock);
 	list_del(&client->list);
 	init_completion(&client->released);
-	device_remove_file(&client->dev, &dev_attr_client_name);
 	device_unregister(&client->dev);
 	mutex_unlock(&adapter->clist_lock);
 	wait_for_completion(&client->released);
@@ -535,6 +762,7 @@
  out:
 	return res;
 }
+EXPORT_SYMBOL(i2c_detach_client);
 
 static int i2c_inc_use_client(struct i2c_client *client)
 {
@@ -567,6 +795,7 @@
 
 	return 0;
 }
+EXPORT_SYMBOL(i2c_use_client);
 
 int i2c_release_client(struct i2c_client *client)
 {
@@ -581,6 +810,7 @@
 
 	return 0;
 }
+EXPORT_SYMBOL(i2c_release_client);
 
 void i2c_clients_command(struct i2c_adapter *adap, unsigned int cmd, void *arg)
 {
@@ -601,6 +831,7 @@
        }
        mutex_unlock(&adap->clist_lock);
 }
+EXPORT_SYMBOL(i2c_clients_command);
 
 static int __init i2c_init(void)
 {
@@ -609,16 +840,12 @@
 	retval = bus_register(&i2c_bus_type);
 	if (retval)
 		return retval;
-	retval = driver_register(&i2c_adapter_driver);
-	if (retval)
-		return retval;
 	return class_register(&i2c_adapter_class);
 }
 
 static void __exit i2c_exit(void)
 {
 	class_unregister(&i2c_adapter_class);
-	driver_unregister(&i2c_adapter_driver);
 	bus_unregister(&i2c_bus_type);
 }
 
@@ -638,8 +865,9 @@
 #ifdef DEBUG
 		for (ret = 0; ret < num; ret++) {
 			dev_dbg(&adap->dev, "master_xfer[%d] %c, addr=0x%02x, "
-				"len=%d\n", ret, msgs[ret].flags & I2C_M_RD ?
-				'R' : 'W', msgs[ret].addr, msgs[ret].len);
+				"len=%d%s\n", ret, (msgs[ret].flags & I2C_M_RD)
+				? 'R' : 'W', msgs[ret].addr, msgs[ret].len,
+				(msgs[ret].flags & I2C_M_RECV_LEN) ? "+" : "");
 		}
 #endif
 
@@ -653,6 +881,7 @@
 		return -ENOSYS;
 	}
 }
+EXPORT_SYMBOL(i2c_transfer);
 
 int i2c_master_send(struct i2c_client *client,const char *buf ,int count)
 {
@@ -671,6 +900,7 @@
 	   transmitted, else error code. */
 	return (ret == 1) ? count : ret;
 }
+EXPORT_SYMBOL(i2c_master_send);
 
 int i2c_master_recv(struct i2c_client *client, char *buf ,int count)
 {
@@ -690,7 +920,7 @@
 	   transmitted, else error code. */
 	return (ret == 1) ? count : ret;
 }
-
+EXPORT_SYMBOL(i2c_master_recv);
 
 int i2c_control(struct i2c_client *client,
 	unsigned int cmd, unsigned long arg)
@@ -712,6 +942,7 @@
 	}
 	return ret;
 }
+EXPORT_SYMBOL(i2c_control);
 
 /* ----------------------------------------------------
  * the i2c address scanning function
@@ -853,6 +1084,70 @@
 
 	return 0;
 }
+EXPORT_SYMBOL(i2c_probe);
+
+struct i2c_client *
+i2c_new_probed_device(struct i2c_adapter *adap,
+		      struct i2c_board_info *info,
+		      unsigned short const *addr_list)
+{
+	int i;
+
+	/* Stop here if the bus doesn't support probing */
+	if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_READ_BYTE)) {
+		dev_err(&adap->dev, "Probing not supported\n");
+		return NULL;
+	}
+
+	mutex_lock(&adap->clist_lock);
+	for (i = 0; addr_list[i] != I2C_CLIENT_END; i++) {
+		/* Check address validity */
+		if (addr_list[i] < 0x03 || addr_list[i] > 0x77) {
+			dev_warn(&adap->dev, "Invalid 7-bit address "
+				 "0x%02x\n", addr_list[i]);
+			continue;
+		}
+
+		/* Check address availability */
+		if (__i2c_check_addr(adap, addr_list[i])) {
+			dev_dbg(&adap->dev, "Address 0x%02x already in "
+				"use, not probing\n", addr_list[i]);
+			continue;
+		}
+
+		/* Test address responsiveness
+		   The default probe method is a quick write, but it is known
+		   to corrupt the 24RF08 EEPROMs due to a state machine bug,
+		   and could also irreversibly write-protect some EEPROMs, so
+		   for address ranges 0x30-0x37 and 0x50-0x5f, we use a byte
+		   read instead. Also, some bus drivers don't implement
+		   quick write, so we fallback to a byte read it that case
+		   too. */
+		if ((addr_list[i] & ~0x07) == 0x30
+		 || (addr_list[i] & ~0x0f) == 0x50
+		 || !i2c_check_functionality(adap, I2C_FUNC_SMBUS_QUICK)) {
+			if (i2c_smbus_xfer(adap, addr_list[i], 0,
+					   I2C_SMBUS_READ, 0,
+					   I2C_SMBUS_BYTE, NULL) >= 0)
+				break;
+		} else {
+			if (i2c_smbus_xfer(adap, addr_list[i], 0,
+					   I2C_SMBUS_WRITE, 0,
+					   I2C_SMBUS_QUICK, NULL) >= 0)
+				break;
+		}
+	}
+	mutex_unlock(&adap->clist_lock);
+
+	if (addr_list[i] == I2C_CLIENT_END) {
+		dev_dbg(&adap->dev, "Probing failed, no device found\n");
+		return NULL;
+	}
+
+	info->addr = addr_list[i];
+	return i2c_new_device(adap, info);
+}
+EXPORT_SYMBOL_GPL(i2c_new_probed_device);
 
 struct i2c_adapter* i2c_get_adapter(int id)
 {
@@ -866,11 +1161,13 @@
 	mutex_unlock(&core_lists);
 	return adapter;
 }
+EXPORT_SYMBOL(i2c_get_adapter);
 
 void i2c_put_adapter(struct i2c_adapter *adap)
 {
 	module_put(adap->owner);
 }
+EXPORT_SYMBOL(i2c_put_adapter);
 
 /* The SMBus parts */
 
@@ -939,6 +1236,7 @@
 	return i2c_smbus_xfer(client->adapter,client->addr,client->flags,
 	                      value,0,I2C_SMBUS_QUICK,NULL);
 }
+EXPORT_SYMBOL(i2c_smbus_write_quick);
 
 s32 i2c_smbus_read_byte(struct i2c_client *client)
 {
@@ -949,12 +1247,14 @@
 	else
 		return data.byte;
 }
+EXPORT_SYMBOL(i2c_smbus_read_byte);
 
 s32 i2c_smbus_write_byte(struct i2c_client *client, u8 value)
 {
 	return i2c_smbus_xfer(client->adapter,client->addr,client->flags,
 	                      I2C_SMBUS_WRITE, value, I2C_SMBUS_BYTE, NULL);
 }
+EXPORT_SYMBOL(i2c_smbus_write_byte);
 
 s32 i2c_smbus_read_byte_data(struct i2c_client *client, u8 command)
 {
@@ -965,6 +1265,7 @@
 	else
 		return data.byte;
 }
+EXPORT_SYMBOL(i2c_smbus_read_byte_data);
 
 s32 i2c_smbus_write_byte_data(struct i2c_client *client, u8 command, u8 value)
 {
@@ -974,6 +1275,7 @@
 	                      I2C_SMBUS_WRITE,command,
 	                      I2C_SMBUS_BYTE_DATA,&data);
 }
+EXPORT_SYMBOL(i2c_smbus_write_byte_data);
 
 s32 i2c_smbus_read_word_data(struct i2c_client *client, u8 command)
 {
@@ -984,6 +1286,7 @@
 	else
 		return data.word;
 }
+EXPORT_SYMBOL(i2c_smbus_read_word_data);
 
 s32 i2c_smbus_write_word_data(struct i2c_client *client, u8 command, u16 value)
 {
@@ -993,6 +1296,23 @@
 	                      I2C_SMBUS_WRITE,command,
 	                      I2C_SMBUS_WORD_DATA,&data);
 }
+EXPORT_SYMBOL(i2c_smbus_write_word_data);
+
+/* Returns the number of read bytes */
+s32 i2c_smbus_read_block_data(struct i2c_client *client, u8 command,
+			      u8 *values)
+{
+	union i2c_smbus_data data;
+
+	if (i2c_smbus_xfer(client->adapter, client->addr, client->flags,
+	                   I2C_SMBUS_READ, command,
+	                   I2C_SMBUS_BLOCK_DATA, &data))
+		return -1;
+
+	memcpy(values, &data.block[1], data.block[0]);
+	return data.block[0];
+}
+EXPORT_SYMBOL(i2c_smbus_read_block_data);
 
 s32 i2c_smbus_write_block_data(struct i2c_client *client, u8 command,
 			       u8 length, const u8 *values)
@@ -1007,6 +1327,7 @@
 			      I2C_SMBUS_WRITE,command,
 			      I2C_SMBUS_BLOCK_DATA,&data);
 }
+EXPORT_SYMBOL(i2c_smbus_write_block_data);
 
 /* Returns the number of read bytes */
 s32 i2c_smbus_read_i2c_block_data(struct i2c_client *client, u8 command, u8 *values)
@@ -1021,6 +1342,7 @@
 	memcpy(values, &data.block[1], data.block[0]);
 	return data.block[0];
 }
+EXPORT_SYMBOL(i2c_smbus_read_i2c_block_data);
 
 s32 i2c_smbus_write_i2c_block_data(struct i2c_client *client, u8 command,
 				   u8 length, const u8 *values)
@@ -1035,6 +1357,7 @@
 			      I2C_SMBUS_WRITE, command,
 			      I2C_SMBUS_I2C_BLOCK_DATA, &data);
 }
+EXPORT_SYMBOL(i2c_smbus_write_i2c_block_data);
 
 /* Simulate a SMBus command using the i2c protocol
    No checking of parameters is done!  */
@@ -1098,9 +1421,9 @@
 		break;
 	case I2C_SMBUS_BLOCK_DATA:
 		if (read_write == I2C_SMBUS_READ) {
-			dev_err(&adapter->dev, "Block read not supported "
-			       "under I2C emulation!\n");
-			return -1;
+			msg[1].flags |= I2C_M_RECV_LEN;
+			msg[1].len = 1; /* block length will be added by
+					   the underlying bus driver */
 		} else {
 			msg[0].len = data->block[0] + 2;
 			if (msg[0].len > I2C_SMBUS_BLOCK_MAX + 2) {
@@ -1114,9 +1437,21 @@
 		}
 		break;
 	case I2C_SMBUS_BLOCK_PROC_CALL:
-		dev_dbg(&adapter->dev, "Block process call not supported "
-		       "under I2C emulation!\n");
-		return -1;
+		num = 2; /* Another special case */
+		read_write = I2C_SMBUS_READ;
+		if (data->block[0] > I2C_SMBUS_BLOCK_MAX) {
+			dev_err(&adapter->dev, "%s called with invalid "
+				"block proc call size (%d)\n", __FUNCTION__,
+				data->block[0]);
+			return -1;
+		}
+		msg[0].len = data->block[0] + 2;
+		for (i = 1; i < msg[0].len; i++)
+			msgbuf0[i] = data->block[i-1];
+		msg[1].flags |= I2C_M_RECV_LEN;
+		msg[1].len = 1; /* block length will be added by
+				   the underlying bus driver */
+		break;
 	case I2C_SMBUS_I2C_BLOCK_DATA:
 		if (read_write == I2C_SMBUS_READ) {
 			msg[1].len = I2C_SMBUS_BLOCK_MAX;
@@ -1180,6 +1515,11 @@
 				for (i = 0; i < I2C_SMBUS_BLOCK_MAX; i++)
 					data->block[i+1] = msgbuf1[i];
 				break;
+			case I2C_SMBUS_BLOCK_DATA:
+			case I2C_SMBUS_BLOCK_PROC_CALL:
+				for (i = 0; i < msgbuf1[0] + 1; i++)
+					data->block[i] = msgbuf1[i];
+				break;
 		}
 	return 0;
 }
@@ -1204,43 +1544,7 @@
 
 	return res;
 }
-
-
-/* Next four are needed by i2c-isa */
-EXPORT_SYMBOL_GPL(i2c_adapter_dev_release);
-EXPORT_SYMBOL_GPL(i2c_adapter_driver);
-EXPORT_SYMBOL_GPL(i2c_adapter_class);
-EXPORT_SYMBOL_GPL(i2c_bus_type);
-
-EXPORT_SYMBOL(i2c_add_adapter);
-EXPORT_SYMBOL(i2c_del_adapter);
-EXPORT_SYMBOL(i2c_del_driver);
-EXPORT_SYMBOL(i2c_attach_client);
-EXPORT_SYMBOL(i2c_detach_client);
-EXPORT_SYMBOL(i2c_use_client);
-EXPORT_SYMBOL(i2c_release_client);
-EXPORT_SYMBOL(i2c_clients_command);
-EXPORT_SYMBOL(i2c_check_addr);
-
-EXPORT_SYMBOL(i2c_master_send);
-EXPORT_SYMBOL(i2c_master_recv);
-EXPORT_SYMBOL(i2c_control);
-EXPORT_SYMBOL(i2c_transfer);
-EXPORT_SYMBOL(i2c_get_adapter);
-EXPORT_SYMBOL(i2c_put_adapter);
-EXPORT_SYMBOL(i2c_probe);
-
 EXPORT_SYMBOL(i2c_smbus_xfer);
-EXPORT_SYMBOL(i2c_smbus_write_quick);
-EXPORT_SYMBOL(i2c_smbus_read_byte);
-EXPORT_SYMBOL(i2c_smbus_write_byte);
-EXPORT_SYMBOL(i2c_smbus_read_byte_data);
-EXPORT_SYMBOL(i2c_smbus_write_byte_data);
-EXPORT_SYMBOL(i2c_smbus_read_word_data);
-EXPORT_SYMBOL(i2c_smbus_write_word_data);
-EXPORT_SYMBOL(i2c_smbus_write_block_data);
-EXPORT_SYMBOL(i2c_smbus_read_i2c_block_data);
-EXPORT_SYMBOL(i2c_smbus_write_i2c_block_data);
 
 MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>");
 MODULE_DESCRIPTION("I2C-Bus main module");
diff --git a/drivers/i2c/i2c-core.h b/drivers/i2c/i2c-core.h
new file mode 100644
index 0000000..cd5bff8
--- /dev/null
+++ b/drivers/i2c/i2c-core.h
@@ -0,0 +1,31 @@
+/*
+ * i2c-core.h - interfaces internal to the I2C framework
+ *
+ * This program is free software; you can redistribute it and/or 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.
+ */
+
+struct i2c_devinfo {
+	struct list_head	list;
+	int			busnum;
+	struct i2c_board_info	board_info;
+};
+
+/* board_lock protects board_list and first_dynamic_bus_num.
+ * only i2c core components are allowed to use these symbols.
+ */
+extern struct mutex	__i2c_board_lock;
+extern struct list_head	__i2c_board_list;
+extern int		__i2c_first_dynamic_bus_num;
+
diff --git a/drivers/ide/cris/ide-cris.c b/drivers/ide/cris/ide-cris.c
index 556455f..5e8efc8 100644
--- a/drivers/ide/cris/ide-cris.c
+++ b/drivers/ide/cris/ide-cris.c
@@ -730,7 +730,7 @@
 
 	if (speed >= XFER_PIO_0 && speed <= XFER_PIO_4) {
 		tune_cris_ide(drive, speed - XFER_PIO_0);
-		return 0;
+		return ide_config_drive_speed(drive, speed);
 	}
 
 	switch(speed)
@@ -760,7 +760,8 @@
 			hold = ATA_DMA2_HOLD;
 			break;
 		default:
-			return 0;
+			BUG();
+			break;
 	}
 
 	if (speed >= XFER_UDMA_0)
@@ -768,7 +769,7 @@
 	else
 		cris_ide_set_speed(TYPE_DMA, 0, strobe, hold);
 
-	return 0;
+	return ide_config_drive_speed(drive, speed);
 }
 
 void __init
@@ -821,7 +822,6 @@
 		hwif->udma_four = 0;
 		hwif->ultra_mask = cris_ultra_mask;
 		hwif->mwdma_mask = 0x07; /* Multiword DMA 0-2 */
-		hwif->swdma_mask = 0x07; /* Singleword DMA 0-2 */
 		hwif->autodma = 1;
 		hwif->drives[0].autodma = 1;
 		hwif->drives[1].autodma = 1;
@@ -1010,7 +1010,6 @@
 		return 0;
 
 	speed_cris_ide(drive, speed);
-	ide_config_drive_speed(drive, speed);
 
 	return ide_dma_enable(drive);
 }
diff --git a/drivers/ide/legacy/ide-cs.c b/drivers/ide/legacy/ide-cs.c
index b08c37c..c6522a6 100644
--- a/drivers/ide/legacy/ide-cs.c
+++ b/drivers/ide/legacy/ide-cs.c
@@ -401,6 +401,7 @@
 	PCMCIA_DEVICE_PROD_ID12("TOSHIBA", "MK2001MPL", 0xb4585a1a, 0x3489e003),
 	PCMCIA_DEVICE_PROD_ID1("TRANSCEND    512M   ", 0xd0909443),
 	PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS1GCF80", 0x709b1bf1, 0x2a54d4b1),
+	PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS2GCF120", 0x709b1bf1, 0x969aa4f2),
 	PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS4GCF120", 0x709b1bf1, 0xf54a91c8),
 	PCMCIA_DEVICE_PROD_ID12("WIT", "IDE16", 0x244e5994, 0x3e232852),
 	PCMCIA_DEVICE_PROD_ID12("WEIDA", "TWTTI", 0xcc7cf69c, 0x212bb918),
diff --git a/drivers/ide/pci/aec62xx.c b/drivers/ide/pci/aec62xx.c
index 990eafe..73bdf64 100644
--- a/drivers/ide/pci/aec62xx.c
+++ b/drivers/ide/pci/aec62xx.c
@@ -1,7 +1,8 @@
 /*
- * linux/drivers/ide/pci/aec62xx.c		Version 0.11	March 27, 2002
+ * linux/drivers/ide/pci/aec62xx.c		Version 0.21	Apr 21, 2007
  *
  * Copyright (C) 1999-2002	Andre Hedrick <andre@linux-ide.org>
+ * Copyright (C) 2007		MontaVista Software, Inc. <source@mvista.com>
  *
  */
 
@@ -193,18 +194,8 @@
 
 static void aec62xx_tune_drive (ide_drive_t *drive, u8 pio)
 {
-	u8 speed = 0;
-	u8 new_pio = XFER_PIO_0 + ide_get_best_pio_mode(drive, 255, 5, NULL);
-
-	switch(pio) {
-		case 5:		speed = new_pio; break;
-		case 4:		speed = XFER_PIO_4; break;
-		case 3:		speed = XFER_PIO_3; break;
-		case 2:		speed = XFER_PIO_2; break;
-		case 1:		speed = XFER_PIO_1; break;
-		default:	speed = XFER_PIO_0; break;
-	}
-	(void) aec62xx_tune_chipset(drive, speed);
+	pio = ide_get_best_pio_mode(drive, pio, 4, NULL);
+	(void) aec62xx_tune_chipset(drive, pio + XFER_PIO_0);
 }
 
 static int aec62xx_config_drive_xfer_rate (ide_drive_t *drive)
@@ -213,7 +204,7 @@
 		return 0;
 
 	if (ide_use_fast_pio(drive))
-		aec62xx_tune_drive(drive, 5);
+		aec62xx_tune_drive(drive, 255);
 
 	return -1;
 }
@@ -288,11 +279,10 @@
 
 	hwif->ultra_mask = 0x7f;
 	hwif->mwdma_mask = 0x07;
-	hwif->swdma_mask = 0x07;
 
 	hwif->ide_dma_check	= &aec62xx_config_drive_xfer_rate;
 	hwif->ide_dma_lostirq	= &aec62xx_irq_timeout;
-	hwif->ide_dma_timeout	= &aec62xx_irq_timeout;
+
 	if (!noautodma)
 		hwif->autodma = 1;
 	hwif->drives[0].autodma = hwif->autodma;
diff --git a/drivers/ide/pci/alim15x3.c b/drivers/ide/pci/alim15x3.c
index 83e0aa6..946a127 100644
--- a/drivers/ide/pci/alim15x3.c
+++ b/drivers/ide/pci/alim15x3.c
@@ -534,7 +534,7 @@
 	struct hd_driveid *id	= drive->id;
 
 	if ((m5229_revision<=0x20) && (drive->media!=ide_disk))
-		goto no_dma_set;
+		goto ata_pio;
 
 	drive->init_speed = 0;
 
@@ -555,20 +555,19 @@
 			    (id->dma_1word & hwif->swdma_mask)) {
 				/* Force if Capable regular DMA modes */
 				if (!config_chipset_for_dma(drive))
-					goto no_dma_set;
+					goto ata_pio;
 			}
 		} else if (__ide_dma_good_drive(drive) &&
 			   (id->eide_dma_time < 150)) {
 			/* Consult the list of known "good" drives */
 			if (!config_chipset_for_dma(drive))
-				goto no_dma_set;
+				goto ata_pio;
 		} else {
 			goto ata_pio;
 		}
 	} else {
 ata_pio:
 		hwif->tuneproc(drive, 255);
-no_dma_set:
 		return -1;
 	}
 
diff --git a/drivers/ide/pci/cmd64x.c b/drivers/ide/pci/cmd64x.c
index 561197f..77f51ab 100644
--- a/drivers/ide/pci/cmd64x.c
+++ b/drivers/ide/pci/cmd64x.c
@@ -1,10 +1,7 @@
-/* $Id: cmd64x.c,v 1.21 2000/01/30 23:23:16
- *
- * linux/drivers/ide/pci/cmd64x.c		Version 1.42	Feb 8, 2007
+/*
+ * linux/drivers/ide/pci/cmd64x.c		Version 1.47	Mar 19, 2007
  *
  * cmd64x.c: Enable interrupts at initialization time on Ultra/PCI machines.
- *           Note, this driver is not used at all on other systems because
- *           there the "BIOS" has done all of the following already.
  *           Due to massive hardware bugs, UltraDMA is only supported
  *           on the 646U2 and not on the 646U.
  *
@@ -39,11 +36,12 @@
  * CMD64x specific registers definition.
  */
 #define CFR		0x50
-#define   CFR_INTR_CH0		0x02
+#define   CFR_INTR_CH0		0x04
 #define CNTRL		0x51
-#define	  CNTRL_DIS_RA0		0x40
-#define   CNTRL_DIS_RA1		0x80
-#define	  CNTRL_ENA_2ND		0x08
+#define   CNTRL_ENA_1ST 	0x04
+#define   CNTRL_ENA_2ND 	0x08
+#define   CNTRL_DIS_RA0 	0x40
+#define   CNTRL_DIS_RA1 	0x80
 
 #define	CMDTIM		0x52
 #define	ARTTIM0		0x53
@@ -90,86 +88,67 @@
 static char * print_cmd64x_get_info (char *buf, struct pci_dev *dev, int index)
 {
 	char *p = buf;
-
-	u8 reg53 = 0, reg54 = 0, reg55 = 0, reg56 = 0;	/* primary */
-	u8 reg57 = 0, reg58 = 0, reg5b;			/* secondary */
 	u8 reg72 = 0, reg73 = 0;			/* primary */
 	u8 reg7a = 0, reg7b = 0;			/* secondary */
-	u8 reg50 = 0, reg71 = 0;			/* extra */
+	u8 reg50 = 1, reg51 = 1, reg57 = 0, reg71 = 0;	/* extra */
+	u8 rev = 0;
 
 	p += sprintf(p, "\nController: %d\n", index);
-	p += sprintf(p, "CMD%x Chipset.\n", dev->device);
+	p += sprintf(p, "PCI-%x Chipset.\n", dev->device);
+
 	(void) pci_read_config_byte(dev, CFR,       &reg50);
-	(void) pci_read_config_byte(dev, ARTTIM0,   &reg53);
-	(void) pci_read_config_byte(dev, DRWTIM0,   &reg54);
-	(void) pci_read_config_byte(dev, ARTTIM1,   &reg55);
-	(void) pci_read_config_byte(dev, DRWTIM1,   &reg56);
-	(void) pci_read_config_byte(dev, ARTTIM2,   &reg57);
-	(void) pci_read_config_byte(dev, DRWTIM2,   &reg58);
-	(void) pci_read_config_byte(dev, DRWTIM3,   &reg5b);
+	(void) pci_read_config_byte(dev, CNTRL,     &reg51);
+	(void) pci_read_config_byte(dev, ARTTIM23,  &reg57);
 	(void) pci_read_config_byte(dev, MRDMODE,   &reg71);
 	(void) pci_read_config_byte(dev, BMIDESR0,  &reg72);
 	(void) pci_read_config_byte(dev, UDIDETCR0, &reg73);
 	(void) pci_read_config_byte(dev, BMIDESR1,  &reg7a);
 	(void) pci_read_config_byte(dev, UDIDETCR1, &reg7b);
 
-	p += sprintf(p, "--------------- Primary Channel "
-			"---------------- Secondary Channel "
-			"-------------\n");
-	p += sprintf(p, "                %sabled           "
-			"              %sabled\n",
-		(reg72&0x80)?"dis":" en",
-		(reg7a&0x80)?"dis":" en");
-	p += sprintf(p, "--------------- drive0 "
-		"--------- drive1 -------- drive0 "
-		"---------- drive1 ------\n");
-	p += sprintf(p, "DMA enabled:    %s              %s"
-			"             %s               %s\n",
-		(reg72&0x20)?"yes":"no ", (reg72&0x40)?"yes":"no ",
-		(reg7a&0x20)?"yes":"no ", (reg7a&0x40)?"yes":"no ");
+	/* PCI0643/6 originally didn't have the primary channel enable bit */
+	(void) pci_read_config_byte(dev, PCI_REVISION_ID, &rev);
+	if ((dev->device == PCI_DEVICE_ID_CMD_643) ||
+	    (dev->device == PCI_DEVICE_ID_CMD_646 && rev < 3))
+		reg51 |= CNTRL_ENA_1ST;
 
-	p += sprintf(p, "DMA Mode:       %s(%s)          %s(%s)",
-		(reg72&0x20)?((reg73&0x01)?"UDMA":" DMA"):" PIO",
-		(reg72&0x20)?(
-			((reg73&0x30)==0x30)?(((reg73&0x35)==0x35)?"3":"0"):
-			((reg73&0x20)==0x20)?(((reg73&0x25)==0x25)?"3":"1"):
-			((reg73&0x10)==0x10)?(((reg73&0x15)==0x15)?"4":"2"):
-			((reg73&0x00)==0x00)?(((reg73&0x05)==0x05)?"5":"2"):
-			"X"):"?",
-		(reg72&0x40)?((reg73&0x02)?"UDMA":" DMA"):" PIO",
-		(reg72&0x40)?(
-			((reg73&0xC0)==0xC0)?(((reg73&0xC5)==0xC5)?"3":"0"):
-			((reg73&0x80)==0x80)?(((reg73&0x85)==0x85)?"3":"1"):
-			((reg73&0x40)==0x40)?(((reg73&0x4A)==0x4A)?"4":"2"):
-			((reg73&0x00)==0x00)?(((reg73&0x0A)==0x0A)?"5":"2"):
-			"X"):"?");
-	p += sprintf(p, "         %s(%s)           %s(%s)\n",
-		(reg7a&0x20)?((reg7b&0x01)?"UDMA":" DMA"):" PIO",
-		(reg7a&0x20)?(
-			((reg7b&0x30)==0x30)?(((reg7b&0x35)==0x35)?"3":"0"):
-			((reg7b&0x20)==0x20)?(((reg7b&0x25)==0x25)?"3":"1"):
-			((reg7b&0x10)==0x10)?(((reg7b&0x15)==0x15)?"4":"2"):
-			((reg7b&0x00)==0x00)?(((reg7b&0x05)==0x05)?"5":"2"):
-			"X"):"?",
-		(reg7a&0x40)?((reg7b&0x02)?"UDMA":" DMA"):" PIO",
-		(reg7a&0x40)?(
-			((reg7b&0xC0)==0xC0)?(((reg7b&0xC5)==0xC5)?"3":"0"):
-			((reg7b&0x80)==0x80)?(((reg7b&0x85)==0x85)?"3":"1"):
-			((reg7b&0x40)==0x40)?(((reg7b&0x4A)==0x4A)?"4":"2"):
-			((reg7b&0x00)==0x00)?(((reg7b&0x0A)==0x0A)?"5":"2"):
-			"X"):"?" );
-	p += sprintf(p, "PIO Mode:       %s                %s"
-			"               %s                 %s\n",
-			"?", "?", "?", "?");
-	p += sprintf(p, "                %s                     %s\n",
-		(reg50 & CFR_INTR_CH0) ? "interrupting" : "polling     ",
-		(reg57 & ARTTIM23_INTR_CH1) ? "interrupting" : "polling");
-	p += sprintf(p, "                %s                          %s\n",
-		(reg71 & MRDMODE_INTR_CH0) ? "pending" : "clear  ",
-		(reg71 & MRDMODE_INTR_CH1) ? "pending" : "clear");
-	p += sprintf(p, "                %s                          %s\n",
-		(reg71 & MRDMODE_BLK_CH0) ? "blocked" : "enabled",
-		(reg71 & MRDMODE_BLK_CH1) ? "blocked" : "enabled");
+	p += sprintf(p, "---------------- Primary Channel "
+			"---------------- Secondary Channel ------------\n");
+	p += sprintf(p, "                 %s                         %s\n",
+		 (reg51 & CNTRL_ENA_1ST) ? "enabled " : "disabled",
+		 (reg51 & CNTRL_ENA_2ND) ? "enabled " : "disabled");
+	p += sprintf(p, "---------------- drive0 --------- drive1 "
+			"-------- drive0 --------- drive1 ------\n");
+	p += sprintf(p, "DMA enabled:     %s              %s"
+			"             %s              %s\n",
+		(reg72 & 0x20) ? "yes" : "no ", (reg72 & 0x40) ? "yes" : "no ",
+		(reg7a & 0x20) ? "yes" : "no ", (reg7a & 0x40) ? "yes" : "no ");
+	p += sprintf(p, "UltraDMA mode:   %s (%c)          %s (%c)",
+		( reg73 & 0x01) ? " on" : "off",
+		((reg73 & 0x30) == 0x30) ? ((reg73 & 0x04) ? '3' : '0') :
+		((reg73 & 0x30) == 0x20) ? ((reg73 & 0x04) ? '3' : '1') :
+		((reg73 & 0x30) == 0x10) ? ((reg73 & 0x04) ? '4' : '2') :
+		((reg73 & 0x30) == 0x00) ? ((reg73 & 0x04) ? '5' : '2') : '?',
+		( reg73 & 0x02) ? " on" : "off",
+		((reg73 & 0xC0) == 0xC0) ? ((reg73 & 0x08) ? '3' : '0') :
+		((reg73 & 0xC0) == 0x80) ? ((reg73 & 0x08) ? '3' : '1') :
+		((reg73 & 0xC0) == 0x40) ? ((reg73 & 0x08) ? '4' : '2') :
+		((reg73 & 0xC0) == 0x00) ? ((reg73 & 0x08) ? '5' : '2') : '?');
+	p += sprintf(p, "         %s (%c)          %s (%c)\n",
+		( reg7b & 0x01) ? " on" : "off",
+		((reg7b & 0x30) == 0x30) ? ((reg7b & 0x04) ? '3' : '0') :
+		((reg7b & 0x30) == 0x20) ? ((reg7b & 0x04) ? '3' : '1') :
+		((reg7b & 0x30) == 0x10) ? ((reg7b & 0x04) ? '4' : '2') :
+		((reg7b & 0x30) == 0x00) ? ((reg7b & 0x04) ? '5' : '2') : '?',
+		( reg7b & 0x02) ? " on" : "off",
+		((reg7b & 0xC0) == 0xC0) ? ((reg7b & 0x08) ? '3' : '0') :
+		((reg7b & 0xC0) == 0x80) ? ((reg7b & 0x08) ? '3' : '1') :
+		((reg7b & 0xC0) == 0x40) ? ((reg7b & 0x08) ? '4' : '2') :
+		((reg7b & 0xC0) == 0x00) ? ((reg7b & 0x08) ? '5' : '2') : '?');
+	p += sprintf(p, "Interrupt:       %s, %s                 %s, %s\n",
+		(reg71 & MRDMODE_BLK_CH0  ) ? "blocked" : "enabled",
+		(reg50 & CFR_INTR_CH0	  ) ? "pending" : "clear  ",
+		(reg71 & MRDMODE_BLK_CH1  ) ? "blocked" : "enabled",
+		(reg57 & ARTTIM23_INTR_CH1) ? "pending" : "clear  ");
 
 	return (char *)p;
 }
@@ -179,7 +158,6 @@
 	char *p = buffer;
 	int i;
 
-	p += sprintf(p, "\n");
 	for (i = 0; i < n_cmd_devs; i++) {
 		struct pci_dev *dev	= cmd_devs[i];
 		p = print_cmd64x_get_info(p, dev, i);
@@ -195,116 +173,103 @@
 }
 
 /*
- * This routine writes the prepared setup/active/recovery counts
- * for a drive into the cmd646 chipset registers to active them.
+ * This routine calculates active/recovery counts and then writes them into
+ * the chipset registers.
  */
-static void program_drive_counts (ide_drive_t *drive, int setup_count, int active_count, int recovery_count)
+static void program_cycle_times (ide_drive_t *drive, int cycle_time, int active_time)
 {
-	unsigned long flags;
-	struct pci_dev *dev = HWIF(drive)->pci_dev;
-	ide_drive_t *drives = HWIF(drive)->drives;
-	u8 temp_b;
-	static const u8 setup_counts[] = {0x40, 0x40, 0x40, 0x80, 0, 0xc0};
-	static const u8 recovery_counts[] =
+	struct pci_dev *dev	= HWIF(drive)->pci_dev;
+	int clock_time		= 1000 / system_bus_clock();
+	u8  cycle_count, active_count, recovery_count, drwtim;
+	static const u8 recovery_values[] =
 		{15, 15, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0};
-	static const u8 arttim_regs[2][2] = {
-			{ ARTTIM0, ARTTIM1 },
-			{ ARTTIM23, ARTTIM23 }
-		};
-	static const u8 drwtim_regs[2][2] = {
-			{ DRWTIM0, DRWTIM1 },
-			{ DRWTIM2, DRWTIM3 }
-		};
-	int channel = (int) HWIF(drive)->channel;
-	int slave = (drives != drive);  /* Is this really the best way to determine this?? */
+	static const u8 drwtim_regs[4] = {DRWTIM0, DRWTIM1, DRWTIM2, DRWTIM3};
 
-	cmdprintk("program_drive_count parameters = s(%d),a(%d),r(%d),p(%d)\n",
-		setup_count, active_count, recovery_count, drive->present);
-	/*
-	 * Set up address setup count registers.
-	 * Primary interface has individual count/timing registers for
-	 * each drive.  Secondary interface has one common set of registers,
-	 * for address setup so we merge these timings, using the slowest
-	 * value.
-	 */
-	if (channel) {
-		drive->drive_data = setup_count;
-		setup_count = max(drives[0].drive_data,
-					drives[1].drive_data);
-		cmdprintk("Secondary interface, setup_count = %d\n",
-					setup_count);
-	}
+	cmdprintk("program_cycle_times parameters: total=%d, active=%d\n",
+		  cycle_time, active_time);
+
+	cycle_count	= quantize_timing( cycle_time, clock_time);
+	active_count	= quantize_timing(active_time, clock_time);
+	recovery_count	= cycle_count - active_count;
 
 	/*
-	 * Convert values to internal chipset representation
+	 * In case we've got too long recovery phase, try to lengthen
+	 * the active phase
 	 */
-	setup_count = (setup_count > 5) ? 0xc0 : (int) setup_counts[setup_count];
-	active_count &= 0xf; /* Remember, max value is 16 */
-	recovery_count = (int) recovery_counts[recovery_count];
-
-	cmdprintk("Final values = %d,%d,%d\n",
-		setup_count, active_count, recovery_count);
-
-	/*
-	 * Now that everything is ready, program the new timings
-	 */
-	local_irq_save(flags);
-	/*
-	 * Program the address_setup clocks into ARTTIM reg,
-	 * and then the active/recovery counts into the DRWTIM reg
-	 */
-	(void) pci_read_config_byte(dev, arttim_regs[channel][slave], &temp_b);
-	(void) pci_write_config_byte(dev, arttim_regs[channel][slave],
-		((u8) setup_count) | (temp_b & 0x3f));
-	(void) pci_write_config_byte(dev, drwtim_regs[channel][slave],
-		(u8) ((active_count << 4) | recovery_count));
-	cmdprintk ("Write %x to %x\n",
-		((u8) setup_count) | (temp_b & 0x3f),
-		arttim_regs[channel][slave]);
-	cmdprintk ("Write %x to %x\n",
-		(u8) ((active_count << 4) | recovery_count),
-		drwtim_regs[channel][slave]);
-	local_irq_restore(flags);
-}
-
-/*
- * This routine selects drive's best PIO mode, calculates setup/active/recovery
- * counts, and then writes them into the chipset registers.
- */
-static u8 cmd64x_tune_pio (ide_drive_t *drive, u8 mode_wanted)
-{
-	int setup_time, active_time, cycle_time;
-	u8  cycle_count, setup_count, active_count, recovery_count;
-	u8  pio_mode;
-	int clock_time = 1000 / system_bus_clock();
-	ide_pio_data_t pio;
-
-	pio_mode = ide_get_best_pio_mode(drive, mode_wanted, 5, &pio);
-	cycle_time = pio.cycle_time;
-
-	setup_time  = ide_pio_timings[pio_mode].setup_time;
-	active_time = ide_pio_timings[pio_mode].active_time;
-
-	setup_count  = quantize_timing( setup_time, clock_time);
-	cycle_count  = quantize_timing( cycle_time, clock_time);
-	active_count = quantize_timing(active_time, clock_time);
-
-	recovery_count = cycle_count - active_count;
-	/* program_drive_counts() takes care of zero recovery cycles */
 	if (recovery_count > 16) {
 		active_count += recovery_count - 16;
 		recovery_count = 16;
 	}
-	if (active_count > 16)
-		active_count = 16; /* maximum allowed by cmd64x */
+	if (active_count > 16)		/* shouldn't actually happen... */
+	 	active_count = 16;
 
-	program_drive_counts (drive, setup_count, active_count, recovery_count);
+	cmdprintk("Final counts: total=%d, active=%d, recovery=%d\n",
+		  cycle_count, active_count, recovery_count);
 
-	cmdprintk("%s: PIO mode wanted %d, selected %d (%dns)%s, "
-		"clocks=%d/%d/%d\n",
-		drive->name, mode_wanted, pio_mode, cycle_time,
-		pio.overridden ? " (overriding vendor mode)" : "",
-		setup_count, active_count, recovery_count);
+	/*
+	 * Convert values to internal chipset representation
+	 */
+	recovery_count = recovery_values[recovery_count];
+ 	active_count  &= 0x0f;
+
+	/* Program the active/recovery counts into the DRWTIM register */
+	drwtim = (active_count << 4) | recovery_count;
+	(void) pci_write_config_byte(dev, drwtim_regs[drive->dn], drwtim);
+	cmdprintk("Write 0x%02x to reg 0x%x\n", drwtim, drwtim_regs[drive->dn]);
+}
+
+/*
+ * This routine selects drive's best PIO mode and writes into the chipset
+ * registers setup/active/recovery timings.
+ */
+static u8 cmd64x_tune_pio (ide_drive_t *drive, u8 mode_wanted)
+{
+	ide_hwif_t *hwif	= HWIF(drive);
+	struct pci_dev *dev	= hwif->pci_dev;
+	ide_pio_data_t pio;
+	u8 pio_mode, setup_count, arttim = 0;
+	static const u8 setup_values[] = {0x40, 0x40, 0x40, 0x80, 0, 0xc0};
+	static const u8 arttim_regs[4] = {ARTTIM0, ARTTIM1, ARTTIM23, ARTTIM23};
+	pio_mode = ide_get_best_pio_mode(drive, mode_wanted, 5, &pio);
+
+	cmdprintk("%s: PIO mode wanted %d, selected %d (%d ns)%s\n",
+		  drive->name, mode_wanted, pio_mode, pio.cycle_time,
+		  pio.overridden ? " (overriding vendor mode)" : "");
+
+	program_cycle_times(drive, pio.cycle_time,
+			    ide_pio_timings[pio_mode].active_time);
+
+	setup_count = quantize_timing(ide_pio_timings[pio_mode].setup_time,
+				      1000 / system_bus_clock());
+
+	/*
+	 * The primary channel has individual address setup timing registers
+	 * for each drive and the hardware selects the slowest timing itself.
+	 * The secondary channel has one common register and we have to select
+	 * the slowest address setup timing ourselves.
+	 */
+	if (hwif->channel) {
+		ide_drive_t *drives = hwif->drives;
+
+		drive->drive_data = setup_count;
+		setup_count = max(drives[0].drive_data, drives[1].drive_data);
+	}
+
+	if (setup_count > 5)		/* shouldn't actually happen... */
+		setup_count = 5;
+	cmdprintk("Final address setup count: %d\n", setup_count);
+
+	/*
+	 * Program the address setup clocks into the ARTTIM registers.
+	 * Avoid clearing the secondary channel's interrupt bit.
+	 */
+	(void) pci_read_config_byte (dev, arttim_regs[drive->dn], &arttim);
+	if (hwif->channel)
+		arttim &= ~ARTTIM23_INTR_CH1;
+	arttim &= ~0xc0;
+	arttim |= setup_values[setup_count];
+	(void) pci_write_config_byte(dev, arttim_regs[drive->dn], arttim);
+	cmdprintk("Write 0x%02x to reg 0x%x\n", arttim, arttim_regs[drive->dn]);
 
 	return pio_mode;
 }
@@ -376,61 +341,64 @@
 	return mode;
 }
 
-static int cmd64x_tune_chipset (ide_drive_t *drive, u8 xferspeed)
+static int cmd64x_tune_chipset (ide_drive_t *drive, u8 speed)
 {
 	ide_hwif_t *hwif	= HWIF(drive);
 	struct pci_dev *dev	= hwif->pci_dev;
+	u8 unit			= drive->dn & 0x01;
+	u8 regU = 0, pciU	= hwif->channel ? UDIDETCR1 : UDIDETCR0;
 
-	u8 unit			= (drive->select.b.unit & 0x01);
-	u8 regU = 0, pciU	= (hwif->channel) ? UDIDETCR1 : UDIDETCR0;
-	u8 regD = 0, pciD	= (hwif->channel) ? BMIDESR1 : BMIDESR0;
-
-	u8 speed	= ide_rate_filter(cmd64x_ratemask(drive), xferspeed);
+	speed = ide_rate_filter(cmd64x_ratemask(drive), speed);
 
 	if (speed >= XFER_SW_DMA_0) {
-		(void) pci_read_config_byte(dev, pciD, &regD);
 		(void) pci_read_config_byte(dev, pciU, &regU);
-		regD &= ~(unit ? 0x40 : 0x20);
 		regU &= ~(unit ? 0xCA : 0x35);
-		(void) pci_write_config_byte(dev, pciD, regD);
-		(void) pci_write_config_byte(dev, pciU, regU);
-		(void) pci_read_config_byte(dev, pciD, &regD);
-		(void) pci_read_config_byte(dev, pciU, &regU);
 	}
 
 	switch(speed) {
-		case XFER_UDMA_5:	regU |= (unit ? 0x0A : 0x05); break;
-		case XFER_UDMA_4:	regU |= (unit ? 0x4A : 0x15); break;
-		case XFER_UDMA_3:	regU |= (unit ? 0x8A : 0x25); break;
-		case XFER_UDMA_2:	regU |= (unit ? 0x42 : 0x11); break;
-		case XFER_UDMA_1:	regU |= (unit ? 0x82 : 0x21); break;
-		case XFER_UDMA_0:	regU |= (unit ? 0xC2 : 0x31); break;
-		case XFER_MW_DMA_2:	regD |= (unit ? 0x40 : 0x10); break;
-		case XFER_MW_DMA_1:	regD |= (unit ? 0x80 : 0x20); break;
-		case XFER_MW_DMA_0:	regD |= (unit ? 0xC0 : 0x30); break;
-		case XFER_SW_DMA_2:	regD |= (unit ? 0x40 : 0x10); break;
-		case XFER_SW_DMA_1:	regD |= (unit ? 0x80 : 0x20); break;
-		case XFER_SW_DMA_0:	regD |= (unit ? 0xC0 : 0x30); break;
-		case XFER_PIO_5:
-		case XFER_PIO_4:
-		case XFER_PIO_3:
-		case XFER_PIO_2:
-		case XFER_PIO_1:
-		case XFER_PIO_0:
-			(void) cmd64x_tune_pio(drive, speed - XFER_PIO_0);
-			break;
-
-		default:
-			return 1;
+	case XFER_UDMA_5:
+		regU |= unit ? 0x0A : 0x05;
+		break;
+	case XFER_UDMA_4:
+		regU |= unit ? 0x4A : 0x15;
+		break;
+	case XFER_UDMA_3:
+		regU |= unit ? 0x8A : 0x25;
+		break;
+	case XFER_UDMA_2:
+		regU |= unit ? 0x42 : 0x11;
+		break;
+	case XFER_UDMA_1:
+		regU |= unit ? 0x82 : 0x21;
+		break;
+	case XFER_UDMA_0:
+		regU |= unit ? 0xC2 : 0x31;
+		break;
+	case XFER_MW_DMA_2:
+		program_cycle_times(drive, 120, 70);
+		break;
+	case XFER_MW_DMA_1:
+		program_cycle_times(drive, 150, 80);
+		break;
+	case XFER_MW_DMA_0:
+		program_cycle_times(drive, 480, 215);
+		break;
+	case XFER_PIO_5:
+	case XFER_PIO_4:
+	case XFER_PIO_3:
+	case XFER_PIO_2:
+	case XFER_PIO_1:
+	case XFER_PIO_0:
+		(void) cmd64x_tune_pio(drive, speed - XFER_PIO_0);
+		break;
+	default:
+		return 1;
 	}
 
-	if (speed >= XFER_SW_DMA_0) {
+	if (speed >= XFER_SW_DMA_0)
 		(void) pci_write_config_byte(dev, pciU, regU);
-		regD |= (unit ? 0x40 : 0x20);
-		(void) pci_write_config_byte(dev, pciD, regD);
-	}
 
-	return (ide_config_drive_speed(drive, speed));
+	return ide_config_drive_speed(drive, speed);
 }
 
 static int config_chipset_for_dma (ide_drive_t *drive)
@@ -457,67 +425,80 @@
 	return -1;
 }
 
-static int cmd64x_alt_dma_status (struct pci_dev *dev)
+static int cmd648_ide_dma_end (ide_drive_t *drive)
 {
-	switch(dev->device) {
-		case PCI_DEVICE_ID_CMD_648:
-		case PCI_DEVICE_ID_CMD_649:
-			return 1;
-		default:
-			break;
-	}
-	return 0;
+	ide_hwif_t *hwif	= HWIF(drive);
+	int err			= __ide_dma_end(drive);
+	u8  irq_mask		= hwif->channel ? MRDMODE_INTR_CH1 :
+						  MRDMODE_INTR_CH0;
+	u8  mrdmode		= inb(hwif->dma_master + 0x01);
+
+	/* clear the interrupt bit */
+	outb(mrdmode | irq_mask, hwif->dma_master + 0x01);
+
+	return err;
 }
 
 static int cmd64x_ide_dma_end (ide_drive_t *drive)
 {
-	u8 dma_stat = 0, dma_cmd = 0;
 	ide_hwif_t *hwif	= HWIF(drive);
 	struct pci_dev *dev	= hwif->pci_dev;
+	int irq_reg		= hwif->channel ? ARTTIM23 : CFR;
+	u8  irq_mask		= hwif->channel ? ARTTIM23_INTR_CH1 :
+						  CFR_INTR_CH0;
+	u8  irq_stat		= 0;
+	int err			= __ide_dma_end(drive);
 
-	drive->waiting_for_dma = 0;
-	/* read DMA command state */
-	dma_cmd = inb(hwif->dma_command);
-	/* stop DMA */
-	outb(dma_cmd & ~1, hwif->dma_command);
-	/* get DMA status */
-	dma_stat = inb(hwif->dma_status);
-	/* clear the INTR & ERROR bits */
-	outb(dma_stat | 6, hwif->dma_status);
-	if (cmd64x_alt_dma_status(dev)) {
-		u8 dma_intr	= 0;
-		u8 dma_mask	= (hwif->channel) ? ARTTIM23_INTR_CH1 :
-						    CFR_INTR_CH0;
-		u8 dma_reg	= (hwif->channel) ? ARTTIM2 : CFR;
-		(void) pci_read_config_byte(dev, dma_reg, &dma_intr);
-		/* clear the INTR bit */
-		(void) pci_write_config_byte(dev, dma_reg, dma_intr|dma_mask);
-	}
-	/* purge DMA mappings */
-	ide_destroy_dmatable(drive);
-	/* verify good DMA status */
-	return (dma_stat & 7) != 4;
+	(void) pci_read_config_byte(dev, irq_reg, &irq_stat);
+	/* clear the interrupt bit */
+	(void) pci_write_config_byte(dev, irq_reg, irq_stat | irq_mask);
+
+	return err;
+}
+
+static int cmd648_ide_dma_test_irq (ide_drive_t *drive)
+{
+	ide_hwif_t *hwif	= HWIF(drive);
+	u8 irq_mask		= hwif->channel ? MRDMODE_INTR_CH1 :
+						  MRDMODE_INTR_CH0;
+	u8 dma_stat		= inb(hwif->dma_status);
+	u8 mrdmode		= inb(hwif->dma_master + 0x01);
+
+#ifdef DEBUG
+	printk("%s: dma_stat: 0x%02x mrdmode: 0x%02x irq_mask: 0x%02x\n",
+	       drive->name, dma_stat, mrdmode, irq_mask);
+#endif
+	if (!(mrdmode & irq_mask))
+		return 0;
+
+	/* return 1 if INTR asserted */
+	if (dma_stat & 4)
+		return 1;
+
+	return 0;
 }
 
 static int cmd64x_ide_dma_test_irq (ide_drive_t *drive)
 {
-	ide_hwif_t *hwif		= HWIF(drive);
-	struct pci_dev *dev		= hwif->pci_dev;
-        u8 dma_alt_stat = 0, mask	= (hwif->channel) ? MRDMODE_INTR_CH1 :
-							    MRDMODE_INTR_CH0;
-	u8 dma_stat = inb(hwif->dma_status);
+	ide_hwif_t *hwif	= HWIF(drive);
+	struct pci_dev *dev	= hwif->pci_dev;
+	int irq_reg		= hwif->channel ? ARTTIM23 : CFR;
+	u8  irq_mask		= hwif->channel ? ARTTIM23_INTR_CH1 :
+						  CFR_INTR_CH0;
+	u8  dma_stat		= inb(hwif->dma_status);
+	u8  irq_stat		= 0;
 
-	(void) pci_read_config_byte(dev, MRDMODE, &dma_alt_stat);
+	(void) pci_read_config_byte(dev, irq_reg, &irq_stat);
+
 #ifdef DEBUG
-	printk("%s: dma_stat: 0x%02x dma_alt_stat: "
-		"0x%02x mask: 0x%02x\n", drive->name,
-		dma_stat, dma_alt_stat, mask);
+	printk("%s: dma_stat: 0x%02x irq_stat: 0x%02x irq_mask: 0x%02x\n",
+	       drive->name, dma_stat, irq_stat, irq_mask);
 #endif
-	if (!(dma_alt_stat & mask))
+	if (!(irq_stat & irq_mask))
 		return 0;
 
 	/* return 1 if INTR asserted */
-	if ((dma_stat & 4) == 4)
+	if (dma_stat & 4)
 		return 1;
 
 	return 0;
@@ -665,7 +646,6 @@
 
 	hwif->ultra_mask = 0x3f;
 	hwif->mwdma_mask = 0x07;
-	hwif->swdma_mask = 0x07;
 
 	if (dev->device == PCI_DEVICE_ID_CMD_643)
 		hwif->ultra_mask = 0x80;
@@ -678,17 +658,25 @@
 	if (!(hwif->udma_four))
 		hwif->udma_four = ata66_cmd64x(hwif);
 
-	if (dev->device == PCI_DEVICE_ID_CMD_646) {
+	switch(dev->device) {
+	case PCI_DEVICE_ID_CMD_648:
+	case PCI_DEVICE_ID_CMD_649:
+	alt_irq_bits:
+		hwif->ide_dma_end	= &cmd648_ide_dma_end;
+		hwif->ide_dma_test_irq	= &cmd648_ide_dma_test_irq;
+		break;
+	case PCI_DEVICE_ID_CMD_646:
 		hwif->chipset = ide_cmd646;
 		if (class_rev == 0x01) {
 			hwif->ide_dma_end = &cmd646_1_ide_dma_end;
-		} else {
-			hwif->ide_dma_end = &cmd64x_ide_dma_end;
-			hwif->ide_dma_test_irq = &cmd64x_ide_dma_test_irq;
-		}
-	} else {
-		hwif->ide_dma_end = &cmd64x_ide_dma_end;
-		hwif->ide_dma_test_irq = &cmd64x_ide_dma_test_irq;
+			break;
+		} else if (class_rev >= 0x03)
+			goto alt_irq_bits;
+		/* fall thru */
+	default:
+		hwif->ide_dma_end	= &cmd64x_ide_dma_end;
+		hwif->ide_dma_test_irq	= &cmd64x_ide_dma_test_irq;
+		break;
 	}
 
 
@@ -698,42 +686,75 @@
 	hwif->drives[1].autodma = hwif->autodma;
 }
 
+static int __devinit init_setup_cmd64x(struct pci_dev *dev, ide_pci_device_t *d)
+{
+	return ide_setup_pci_device(dev, d);
+}
+
+static int __devinit init_setup_cmd646(struct pci_dev *dev, ide_pci_device_t *d)
+{
+	u8 rev = 0;
+
+	/*
+	 * The original PCI0646 didn't have the primary channel enable bit,
+	 * it appeared starting with PCI0646U (i.e. revision ID 3).
+	 */
+	pci_read_config_byte(dev, PCI_REVISION_ID, &rev);
+	if (rev < 3)
+		d->enablebits[0].reg = 0;
+
+	return ide_setup_pci_device(dev, d);
+}
+
 static ide_pci_device_t cmd64x_chipsets[] __devinitdata = {
 	{	/* 0 */
 		.name		= "CMD643",
+		.init_setup	= init_setup_cmd64x,
 		.init_chipset	= init_chipset_cmd64x,
 		.init_hwif	= init_hwif_cmd64x,
 		.channels	= 2,
 		.autodma	= AUTODMA,
+		.enablebits	= {{0x00,0x00,0x00}, {0x51,0x08,0x08}},
 		.bootable	= ON_BOARD,
 	},{	/* 1 */
 		.name		= "CMD646",
+		.init_setup	= init_setup_cmd646,
 		.init_chipset	= init_chipset_cmd64x,
 		.init_hwif	= init_hwif_cmd64x,
 		.channels	= 2,
 		.autodma	= AUTODMA,
-		.enablebits	= {{0x00,0x00,0x00}, {0x51,0x80,0x80}},
+		.enablebits	= {{0x51,0x04,0x04}, {0x51,0x08,0x08}},
 		.bootable	= ON_BOARD,
 	},{	/* 2 */
 		.name		= "CMD648",
+		.init_setup	= init_setup_cmd64x,
 		.init_chipset	= init_chipset_cmd64x,
 		.init_hwif	= init_hwif_cmd64x,
 		.channels	= 2,
 		.autodma	= AUTODMA,
+		.enablebits	= {{0x51,0x04,0x04}, {0x51,0x08,0x08}},
 		.bootable	= ON_BOARD,
 	},{	/* 3 */
 		.name		= "CMD649",
+		.init_setup	= init_setup_cmd64x,
 		.init_chipset	= init_chipset_cmd64x,
 		.init_hwif	= init_hwif_cmd64x,
 		.channels	= 2,
 		.autodma	= AUTODMA,
+		.enablebits	= {{0x51,0x04,0x04}, {0x51,0x08,0x08}},
 		.bootable	= ON_BOARD,
 	}
 };
 
+/*
+ * We may have to modify enablebits for PCI0646, so we'd better pass
+ * a local copy of the ide_pci_device_t structure down the call chain...
+ */
 static int __devinit cmd64x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 {
-	return ide_setup_pci_device(dev, &cmd64x_chipsets[id->driver_data]);
+	ide_pci_device_t d = cmd64x_chipsets[id->driver_data];
+
+	return d.init_setup(dev, &d);
 }
 
 static struct pci_device_id cmd64x_pci_tbl[] = {
diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c
index ab6fa27..cf9d344 100644
--- a/drivers/ide/pci/hpt366.c
+++ b/drivers/ide/pci/hpt366.c
@@ -1,5 +1,5 @@
 /*
- * linux/drivers/ide/pci/hpt366.c		Version 1.02	Apr 18, 2007
+ * linux/drivers/ide/pci/hpt366.c		Version 1.03	May 4, 2007
  *
  * Copyright (C) 1999-2003		Andre Hedrick <andre@linux-ide.org>
  * Portions Copyright (C) 2001	        Sun Microsystems, Inc.
@@ -1527,7 +1527,12 @@
 	if (rev > 2)
 		goto init_single;
 
+	/*
+	 * HPT36x chips are single channel and
+	 * do not seem to have the channel enable bit...
+	 */
 	d->channels = 1;
+	d->enablebits[0].reg = 0;
 
 	if ((dev2 = pci_get_slot(dev->bus, dev->devfn + 1)) != NULL) {
 	  	u8  pin1 = 0, pin2 = 0;
diff --git a/drivers/ide/pci/it821x.c b/drivers/ide/pci/it821x.c
index a132767..4e12548 100644
--- a/drivers/ide/pci/it821x.c
+++ b/drivers/ide/pci/it821x.c
@@ -1,8 +1,9 @@
 
 /*
- * linux/drivers/ide/pci/it821x.c		Version 0.09	December 2004
+ * linux/drivers/ide/pci/it821x.c		Version 0.10	Mar 10 2007
  *
  * Copyright (C) 2004		Red Hat <alan@redhat.com>
+ * Copyright (C) 2007		Bartlomiej Zolnierkiewicz
  *
  *  May be copied or modified under the terms of the GNU General Public License
  *  Based in part on the ITE vendor provided SCSI driver.
@@ -104,6 +105,7 @@
 /**
  *	it821x_program	-	program the PIO/MWDMA registers
  *	@drive: drive to tune
+ *	@timing: timing info
  *
  *	Program the PIO/MWDMA timing for this channel according to the
  *	current clock.
@@ -127,6 +129,7 @@
 /**
  *	it821x_program_udma	-	program the UDMA registers
  *	@drive: drive to tune
+ *	@timing: timing info
  *
  *	Program the UDMA timing for this drive according to the
  *	current clock.
@@ -153,10 +156,9 @@
 	}
 }
 
-
 /**
  *	it821x_clock_strategy
- *	@hwif: hardware interface
+ *	@drive: drive to set up
  *
  *	Select between the 50 and 66Mhz base clocks to get the best
  *	results for this interface.
@@ -182,8 +184,11 @@
 		altclock = itdev->want[0][1];
 	}
 
-	/* Master doesn't care does the slave ? */
-	if(clock == ATA_ANY)
+	/*
+	 * if both clocks can be used for the mode with the higher priority
+	 * use the clock needed by the mode with the lower priority
+	 */
+	if (clock == ATA_ANY)
 		clock = altclock;
 
 	/* Nobody cares - keep the same clock */
@@ -240,37 +245,56 @@
 }
 
 /**
- *	it821x_tuneproc	-	tune a drive
+ *	it821x_tunepio	-	tune a drive
  *	@drive: drive to tune
- *	@mode_wanted: the target operating mode
+ *	@pio: the desired PIO mode
  *
- *	Load the timing settings for this device mode into the
- *	controller. By the time we are called the mode has been
- *	modified as neccessary to handle the absence of seperate
- *	master/slave timers for MWDMA/PIO.
- *
- *	This code is only used in pass through mode.
+ *	Try to tune the drive/host to the desired PIO mode taking into
+ *	the consideration the maximum PIO mode supported by the other
+ *	device on the cable.
  */
 
-static void it821x_tuneproc (ide_drive_t *drive, byte mode_wanted)
+static int it821x_tunepio(ide_drive_t *drive, u8 set_pio)
 {
 	ide_hwif_t *hwif	= drive->hwif;
 	struct it821x_dev *itdev = ide_get_hwifdata(hwif);
 	int unit = drive->select.b.unit;
+	ide_drive_t *pair = &hwif->drives[1 - unit];
 
 	/* Spec says 89 ref driver uses 88 */
 	static u16 pio[]	= { 0xAA88, 0xA382, 0xA181, 0x3332, 0x3121 };
 	static u8 pio_want[]    = { ATA_66, ATA_66, ATA_66, ATA_66, ATA_ANY };
 
-	if(itdev->smart)
-		return;
+	/*
+	 * Compute the best PIO mode we can for a given device. We must
+	 * pick a speed that does not cause problems with the other device
+	 * on the cable.
+	 */
+	if (pair) {
+		u8 pair_pio = ide_get_best_pio_mode(pair, 255, 4, NULL);
+		/* trim PIO to the slowest of the master/slave */
+		if (pair_pio < set_pio)
+			set_pio = pair_pio;
+	}
+
+	if (itdev->smart)
+		goto set_drive_speed;
 
 	/* We prefer 66Mhz clock for PIO 0-3, don't care for PIO4 */
-	itdev->want[unit][1] = pio_want[mode_wanted];
+	itdev->want[unit][1] = pio_want[set_pio];
 	itdev->want[unit][0] = 1;	/* PIO is lowest priority */
-	itdev->pio[unit] = pio[mode_wanted];
+	itdev->pio[unit] = pio[set_pio];
 	it821x_clock_strategy(drive);
 	it821x_program(drive, itdev->pio[unit]);
+
+set_drive_speed:
+	return ide_config_drive_speed(drive, XFER_PIO_0 + set_pio);
+}
+
+static void it821x_tuneproc(ide_drive_t *drive, u8 pio)
+{
+	pio = ide_get_best_pio_mode(drive, pio, 4, NULL);
+	(void)it821x_tunepio(drive, pio);
 }
 
 /**
@@ -354,40 +378,6 @@
 }
 
 /**
- *	config_it821x_chipset_for_pio	-	set drive timings
- *	@drive: drive to tune
- *	@speed we want
- *
- *	Compute the best pio mode we can for a given device. We must
- *	pick a speed that does not cause problems with the other device
- *	on the cable.
- */
-
-static void config_it821x_chipset_for_pio (ide_drive_t *drive, byte set_speed)
-{
-	u8 unit = drive->select.b.unit;
-	ide_hwif_t *hwif = drive->hwif;
-	ide_drive_t *pair = &hwif->drives[1-unit];
-	u8 speed = 0, set_pio	= ide_get_best_pio_mode(drive, 255, 5, NULL);
-	u8 pair_pio;
-
-	/* We have to deal with this mess in pairs */
-	if(pair != NULL) {
-		pair_pio = ide_get_best_pio_mode(pair, 255, 5, NULL);
-		/* Trim PIO to the slowest of the master/slave */
-		if(pair_pio < set_pio)
-			set_pio = pair_pio;
-	}
-	it821x_tuneproc(drive, set_pio);
-	speed = XFER_PIO_0 + set_pio;
-	/* XXX - We trim to the lowest of the pair so the other drive
-	   will always be fine at this point until we do hotplug passthru */
-
-	if (set_speed)
-		(void) ide_config_drive_speed(drive, speed);
-}
-
-/**
  *	it821x_dma_read	-	DMA hook
  *	@drive: drive for DMA
  *
@@ -450,15 +440,17 @@
 	struct it821x_dev *itdev = ide_get_hwifdata(hwif);
 	u8 speed		= ide_rate_filter(it821x_ratemask(drive), xferspeed);
 
-	if(!itdev->smart) {
-		switch(speed) {
-			case XFER_PIO_4:
-			case XFER_PIO_3:
-			case XFER_PIO_2:
-			case XFER_PIO_1:
-			case XFER_PIO_0:
-				it821x_tuneproc(drive, (speed - XFER_PIO_0));
-				break;
+	switch (speed) {
+	case XFER_PIO_4:
+	case XFER_PIO_3:
+	case XFER_PIO_2:
+	case XFER_PIO_1:
+	case XFER_PIO_0:
+		return it821x_tunepio(drive, speed - XFER_PIO_0);
+	}
+
+	if (itdev->smart == 0) {
+		switch (speed) {
 			/* MWDMA tuning is really hard because our MWDMA and PIO
 			   timings are kept in the same place. We can switch in the
 			   host dma on/off callbacks */
@@ -498,14 +490,12 @@
 {
 	u8 speed	= ide_dma_speed(drive, it821x_ratemask(drive));
 
-	if (speed) {
-		config_it821x_chipset_for_pio(drive, 0);
-		it821x_tune_chipset(drive, speed);
+	if (speed == 0)
+		return 0;
 
-		return ide_dma_enable(drive);
-	}
+	it821x_tune_chipset(drive, speed);
 
-	return 0;
+	return ide_dma_enable(drive);
 }
 
 /**
@@ -523,7 +513,7 @@
 	if (ide_use_dma(drive) && config_chipset_for_dma(drive))
 		return 0;
 
-	config_it821x_chipset_for_pio(drive, 1);
+	it821x_tuneproc(drive, 255);
 
 	return -1;
 }
diff --git a/drivers/ide/pci/pdc202xx_new.c b/drivers/ide/pci/pdc202xx_new.c
index ace9892..2da5cbb 100644
--- a/drivers/ide/pci/pdc202xx_new.c
+++ b/drivers/ide/pci/pdc202xx_new.c
@@ -255,9 +255,6 @@
 		printk(KERN_WARNING "%s reduced to Ultra33 mode.\n", drive->name);
 	}
 
-	if (drive->media != ide_disk && drive->media != ide_cdrom)
-		return 0;
-
 	if (id->capability & 4) {
 		/*
 		 * Set IORDY_EN & PREFETCH_EN (this seems to have
diff --git a/drivers/ide/pci/siimage.c b/drivers/ide/pci/siimage.c
index 71eccdf..c0188de 100644
--- a/drivers/ide/pci/siimage.c
+++ b/drivers/ide/pci/siimage.c
@@ -1,5 +1,5 @@
 /*
- * linux/drivers/ide/pci/siimage.c		Version 1.11	Jan 27, 2007
+ * linux/drivers/ide/pci/siimage.c		Version 1.12	Mar 10 2007
  *
  * Copyright (C) 2001-2002	Andre Hedrick <andre@linux-ide.org>
  * Copyright (C) 2003		Red Hat <alan@redhat.com>
@@ -287,11 +287,6 @@
 		(void) ide_config_drive_speed(drive, speed);
 }
 
-static void config_chipset_for_pio (ide_drive_t *drive, byte set_speed)
-{
-	config_siimage_chipset_for_pio(drive, set_speed);
-}
-
 /**
  *	siimage_tune_chipset	-	set controller timings
  *	@drive: Drive to set up
@@ -396,8 +391,6 @@
 {
 	u8 speed	= ide_dma_speed(drive, siimage_ratemask(drive));
 
-	config_chipset_for_pio(drive, !speed);
-
 	if (!speed)
 		return 0;
 
@@ -423,7 +416,7 @@
 		return 0;
 
 	if (ide_use_fast_pio(drive))
-		config_chipset_for_pio(drive, 1);
+		config_siimage_chipset_for_pio(drive, 1);
 
 	return -1;
 }
@@ -1015,7 +1008,6 @@
 
 	hwif->ultra_mask = 0x7f;
 	hwif->mwdma_mask = 0x07;
-	hwif->swdma_mask = 0x07;
 
 	if (!is_sata(hwif))
 		hwif->atapi_dma = 1;
diff --git a/drivers/ide/pci/sl82c105.c b/drivers/ide/pci/sl82c105.c
index 3a8a76f..fe3b4b9 100644
--- a/drivers/ide/pci/sl82c105.c
+++ b/drivers/ide/pci/sl82c105.c
@@ -11,6 +11,8 @@
  * Merge in Russell's HW workarounds, fix various problems
  * with the timing registers setup.
  *  -- Benjamin Herrenschmidt (01/11/03) benh@kernel.crashing.org
+ *
+ * Copyright (C) 2006-2007 MontaVista Software, Inc. <source@mvista.com>
  */
 
 #include <linux/types.h>
@@ -47,25 +49,19 @@
 #define CTRL_P0EN       (1 << 0)
 
 /*
- * Convert a PIO mode and cycle time to the required on/off
- * times for the interface.  This has protection against run-away
- * timings.
+ * Convert a PIO mode and cycle time to the required on/off times
+ * for the interface.  This has protection against runaway timings.
  */
-static unsigned int get_timing_sl82c105(ide_pio_data_t *p)
+static unsigned int get_pio_timings(ide_pio_data_t *p)
 {
-	unsigned int cmd_on;
-	unsigned int cmd_off;
+	unsigned int cmd_on, cmd_off;
 
-	cmd_on = (ide_pio_timings[p->pio_mode].active_time + 29) / 30;
+	cmd_on  = (ide_pio_timings[p->pio_mode].active_time + 29) / 30;
 	cmd_off = (p->cycle_time - 30 * cmd_on + 29) / 30;
 
-	if (cmd_on > 32)
-		cmd_on = 32;
 	if (cmd_on == 0)
 		cmd_on = 1;
 
-	if (cmd_off > 32)
-		cmd_off = 32;
 	if (cmd_off == 0)
 		cmd_off = 1;
 
@@ -73,100 +69,59 @@
 }
 
 /*
- * Configure the drive and chipset for PIO
+ * Configure the chipset for PIO mode.
  */
-static void config_for_pio(ide_drive_t *drive, int pio, int report, int chipset_only)
+static u8 sl82c105_tune_pio(ide_drive_t *drive, u8 pio)
 {
-	ide_hwif_t *hwif = HWIF(drive);
-	struct pci_dev *dev = hwif->pci_dev;
+	struct pci_dev *dev	= HWIF(drive)->pci_dev;
+	int reg			= 0x44 + drive->dn * 4;
 	ide_pio_data_t p;
-	u16 drv_ctrl = 0x909;
-	unsigned int xfer_mode, reg;
+	u16 drv_ctrl;
 
-	DBG(("config_for_pio(drive:%s, pio:%d, report:%d, chipset_only:%d)\n",
-		drive->name, pio, report, chipset_only));
-		
-	reg = (hwif->channel ? 0x4c : 0x44) + (drive->select.b.unit ? 4 : 0);
+	DBG(("sl82c105_tune_pio(drive:%s, pio:%u)\n", drive->name, pio));
 
 	pio = ide_get_best_pio_mode(drive, pio, 5, &p);
 
-	xfer_mode = XFER_PIO_0 + pio;
+	drive->drive_data = drv_ctrl = get_pio_timings(&p);
 
-	if (chipset_only || ide_config_drive_speed(drive, xfer_mode) == 0) {
-		drv_ctrl = get_timing_sl82c105(&p);
-		drive->pio_speed = xfer_mode;
-	} else
-		drive->pio_speed = XFER_PIO_0;
-
-	if (drive->using_dma == 0) {
+	if (!drive->using_dma) {
 		/*
 		 * If we are actually using MW DMA, then we can not
 		 * reprogram the interface drive control register.
 		 */
-		pci_write_config_word(dev, reg, drv_ctrl);
-		pci_read_config_word(dev, reg, &drv_ctrl);
-
-		if (report) {
-			printk("%s: selected %s (%dns) (%04X)\n", drive->name,
-			       ide_xfer_verbose(xfer_mode), p.cycle_time, drv_ctrl);
-		}
+		pci_write_config_word(dev, reg,  drv_ctrl);
+		pci_read_config_word (dev, reg, &drv_ctrl);
 	}
+
+	printk(KERN_DEBUG "%s: selected %s (%dns) (%04X)\n", drive->name,
+	       ide_xfer_verbose(pio + XFER_PIO_0), p.cycle_time, drv_ctrl);
+
+	return pio;
 }
 
 /*
- * Configure the drive and the chipset for DMA
+ * Configure the drive for DMA.
+ * We'll program the chipset only when DMA is actually turned on.
  */
-static int config_for_dma (ide_drive_t *drive)
+static int config_for_dma(ide_drive_t *drive)
 {
-	ide_hwif_t *hwif = HWIF(drive);
-	struct pci_dev *dev = hwif->pci_dev;
-	unsigned int reg;
-
 	DBG(("config_for_dma(drive:%s)\n", drive->name));
 
-	reg = (hwif->channel ? 0x4c : 0x44) + (drive->select.b.unit ? 4 : 0);
-
 	if (ide_config_drive_speed(drive, XFER_MW_DMA_2) != 0)
-		return 1;
+		return 0;
 
-	pci_write_config_word(dev, reg, 0x0240);
-
-	return 0;
+	return ide_dma_enable(drive);
 }
 
 /*
- * Check to see if the drive and
- * chipset is capable of DMA mode
+ * Check to see if the drive and chipset are capable of DMA mode.
  */
-
-static int sl82c105_check_drive (ide_drive_t *drive)
+static int sl82c105_ide_dma_check(ide_drive_t *drive)
 {
-	ide_hwif_t *hwif	= HWIF(drive);
+	DBG(("sl82c105_ide_dma_check(drive:%s)\n", drive->name));
 
-	DBG(("sl82c105_check_drive(drive:%s)\n", drive->name));
-
-	do {
-		struct hd_driveid *id = drive->id;
-
-		if (!drive->autodma)
-			break;
-
-		if (!id || !(id->capability & 1))
-			break;
-
-		/* Consult the list of known "bad" drives */
-		if (__ide_dma_bad_drive(drive))
-			break;
-
-		if (id->field_valid & 2) {
-			if ((id->dma_mword & hwif->mwdma_mask) ||
-			    (id->dma_1word & hwif->swdma_mask))
-				return 0;
-		}
-
-		if (__ide_dma_good_drive(drive) && id->eide_dma_time < 150)
-			return 0;
-	} while (0);
+	if (ide_use_dma(drive) && config_for_dma(drive))
+		return 0;
 
 	return -1;
 }
@@ -195,14 +150,14 @@
  * This function is called when the IDE timer expires, the drive
  * indicates that it is READY, and we were waiting for DMA to complete.
  */
-static int sl82c105_ide_dma_lost_irq(ide_drive_t *drive)
+static int sl82c105_ide_dma_lostirq(ide_drive_t *drive)
 {
-	ide_hwif_t *hwif = HWIF(drive);
-	struct pci_dev *dev = hwif->pci_dev;
-	u32 val, mask = hwif->channel ? CTRL_IDE_IRQB : CTRL_IDE_IRQA;
-	unsigned long dma_base = hwif->dma_base;
+	ide_hwif_t *hwif	= HWIF(drive);
+	struct pci_dev *dev	= hwif->pci_dev;
+	u32 val, mask		= hwif->channel ? CTRL_IDE_IRQB : CTRL_IDE_IRQA;
+	u8 dma_cmd;
 
-	printk("sl82c105: lost IRQ: resetting host\n");
+	printk("sl82c105: lost IRQ, resetting host\n");
 
 	/*
 	 * Check the raw interrupt from the drive.
@@ -215,15 +170,15 @@
 	 * Was DMA enabled?  If so, disable it - we're resetting the
 	 * host.  The IDE layer will be handling the drive for us.
 	 */
-	val = inb(dma_base);
-	if (val & 1) {
-		outb(val & ~1, dma_base);
+	dma_cmd = inb(hwif->dma_command);
+	if (dma_cmd & 1) {
+		outb(dma_cmd & ~1, hwif->dma_command);
 		printk("sl82c105: DMA was enabled\n");
 	}
 
 	sl82c105_reset_host(dev);
 
-	/* ide_dmaproc would return 1, so we do as well */
+	/* __ide_dma_lostirq would return 1, so we do as well */
 	return 1;
 }
 
@@ -235,10 +190,10 @@
  * The generic IDE core will have disabled the BMEN bit before this
  * function is called.
  */
-static void sl82c105_ide_dma_start(ide_drive_t *drive)
+static void sl82c105_dma_start(ide_drive_t *drive)
 {
-	ide_hwif_t *hwif = HWIF(drive);
-	struct pci_dev *dev = hwif->pci_dev;
+	ide_hwif_t *hwif	= HWIF(drive);
+	struct pci_dev *dev	= hwif->pci_dev;
 
 	sl82c105_reset_host(dev);
 	ide_dma_start(drive);
@@ -246,8 +201,8 @@
 
 static int sl82c105_ide_dma_timeout(ide_drive_t *drive)
 {
-	ide_hwif_t *hwif = HWIF(drive);
-	struct pci_dev *dev = hwif->pci_dev;
+	ide_hwif_t *hwif	= HWIF(drive);
+	struct pci_dev *dev	= hwif->pci_dev;
 
 	DBG(("sl82c105_ide_dma_timeout(drive:%s)\n", drive->name));
 
@@ -255,26 +210,32 @@
 	return __ide_dma_timeout(drive);
 }
 
-static int sl82c105_ide_dma_on (ide_drive_t *drive)
+static int sl82c105_ide_dma_on(ide_drive_t *drive)
 {
+	struct pci_dev *dev	= HWIF(drive)->pci_dev;
+	int rc, reg 		= 0x44 + drive->dn * 4;
+
 	DBG(("sl82c105_ide_dma_on(drive:%s)\n", drive->name));
 
-	if (config_for_dma(drive))
-		return 1;
-	printk(KERN_INFO "%s: DMA enabled\n", drive->name);
-	return __ide_dma_on(drive);
+	rc = __ide_dma_on(drive);
+	if (rc == 0) {
+		pci_write_config_word(dev, reg, 0x0200);
+
+		printk(KERN_INFO "%s: DMA enabled\n", drive->name);
+	}
+	return rc;
 }
 
 static void sl82c105_dma_off_quietly(ide_drive_t *drive)
 {
-	u8 speed = XFER_PIO_0;
+	struct pci_dev *dev	= HWIF(drive)->pci_dev;
+	int reg 		= 0x44 + drive->dn * 4;
 
 	DBG(("sl82c105_dma_off_quietly(drive:%s)\n", drive->name));
 
+	pci_write_config_word(dev, reg, drive->drive_data);
+
 	ide_dma_off_quietly(drive);
-	if (drive->pio_speed)
-		speed = drive->pio_speed - XFER_PIO_0;
-	config_for_pio(drive, speed, 0, 1);
 }
 
 /*
@@ -286,8 +247,8 @@
  */
 static void sl82c105_selectproc(ide_drive_t *drive)
 {
-	ide_hwif_t *hwif = HWIF(drive);
-	struct pci_dev *dev = hwif->pci_dev;
+	ide_hwif_t *hwif	= HWIF(drive);
+	struct pci_dev *dev	= hwif->pci_dev;
 	u32 val, old, mask;
 
 	//DBG(("sl82c105_selectproc(drive:%s)\n", drive->name));
@@ -323,18 +284,12 @@
  * We only deal with PIO mode here - DMA mode 'using_dma' is not
  * initialised at the point that this function is called.
  */
-static void tune_sl82c105(ide_drive_t *drive, u8 pio)
+static void sl82c105_tune_drive(ide_drive_t *drive, u8 pio)
 {
-	DBG(("tune_sl82c105(drive:%s)\n", drive->name));
+	DBG(("sl82c105_tune_drive(drive:%s, pio:%u)\n", drive->name, pio));
 
-	config_for_pio(drive, pio, 1, 0);
-
-	/*
-	 * We support 32-bit I/O on this interface, and it
-	 * doesn't have problems with interrupts.
-	 */
-	drive->io_32bit = 1;
-	drive->unmask = 1;
+	pio = sl82c105_tune_pio(drive, pio);
+	(void) ide_config_drive_speed(drive, XFER_PIO_0 + pio);
 }
 
 /*
@@ -393,7 +348,7 @@
 }
 
 /*
- * Initialise the chip
+ * Initialise IDE channel
  */
 static void __devinit init_hwif_sl82c105(ide_hwif_t *hwif)
 {
@@ -401,24 +356,22 @@
 
 	DBG(("init_hwif_sl82c105(hwif: ide%d)\n", hwif->index));
 
-	hwif->tuneproc = tune_sl82c105;
-	hwif->selectproc = sl82c105_selectproc;
-	hwif->resetproc = sl82c105_resetproc;
+	hwif->tuneproc		= &sl82c105_tune_drive;
+	hwif->selectproc	= &sl82c105_selectproc;
+	hwif->resetproc 	= &sl82c105_resetproc;
 
 	/*
-	 * Default to PIO 0 for fallback unless tuned otherwise.
+	 * We support 32-bit I/O on this interface, and
+	 * it doesn't have problems with interrupts.
+	 */
+	hwif->drives[0].io_32bit = hwif->drives[1].io_32bit = 1;
+	hwif->drives[0].unmask   = hwif->drives[1].unmask   = 1;
+
+	/*
 	 * We always autotune PIO,  this is done before DMA is checked,
 	 * so there's no risk of accidentally disabling DMA
 	 */
-	hwif->drives[0].pio_speed = XFER_PIO_0;
-	hwif->drives[0].autotune = 1;
-	hwif->drives[1].pio_speed = XFER_PIO_0;
-	hwif->drives[1].autotune = 1;
-
-	hwif->atapi_dma = 0;
-	hwif->mwdma_mask = 0;
-	hwif->swdma_mask = 0;
-	hwif->autodma = 0;
+	hwif->drives[0].autotune = hwif->drives[1].autotune = 1;
 
 	if (!hwif->dma_base)
 		return;
@@ -429,27 +382,27 @@
 		 * Never ever EVER under any circumstances enable
 		 * DMA when the bridge is this old.
 		 */
-		printk("    %s: Winbond 553 bridge revision %d, BM-DMA disabled\n",
-		       hwif->name, rev);
-	} else {
-		hwif->atapi_dma = 1;
-		hwif->mwdma_mask = 0x04;
-
-		hwif->ide_dma_check = &sl82c105_check_drive;
-		hwif->ide_dma_on = &sl82c105_ide_dma_on;
-		hwif->dma_off_quietly = &sl82c105_dma_off_quietly;
-		hwif->ide_dma_lostirq = &sl82c105_ide_dma_lost_irq;
-		hwif->dma_start = &sl82c105_ide_dma_start;
-		hwif->ide_dma_timeout = &sl82c105_ide_dma_timeout;
-
-		if (!noautodma)
-			hwif->autodma = 1;
-		hwif->drives[0].autodma = hwif->autodma;
-		hwif->drives[1].autodma = hwif->autodma;
-
-		if (hwif->mate)
-			hwif->serialized = hwif->mate->serialized = 1;
+		printk("    %s: Winbond W83C553 bridge revision %d, "
+		       "BM-DMA disabled\n", hwif->name, rev);
+		return;
 	}
+
+	hwif->atapi_dma  = 1;
+	hwif->mwdma_mask = 0x04;
+
+	hwif->ide_dma_check		= &sl82c105_ide_dma_check;
+	hwif->ide_dma_on		= &sl82c105_ide_dma_on;
+	hwif->dma_off_quietly		= &sl82c105_dma_off_quietly;
+	hwif->ide_dma_lostirq		= &sl82c105_ide_dma_lostirq;
+	hwif->dma_start			= &sl82c105_dma_start;
+	hwif->ide_dma_timeout		= &sl82c105_ide_dma_timeout;
+
+	if (!noautodma)
+		hwif->autodma = 1;
+	hwif->drives[0].autodma = hwif->drives[1].autodma = hwif->autodma;
+
+	if (hwif->mate)
+		hwif->serialized = hwif->mate->serialized = 1;
 }
 
 static ide_pci_device_t sl82c105_chipset __devinitdata = {
diff --git a/drivers/ieee1394/hosts.c b/drivers/ieee1394/hosts.c
index 6164a9a..bd0755c 100644
--- a/drivers/ieee1394/hosts.c
+++ b/drivers/ieee1394/hosts.c
@@ -15,7 +15,6 @@
 #include <linux/list.h>
 #include <linux/init.h>
 #include <linux/slab.h>
-#include <linux/pci.h>
 #include <linux/timer.h>
 #include <linux/jiffies.h>
 #include <linux/mutex.h>
diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c
index 842cd0b..eff591d 100644
--- a/drivers/infiniband/core/cm.c
+++ b/drivers/infiniband/core/cm.c
@@ -40,7 +40,6 @@
 #include <linux/err.h>
 #include <linux/idr.h>
 #include <linux/interrupt.h>
-#include <linux/pci.h>
 #include <linux/random.h>
 #include <linux/rbtree.h>
 #include <linux/spinlock.h>
diff --git a/drivers/infiniband/core/iwcm.c b/drivers/infiniband/core/iwcm.c
index 891d1fa..223b1aa 100644
--- a/drivers/infiniband/core/iwcm.c
+++ b/drivers/infiniband/core/iwcm.c
@@ -39,7 +39,6 @@
 #include <linux/err.h>
 #include <linux/idr.h>
 #include <linux/interrupt.h>
-#include <linux/pci.h>
 #include <linux/rbtree.h>
 #include <linux/spinlock.h>
 #include <linux/workqueue.h>
diff --git a/drivers/infiniband/core/mad_priv.h b/drivers/infiniband/core/mad_priv.h
index de89717..9be5cc0 100644
--- a/drivers/infiniband/core/mad_priv.h
+++ b/drivers/infiniband/core/mad_priv.h
@@ -39,7 +39,6 @@
 
 #include <linux/completion.h>
 #include <linux/err.h>
-#include <linux/pci.h>
 #include <linux/workqueue.h>
 #include <rdma/ib_mad.h>
 #include <rdma/ib_smi.h>
diff --git a/drivers/infiniband/core/multicast.c b/drivers/infiniband/core/multicast.c
index 4a579b3..1e13ab4 100644
--- a/drivers/infiniband/core/multicast.c
+++ b/drivers/infiniband/core/multicast.c
@@ -34,7 +34,6 @@
 #include <linux/dma-mapping.h>
 #include <linux/err.h>
 #include <linux/interrupt.h>
-#include <linux/pci.h>
 #include <linux/bitops.h>
 #include <linux/random.h>
 
diff --git a/drivers/infiniband/core/sa_query.c b/drivers/infiniband/core/sa_query.c
index 9a7eaad..6469406 100644
--- a/drivers/infiniband/core/sa_query.c
+++ b/drivers/infiniband/core/sa_query.c
@@ -40,7 +40,6 @@
 #include <linux/random.h>
 #include <linux/spinlock.h>
 #include <linux/slab.h>
-#include <linux/pci.h>
 #include <linux/dma-mapping.h>
 #include <linux/kref.h>
 #include <linux/idr.h>
diff --git a/drivers/infiniband/core/user_mad.c b/drivers/infiniband/core/user_mad.c
index 8199b83..d97ded2 100644
--- a/drivers/infiniband/core/user_mad.c
+++ b/drivers/infiniband/core/user_mad.c
@@ -40,7 +40,6 @@
 #include <linux/err.h>
 #include <linux/fs.h>
 #include <linux/cdev.h>
-#include <linux/pci.h>
 #include <linux/dma-mapping.h>
 #include <linux/poll.h>
 #include <linux/rwsem.h>
diff --git a/drivers/infiniband/hw/ipath/ipath_fs.c b/drivers/infiniband/hw/ipath/ipath_fs.c
index ed55979..036ed1e 100644
--- a/drivers/infiniband/hw/ipath/ipath_fs.c
+++ b/drivers/infiniband/hw/ipath/ipath_fs.c
@@ -38,7 +38,6 @@
 #include <linux/pagemap.h>
 #include <linux/init.h>
 #include <linux/namei.h>
-#include <linux/pci.h>
 
 #include "ipath_kernel.h"
 
diff --git a/drivers/infiniband/hw/ipath/ipath_layer.c b/drivers/infiniband/hw/ipath/ipath_layer.c
index e46aa4e..05a1d2b 100644
--- a/drivers/infiniband/hw/ipath/ipath_layer.c
+++ b/drivers/infiniband/hw/ipath/ipath_layer.c
@@ -37,7 +37,6 @@
  */
 
 #include <linux/io.h>
-#include <linux/pci.h>
 #include <asm/byteorder.h>
 
 #include "ipath_kernel.h"
diff --git a/drivers/infiniband/hw/ipath/ipath_stats.c b/drivers/infiniband/hw/ipath/ipath_stats.c
index 9307f71..d8b5e4c 100644
--- a/drivers/infiniband/hw/ipath/ipath_stats.c
+++ b/drivers/infiniband/hw/ipath/ipath_stats.c
@@ -31,8 +31,6 @@
  * SOFTWARE.
  */
 
-#include <linux/pci.h>
-
 #include "ipath_kernel.h"
 
 struct infinipath_stats ipath_stats;
diff --git a/drivers/infiniband/hw/ipath/ipath_sysfs.c b/drivers/infiniband/hw/ipath/ipath_sysfs.c
index ffa6318..4dc398d 100644
--- a/drivers/infiniband/hw/ipath/ipath_sysfs.c
+++ b/drivers/infiniband/hw/ipath/ipath_sysfs.c
@@ -32,7 +32,6 @@
  */
 
 #include <linux/ctype.h>
-#include <linux/pci.h>
 
 #include "ipath_kernel.h"
 #include "ipath_common.h"
diff --git a/drivers/infiniband/hw/mthca/mthca_memfree.h b/drivers/infiniband/hw/mthca/mthca_memfree.h
index 5941441..a1ab068 100644
--- a/drivers/infiniband/hw/mthca/mthca_memfree.h
+++ b/drivers/infiniband/hw/mthca/mthca_memfree.h
@@ -38,7 +38,6 @@
 #define MTHCA_MEMFREE_H
 
 #include <linux/list.h>
-#include <linux/pci.h>
 #include <linux/mutex.h>
 
 #define MTHCA_ICM_CHUNK_LEN \
diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h
index fd55826..d8f6bb4 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib.h
+++ b/drivers/infiniband/ulp/ipoib/ipoib.h
@@ -41,7 +41,6 @@
 #include <linux/skbuff.h>
 #include <linux/netdevice.h>
 #include <linux/workqueue.h>
-#include <linux/pci.h>
 #include <linux/kref.h>
 #include <linux/if_infiniband.h>
 #include <linux/mutex.h>
diff --git a/drivers/infiniband/ulp/iser/iser_initiator.c b/drivers/infiniband/ulp/iser/iser_initiator.c
index 278fcbc..3651072 100644
--- a/drivers/infiniband/ulp/iser/iser_initiator.c
+++ b/drivers/infiniband/ulp/iser/iser_initiator.c
@@ -201,7 +201,7 @@
 	 * what's common for both schemes is that the connection is not started
 	 */
 	if (conn->c_stage != ISCSI_CONN_STARTED)
-		rx_data_size = DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH;
+		rx_data_size = ISCSI_DEF_MAX_RECV_SEG_LEN;
 	else /* FIXME till user space sets conn->max_recv_dlength correctly */
 		rx_data_size = 128;
 
diff --git a/drivers/input/Makefile b/drivers/input/Makefile
index da575de..b4cd106 100644
--- a/drivers/input/Makefile
+++ b/drivers/input/Makefile
@@ -13,7 +13,6 @@
 obj-$(CONFIG_INPUT_JOYDEV)	+= joydev.o
 obj-$(CONFIG_INPUT_EVDEV)	+= evdev.o
 obj-$(CONFIG_INPUT_TSDEV)	+= tsdev.o
-obj-$(CONFIG_INPUT_POWER)	+= power.o
 obj-$(CONFIG_INPUT_EVBUG)	+= evbug.o
 
 obj-$(CONFIG_INPUT_KEYBOARD)	+= keyboard/
diff --git a/drivers/input/evbug.c b/drivers/input/evbug.c
index 5a9653c..c21f2f1 100644
--- a/drivers/input/evbug.c
+++ b/drivers/input/evbug.c
@@ -38,31 +38,43 @@
 MODULE_DESCRIPTION("Input driver event debug module");
 MODULE_LICENSE("GPL");
 
-static char evbug_name[] = "evbug";
-
 static void evbug_event(struct input_handle *handle, unsigned int type, unsigned int code, int value)
 {
 	printk(KERN_DEBUG "evbug.c: Event. Dev: %s, Type: %d, Code: %d, Value: %d\n",
 		handle->dev->phys, type, code, value);
 }
 
-static struct input_handle *evbug_connect(struct input_handler *handler, struct input_dev *dev,
-					  const struct input_device_id *id)
+static int evbug_connect(struct input_handler *handler, struct input_dev *dev,
+			 const struct input_device_id *id)
 {
 	struct input_handle *handle;
+	int error;
 
-	if (!(handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL)))
-		return NULL;
+	handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL);
+	if (!handle)
+		return -ENOMEM;
 
 	handle->dev = dev;
 	handle->handler = handler;
-	handle->name = evbug_name;
+	handle->name = "evbug";
 
-	input_open_device(handle);
+	error = input_register_handle(handle);
+	if (error)
+		goto err_free_handle;
+
+	error = input_open_device(handle);
+	if (error)
+		goto err_unregister_handle;
 
 	printk(KERN_DEBUG "evbug.c: Connected device: \"%s\", %s\n", dev->name, dev->phys);
 
-	return handle;
+	return 0;
+
+ err_unregister_handle:
+	input_unregister_handle(handle);
+ err_free_handle:
+	kfree(handle);
+	return error;
 }
 
 static void evbug_disconnect(struct input_handle *handle)
@@ -70,7 +82,7 @@
 	printk(KERN_DEBUG "evbug.c: Disconnected device: %s\n", handle->dev->phys);
 
 	input_close_device(handle);
-
+	input_unregister_handle(handle);
 	kfree(handle);
 }
 
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index 6439f37..1f6fcec 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -29,11 +29,11 @@
 	char name[16];
 	struct input_handle handle;
 	wait_queue_head_t wait;
-	struct evdev_list *grab;
-	struct list_head list;
+	struct evdev_client *grab;
+	struct list_head client_list;
 };
 
-struct evdev_list {
+struct evdev_client {
 	struct input_event buffer[EVDEV_BUFFER_SIZE];
 	int head;
 	int tail;
@@ -47,28 +47,28 @@
 static void evdev_event(struct input_handle *handle, unsigned int type, unsigned int code, int value)
 {
 	struct evdev *evdev = handle->private;
-	struct evdev_list *list;
+	struct evdev_client *client;
 
 	if (evdev->grab) {
-		list = evdev->grab;
+		client = evdev->grab;
 
-		do_gettimeofday(&list->buffer[list->head].time);
-		list->buffer[list->head].type = type;
-		list->buffer[list->head].code = code;
-		list->buffer[list->head].value = value;
-		list->head = (list->head + 1) & (EVDEV_BUFFER_SIZE - 1);
+		do_gettimeofday(&client->buffer[client->head].time);
+		client->buffer[client->head].type = type;
+		client->buffer[client->head].code = code;
+		client->buffer[client->head].value = value;
+		client->head = (client->head + 1) & (EVDEV_BUFFER_SIZE - 1);
 
-		kill_fasync(&list->fasync, SIGIO, POLL_IN);
+		kill_fasync(&client->fasync, SIGIO, POLL_IN);
 	} else
-		list_for_each_entry(list, &evdev->list, node) {
+		list_for_each_entry(client, &evdev->client_list, node) {
 
-			do_gettimeofday(&list->buffer[list->head].time);
-			list->buffer[list->head].type = type;
-			list->buffer[list->head].code = code;
-			list->buffer[list->head].value = value;
-			list->head = (list->head + 1) & (EVDEV_BUFFER_SIZE - 1);
+			do_gettimeofday(&client->buffer[client->head].time);
+			client->buffer[client->head].type = type;
+			client->buffer[client->head].code = code;
+			client->buffer[client->head].value = value;
+			client->head = (client->head + 1) & (EVDEV_BUFFER_SIZE - 1);
 
-			kill_fasync(&list->fasync, SIGIO, POLL_IN);
+			kill_fasync(&client->fasync, SIGIO, POLL_IN);
 		}
 
 	wake_up_interruptible(&evdev->wait);
@@ -76,22 +76,23 @@
 
 static int evdev_fasync(int fd, struct file *file, int on)
 {
+	struct evdev_client *client = file->private_data;
 	int retval;
-	struct evdev_list *list = file->private_data;
 
-	retval = fasync_helper(fd, file, on, &list->fasync);
+	retval = fasync_helper(fd, file, on, &client->fasync);
 
 	return retval < 0 ? retval : 0;
 }
 
 static int evdev_flush(struct file *file, fl_owner_t id)
 {
-	struct evdev_list *list = file->private_data;
+	struct evdev_client *client = file->private_data;
+	struct evdev *evdev = client->evdev;
 
-	if (!list->evdev->exist)
+	if (!evdev->exist)
 		return -ENODEV;
 
-	return input_flush_device(&list->evdev->handle, file);
+	return input_flush_device(&evdev->handle, file);
 }
 
 static void evdev_free(struct evdev *evdev)
@@ -100,48 +101,62 @@
 	kfree(evdev);
 }
 
-static int evdev_release(struct inode * inode, struct file * file)
+static int evdev_release(struct inode *inode, struct file *file)
 {
-	struct evdev_list *list = file->private_data;
+	struct evdev_client *client = file->private_data;
+	struct evdev *evdev = client->evdev;
 
-	if (list->evdev->grab == list) {
-		input_release_device(&list->evdev->handle);
-		list->evdev->grab = NULL;
+	if (evdev->grab == client) {
+		input_release_device(&evdev->handle);
+		evdev->grab = NULL;
 	}
 
 	evdev_fasync(-1, file, 0);
-	list_del(&list->node);
+	list_del(&client->node);
+	kfree(client);
 
-	if (!--list->evdev->open) {
-		if (list->evdev->exist)
-			input_close_device(&list->evdev->handle);
+	if (!--evdev->open) {
+		if (evdev->exist)
+			input_close_device(&evdev->handle);
 		else
-			evdev_free(list->evdev);
+			evdev_free(evdev);
 	}
 
-	kfree(list);
 	return 0;
 }
 
-static int evdev_open(struct inode * inode, struct file * file)
+static int evdev_open(struct inode *inode, struct file *file)
 {
-	struct evdev_list *list;
+	struct evdev_client *client;
+	struct evdev *evdev;
 	int i = iminor(inode) - EVDEV_MINOR_BASE;
+	int error;
 
-	if (i >= EVDEV_MINORS || !evdev_table[i] || !evdev_table[i]->exist)
+	if (i >= EVDEV_MINORS)
 		return -ENODEV;
 
-	if (!(list = kzalloc(sizeof(struct evdev_list), GFP_KERNEL)))
+	evdev = evdev_table[i];
+
+	if (!evdev || !evdev->exist)
+		return -ENODEV;
+
+	client = kzalloc(sizeof(struct evdev_client), GFP_KERNEL);
+	if (!client)
 		return -ENOMEM;
 
-	list->evdev = evdev_table[i];
-	list_add_tail(&list->node, &evdev_table[i]->list);
-	file->private_data = list;
+	client->evdev = evdev;
+	list_add_tail(&client->node, &evdev->client_list);
 
-	if (!list->evdev->open++)
-		if (list->evdev->exist)
-			input_open_device(&list->evdev->handle);
+	if (!evdev->open++ && evdev->exist) {
+		error = input_open_device(&evdev->handle);
+		if (error) {
+			list_del(&client->node);
+			kfree(client);
+			return error;
+		}
+	}
 
+	file->private_data = client;
 	return 0;
 }
 
@@ -243,54 +258,55 @@
 
 #endif /* CONFIG_COMPAT */
 
-static ssize_t evdev_write(struct file * file, const char __user * buffer, size_t count, loff_t *ppos)
+static ssize_t evdev_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
 {
-	struct evdev_list *list = file->private_data;
+	struct evdev_client *client = file->private_data;
+	struct evdev *evdev = client->evdev;
 	struct input_event event;
 	int retval = 0;
 
-	if (!list->evdev->exist)
+	if (!evdev->exist)
 		return -ENODEV;
 
 	while (retval < count) {
 
 		if (evdev_event_from_user(buffer + retval, &event))
 			return -EFAULT;
-		input_inject_event(&list->evdev->handle, event.type, event.code, event.value);
+		input_inject_event(&evdev->handle, event.type, event.code, event.value);
 		retval += evdev_event_size();
 	}
 
 	return retval;
 }
 
-static ssize_t evdev_read(struct file * file, char __user * buffer, size_t count, loff_t *ppos)
+static ssize_t evdev_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
 {
-	struct evdev_list *list = file->private_data;
+	struct evdev_client *client = file->private_data;
+	struct evdev *evdev = client->evdev;
 	int retval;
 
 	if (count < evdev_event_size())
 		return -EINVAL;
 
-	if (list->head == list->tail && list->evdev->exist && (file->f_flags & O_NONBLOCK))
+	if (client->head == client->tail && evdev->exist && (file->f_flags & O_NONBLOCK))
 		return -EAGAIN;
 
-	retval = wait_event_interruptible(list->evdev->wait,
-		list->head != list->tail || (!list->evdev->exist));
-
+	retval = wait_event_interruptible(evdev->wait,
+		client->head != client->tail || !evdev->exist);
 	if (retval)
 		return retval;
 
-	if (!list->evdev->exist)
+	if (!evdev->exist)
 		return -ENODEV;
 
-	while (list->head != list->tail && retval + evdev_event_size() <= count) {
+	while (client->head != client->tail && retval + evdev_event_size() <= count) {
 
-		struct input_event *event = (struct input_event *) list->buffer + list->tail;
+		struct input_event *event = (struct input_event *) client->buffer + client->tail;
 
 		if (evdev_event_to_user(buffer + retval, event))
 			return -EFAULT;
 
-		list->tail = (list->tail + 1) & (EVDEV_BUFFER_SIZE - 1);
+		client->tail = (client->tail + 1) & (EVDEV_BUFFER_SIZE - 1);
 		retval += evdev_event_size();
 	}
 
@@ -300,11 +316,12 @@
 /* No kernel lock - fine */
 static unsigned int evdev_poll(struct file *file, poll_table *wait)
 {
-	struct evdev_list *list = file->private_data;
+	struct evdev_client *client = file->private_data;
+	struct evdev *evdev = client->evdev;
 
-	poll_wait(file, &list->evdev->wait, wait);
-	return ((list->head == list->tail) ? 0 : (POLLIN | POLLRDNORM)) |
-		(list->evdev->exist ? 0 : (POLLHUP | POLLERR));
+	poll_wait(file, &evdev->wait, wait);
+	return ((client->head == client->tail) ? 0 : (POLLIN | POLLRDNORM)) |
+		(evdev->exist ? 0 : (POLLHUP | POLLERR));
 }
 
 #ifdef CONFIG_COMPAT
@@ -387,8 +404,8 @@
 static long evdev_ioctl_handler(struct file *file, unsigned int cmd,
 				void __user *p, int compat_mode)
 {
-	struct evdev_list *list = file->private_data;
-	struct evdev *evdev = list->evdev;
+	struct evdev_client *client = file->private_data;
+	struct evdev *evdev = client->evdev;
 	struct input_dev *dev = evdev->handle.dev;
 	struct input_absinfo abs;
 	struct ff_effect effect;
@@ -434,32 +451,21 @@
 		case EVIOCGKEYCODE:
 			if (get_user(t, ip))
 				return -EFAULT;
-			if (t < 0 || t >= dev->keycodemax || !dev->keycodesize)
-				return -EINVAL;
-			if (put_user(INPUT_KEYCODE(dev, t), ip + 1))
+
+			error = dev->getkeycode(dev, t, &v);
+			if (error)
+				return error;
+
+			if (put_user(v, ip + 1))
 				return -EFAULT;
+
 			return 0;
 
 		case EVIOCSKEYCODE:
-			if (get_user(t, ip))
+			if (get_user(t, ip) || get_user(v, ip + 1))
 				return -EFAULT;
-			if (t < 0 || t >= dev->keycodemax || !dev->keycodesize)
-				return -EINVAL;
-			if (get_user(v, ip + 1))
-				return -EFAULT;
-			if (v < 0 || v > KEY_MAX)
-				return -EINVAL;
-			if (dev->keycodesize < sizeof(v) && (v >> (dev->keycodesize * 8)))
-				return -EINVAL;
 
-			u = SET_INPUT_KEYCODE(dev, t, v);
-			clear_bit(u, dev->keybit);
-			set_bit(v, dev->keybit);
-			for (i = 0; i < dev->keycodemax; i++)
-				if (INPUT_KEYCODE(dev, i) == u)
-					set_bit(u, dev->keybit);
-
-			return 0;
+			return dev->setkeycode(dev, t, v);
 
 		case EVIOCSFF:
 			if (copy_from_user(&effect, p, sizeof(effect)))
@@ -487,10 +493,10 @@
 					return -EBUSY;
 				if (input_grab_device(&evdev->handle))
 					return -EBUSY;
-				evdev->grab = list;
+				evdev->grab = client;
 				return 0;
 			} else {
-				if (evdev->grab != list)
+				if (evdev->grab != client)
 					return -EINVAL;
 				input_release_device(&evdev->handle);
 				evdev->grab = NULL;
@@ -616,23 +622,26 @@
 	.flush =	evdev_flush
 };
 
-static struct input_handle *evdev_connect(struct input_handler *handler, struct input_dev *dev,
-					  const struct input_device_id *id)
+static int evdev_connect(struct input_handler *handler, struct input_dev *dev,
+			 const struct input_device_id *id)
 {
 	struct evdev *evdev;
 	struct class_device *cdev;
+	dev_t devt;
 	int minor;
+	int error;
 
 	for (minor = 0; minor < EVDEV_MINORS && evdev_table[minor]; minor++);
 	if (minor == EVDEV_MINORS) {
 		printk(KERN_ERR "evdev: no more free evdev devices\n");
-		return NULL;
+		return -ENFILE;
 	}
 
-	if (!(evdev = kzalloc(sizeof(struct evdev), GFP_KERNEL)))
-		return NULL;
+	evdev = kzalloc(sizeof(struct evdev), GFP_KERNEL);
+	if (!evdev)
+		return -ENOMEM;
 
-	INIT_LIST_HEAD(&evdev->list);
+	INIT_LIST_HEAD(&evdev->client_list);
 	init_waitqueue_head(&evdev->wait);
 
 	evdev->exist = 1;
@@ -645,23 +654,45 @@
 
 	evdev_table[minor] = evdev;
 
-	cdev = class_device_create(&input_class, &dev->cdev,
-			MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor),
-			dev->cdev.dev, evdev->name);
+	devt = MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor),
+
+	cdev = class_device_create(&input_class, &dev->cdev, devt,
+				   dev->cdev.dev, evdev->name);
+	if (IS_ERR(cdev)) {
+		error = PTR_ERR(cdev);
+		goto err_free_evdev;
+	}
 
 	/* temporary symlink to keep userspace happy */
-	sysfs_create_link(&input_class.subsys.kset.kobj, &cdev->kobj,
-			  evdev->name);
+	error = sysfs_create_link(&input_class.subsys.kobj,
+				  &cdev->kobj, evdev->name);
+	if (error)
+		goto err_cdev_destroy;
 
-	return &evdev->handle;
+	error = input_register_handle(&evdev->handle);
+	if (error)
+		goto err_remove_link;
+
+	return 0;
+
+ err_remove_link:
+	sysfs_remove_link(&input_class.subsys.kobj, evdev->name);
+ err_cdev_destroy:
+	class_device_destroy(&input_class, devt);
+ err_free_evdev:
+	kfree(evdev);
+	evdev_table[minor] = NULL;
+	return error;
 }
 
 static void evdev_disconnect(struct input_handle *handle)
 {
 	struct evdev *evdev = handle->private;
-	struct evdev_list *list;
+	struct evdev_client *client;
 
-	sysfs_remove_link(&input_class.subsys.kset.kobj, evdev->name);
+	input_unregister_handle(handle);
+
+	sysfs_remove_link(&input_class.subsys.kobj, evdev->name);
 	class_device_destroy(&input_class,
 			MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + evdev->minor));
 	evdev->exist = 0;
@@ -670,8 +701,8 @@
 		input_flush_device(handle, NULL);
 		input_close_device(handle);
 		wake_up_interruptible(&evdev->wait);
-		list_for_each_entry(list, &evdev->list, node)
-			kill_fasync(&list->fasync, SIGIO, POLL_HUP);
+		list_for_each_entry(client, &evdev->client_list, node)
+			kill_fasync(&client->fasync, SIGIO, POLL_HUP);
 	} else
 		evdev_free(evdev);
 }
diff --git a/drivers/input/input.c b/drivers/input/input.c
index a9a706f..915e9ab 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -299,12 +299,87 @@
 }
 EXPORT_SYMBOL(input_close_device);
 
-static void input_link_handle(struct input_handle *handle)
+static int input_fetch_keycode(struct input_dev *dev, int scancode)
 {
-	list_add_tail(&handle->d_node, &handle->dev->h_list);
-	list_add_tail(&handle->h_node, &handle->handler->h_list);
+	switch (dev->keycodesize) {
+		case 1:
+			return ((u8 *)dev->keycode)[scancode];
+
+		case 2:
+			return ((u16 *)dev->keycode)[scancode];
+
+		default:
+			return ((u32 *)dev->keycode)[scancode];
+	}
 }
 
+static int input_default_getkeycode(struct input_dev *dev,
+				    int scancode, int *keycode)
+{
+	if (!dev->keycodesize)
+		return -EINVAL;
+
+	if (scancode < 0 || scancode >= dev->keycodemax)
+		return -EINVAL;
+
+	*keycode = input_fetch_keycode(dev, scancode);
+
+	return 0;
+}
+
+static int input_default_setkeycode(struct input_dev *dev,
+				    int scancode, int keycode)
+{
+	int old_keycode;
+	int i;
+
+	if (scancode < 0 || scancode >= dev->keycodemax)
+		return -EINVAL;
+
+	if (keycode < 0 || keycode > KEY_MAX)
+		return -EINVAL;
+
+	if (!dev->keycodesize)
+		return -EINVAL;
+
+	if (dev->keycodesize < sizeof(keycode) && (keycode >> (dev->keycodesize * 8)))
+		return -EINVAL;
+
+	switch (dev->keycodesize) {
+		case 1: {
+			u8 *k = (u8 *)dev->keycode;
+			old_keycode = k[scancode];
+			k[scancode] = keycode;
+			break;
+		}
+		case 2: {
+			u16 *k = (u16 *)dev->keycode;
+			old_keycode = k[scancode];
+			k[scancode] = keycode;
+			break;
+		}
+		default: {
+			u32 *k = (u32 *)dev->keycode;
+			old_keycode = k[scancode];
+			k[scancode] = keycode;
+			break;
+		}
+	}
+
+	clear_bit(old_keycode, dev->keybit);
+	set_bit(keycode, dev->keybit);
+
+	for (i = 0; i < dev->keycodemax; i++) {
+		if (input_fetch_keycode(dev, i) == old_keycode) {
+			set_bit(old_keycode, dev->keybit);
+			break; /* Setting the bit twice is useless, so break */
+		}
+	}
+
+	return 0;
+}
+
+
 #define MATCH_BIT(bit, max) \
 		for (i = 0; i < NBITS(max); i++) \
 			if ((id->bit[i] & dev->bit[i]) != id->bit[i]) \
@@ -351,6 +426,29 @@
 	return NULL;
 }
 
+static int input_attach_handler(struct input_dev *dev, struct input_handler *handler)
+{
+	const struct input_device_id *id;
+	int error;
+
+	if (handler->blacklist && input_match_device(handler->blacklist, dev))
+		return -ENODEV;
+
+	id = input_match_device(handler->id_table, dev);
+	if (!id)
+		return -ENODEV;
+
+	error = handler->connect(handler, dev, id);
+	if (error && error != -ENODEV)
+		printk(KERN_ERR
+			"input: failed to attach handler %s to device %s, "
+			"error: %d\n",
+			handler->name, kobject_name(&dev->cdev.kobj), error);
+
+	return error;
+}
+
+
 #ifdef CONFIG_PROC_FS
 
 static struct proc_dir_entry *proc_bus_input_dir;
@@ -439,6 +537,7 @@
 	seq_printf(seq, "N: Name=\"%s\"\n", dev->name ? dev->name : "");
 	seq_printf(seq, "P: Phys=%s\n", dev->phys ? dev->phys : "");
 	seq_printf(seq, "S: Sysfs=%s\n", path ? path : "");
+	seq_printf(seq, "U: Uniq=%s\n", dev->uniq ? dev->uniq : "");
 	seq_printf(seq, "H: Handlers=");
 
 	list_for_each_entry(handle, &dev->h_list, d_node)
@@ -753,6 +852,13 @@
 	.attrs	= input_dev_caps_attrs,
 };
 
+static struct attribute_group *input_dev_attr_groups[] = {
+	&input_dev_attr_group,
+	&input_dev_id_attr_group,
+	&input_dev_caps_attr_group,
+	NULL
+};
+
 static void input_dev_release(struct class_device *class_dev)
 {
 	struct input_dev *dev = to_input_dev(class_dev);
@@ -906,6 +1012,7 @@
 	dev = kzalloc(sizeof(struct input_dev), GFP_KERNEL);
 	if (dev) {
 		dev->cdev.class = &input_class;
+		dev->cdev.groups = input_dev_attr_groups;
 		class_device_initialize(&dev->cdev);
 		mutex_init(&dev->mutex);
 		INIT_LIST_HEAD(&dev->h_list);
@@ -934,23 +1041,71 @@
  */
 void input_free_device(struct input_dev *dev)
 {
-	if (dev) {
-
-		mutex_lock(&dev->mutex);
-		dev->name = dev->phys = dev->uniq = NULL;
-		mutex_unlock(&dev->mutex);
-
+	if (dev)
 		input_put_device(dev);
-	}
 }
 EXPORT_SYMBOL(input_free_device);
 
+/**
+ * input_set_capability - mark device as capable of a certain event
+ * @dev: device that is capable of emitting or accepting event
+ * @type: type of the event (EV_KEY, EV_REL, etc...)
+ * @code: event code
+ *
+ * In addition to setting up corresponding bit in appropriate capability
+ * bitmap the function also adjusts dev->evbit.
+ */
+void input_set_capability(struct input_dev *dev, unsigned int type, unsigned int code)
+{
+	switch (type) {
+	case EV_KEY:
+		__set_bit(code, dev->keybit);
+		break;
+
+	case EV_REL:
+		__set_bit(code, dev->relbit);
+		break;
+
+	case EV_ABS:
+		__set_bit(code, dev->absbit);
+		break;
+
+	case EV_MSC:
+		__set_bit(code, dev->mscbit);
+		break;
+
+	case EV_SW:
+		__set_bit(code, dev->swbit);
+		break;
+
+	case EV_LED:
+		__set_bit(code, dev->ledbit);
+		break;
+
+	case EV_SND:
+		__set_bit(code, dev->sndbit);
+		break;
+
+	case EV_FF:
+		__set_bit(code, dev->ffbit);
+		break;
+
+	default:
+		printk(KERN_ERR
+			"input_set_capability: unknown type %u (code %u)\n",
+			type, code);
+		dump_stack();
+		return;
+	}
+
+	__set_bit(type, dev->evbit);
+}
+EXPORT_SYMBOL(input_set_capability);
+
 int input_register_device(struct input_dev *dev)
 {
 	static atomic_t input_no = ATOMIC_INIT(0);
-	struct input_handle *handle;
 	struct input_handler *handler;
-	const struct input_device_id *id;
 	const char *path;
 	int error;
 
@@ -969,55 +1124,41 @@
 		dev->rep[REP_PERIOD] = 33;
 	}
 
+	if (!dev->getkeycode)
+		dev->getkeycode = input_default_getkeycode;
+
+	if (!dev->setkeycode)
+		dev->setkeycode = input_default_setkeycode;
+
 	list_add_tail(&dev->node, &input_dev_list);
 
 	snprintf(dev->cdev.class_id, sizeof(dev->cdev.class_id),
 		 "input%ld", (unsigned long) atomic_inc_return(&input_no) - 1);
 
+	if (!dev->cdev.dev)
+		dev->cdev.dev = dev->dev.parent;
+
 	error = class_device_add(&dev->cdev);
 	if (error)
 		return error;
 
-	error = sysfs_create_group(&dev->cdev.kobj, &input_dev_attr_group);
-	if (error)
-		goto fail1;
-
-	error = sysfs_create_group(&dev->cdev.kobj, &input_dev_id_attr_group);
-	if (error)
-		goto fail2;
-
-	error = sysfs_create_group(&dev->cdev.kobj, &input_dev_caps_attr_group);
-	if (error)
-		goto fail3;
-
 	path = kobject_get_path(&dev->cdev.kobj, GFP_KERNEL);
 	printk(KERN_INFO "input: %s as %s\n",
 		dev->name ? dev->name : "Unspecified device", path ? path : "N/A");
 	kfree(path);
 
 	list_for_each_entry(handler, &input_handler_list, node)
-		if (!handler->blacklist || !input_match_device(handler->blacklist, dev))
-			if ((id = input_match_device(handler->id_table, dev)))
-				if ((handle = handler->connect(handler, dev, id))) {
-					input_link_handle(handle);
-					if (handler->start)
-						handler->start(handle);
-				}
+		input_attach_handler(dev, handler);
 
 	input_wakeup_procfs_readers();
 
 	return 0;
-
- fail3:	sysfs_remove_group(&dev->cdev.kobj, &input_dev_id_attr_group);
- fail2:	sysfs_remove_group(&dev->cdev.kobj, &input_dev_attr_group);
- fail1:	class_device_del(&dev->cdev);
-	return error;
 }
 EXPORT_SYMBOL(input_register_device);
 
 void input_unregister_device(struct input_dev *dev)
 {
-	struct list_head *node, *next;
+	struct input_handle *handle, *next;
 	int code;
 
 	for (code = 0; code <= KEY_MAX; code++)
@@ -1027,19 +1168,12 @@
 
 	del_timer_sync(&dev->timer);
 
-	list_for_each_safe(node, next, &dev->h_list) {
-		struct input_handle * handle = to_handle(node);
-		list_del_init(&handle->d_node);
-		list_del_init(&handle->h_node);
+	list_for_each_entry_safe(handle, next, &dev->h_list, d_node)
 		handle->handler->disconnect(handle);
-	}
+	WARN_ON(!list_empty(&dev->h_list));
 
 	list_del_init(&dev->node);
 
-	sysfs_remove_group(&dev->cdev.kobj, &input_dev_caps_attr_group);
-	sysfs_remove_group(&dev->cdev.kobj, &input_dev_id_attr_group);
-	sysfs_remove_group(&dev->cdev.kobj, &input_dev_attr_group);
-
 	class_device_unregister(&dev->cdev);
 
 	input_wakeup_procfs_readers();
@@ -1049,8 +1183,6 @@
 int input_register_handler(struct input_handler *handler)
 {
 	struct input_dev *dev;
-	struct input_handle *handle;
-	const struct input_device_id *id;
 
 	INIT_LIST_HEAD(&handler->h_list);
 
@@ -1064,13 +1196,7 @@
 	list_add_tail(&handler->node, &input_handler_list);
 
 	list_for_each_entry(dev, &input_dev_list, node)
-		if (!handler->blacklist || !input_match_device(handler->blacklist, dev))
-			if ((id = input_match_device(handler->id_table, dev)))
-				if ((handle = handler->connect(handler, dev, id))) {
-					input_link_handle(handle);
-					if (handler->start)
-						handler->start(handle);
-				}
+		input_attach_handler(dev, handler);
 
 	input_wakeup_procfs_readers();
 	return 0;
@@ -1079,14 +1205,11 @@
 
 void input_unregister_handler(struct input_handler *handler)
 {
-	struct list_head *node, *next;
+	struct input_handle *handle, *next;
 
-	list_for_each_safe(node, next, &handler->h_list) {
-		struct input_handle * handle = to_handle_h(node);
-		list_del_init(&handle->h_node);
-		list_del_init(&handle->d_node);
+	list_for_each_entry_safe(handle, next, &handler->h_list, h_node)
 		handler->disconnect(handle);
-	}
+	WARN_ON(!list_empty(&handler->h_list));
 
 	list_del_init(&handler->node);
 
@@ -1097,6 +1220,27 @@
 }
 EXPORT_SYMBOL(input_unregister_handler);
 
+int input_register_handle(struct input_handle *handle)
+{
+	struct input_handler *handler = handle->handler;
+
+	list_add_tail(&handle->d_node, &handle->dev->h_list);
+	list_add_tail(&handle->h_node, &handler->h_list);
+
+	if (handler->start)
+		handler->start(handle);
+
+	return 0;
+}
+EXPORT_SYMBOL(input_register_handle);
+
+void input_unregister_handle(struct input_handle *handle)
+{
+	list_del_init(&handle->h_node);
+	list_del_init(&handle->d_node);
+}
+EXPORT_SYMBOL(input_unregister_handle);
+
 static int input_open_file(struct inode *inode, struct file *file)
 {
 	struct input_handler *handler = input_table[iminor(inode) >> 5];
diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c
index 9f3529a..9bcc542 100644
--- a/drivers/input/joydev.c
+++ b/drivers/input/joydev.c
@@ -43,7 +43,7 @@
 	char name[16];
 	struct input_handle handle;
 	wait_queue_head_t wait;
-	struct list_head list;
+	struct list_head client_list;
 	struct js_corr corr[ABS_MAX + 1];
 	struct JS_DATA_SAVE_TYPE glue;
 	int nabs;
@@ -55,7 +55,7 @@
 	__s16 abs[ABS_MAX + 1];
 };
 
-struct joydev_list {
+struct joydev_client {
 	struct js_event buffer[JOYDEV_BUFFER_SIZE];
 	int head;
 	int tail;
@@ -87,7 +87,7 @@
 static void joydev_event(struct input_handle *handle, unsigned int type, unsigned int code, int value)
 {
 	struct joydev *joydev = handle->private;
-	struct joydev_list *list;
+	struct joydev_client *client;
 	struct js_event event;
 
 	switch (type) {
@@ -115,15 +115,15 @@
 
 	event.time = jiffies_to_msecs(jiffies);
 
-	list_for_each_entry(list, &joydev->list, node) {
+	list_for_each_entry(client, &joydev->client_list, node) {
 
-		memcpy(list->buffer + list->head, &event, sizeof(struct js_event));
+		memcpy(client->buffer + client->head, &event, sizeof(struct js_event));
 
-		if (list->startup == joydev->nabs + joydev->nkey)
-			if (list->tail == (list->head = (list->head + 1) & (JOYDEV_BUFFER_SIZE - 1)))
-				list->startup = 0;
+		if (client->startup == joydev->nabs + joydev->nkey)
+			if (client->tail == (client->head = (client->head + 1) & (JOYDEV_BUFFER_SIZE - 1)))
+				client->startup = 0;
 
-		kill_fasync(&list->fasync, SIGIO, POLL_IN);
+		kill_fasync(&client->fasync, SIGIO, POLL_IN);
 	}
 
 	wake_up_interruptible(&joydev->wait);
@@ -132,9 +132,9 @@
 static int joydev_fasync(int fd, struct file *file, int on)
 {
 	int retval;
-	struct joydev_list *list = file->private_data;
+	struct joydev_client *client = file->private_data;
 
-	retval = fasync_helper(fd, file, on, &list->fasync);
+	retval = fasync_helper(fd, file, on, &client->fasync);
 
 	return retval < 0 ? retval : 0;
 }
@@ -145,60 +145,73 @@
 	kfree(joydev);
 }
 
-static int joydev_release(struct inode * inode, struct file * file)
+static int joydev_release(struct inode *inode, struct file *file)
 {
-	struct joydev_list *list = file->private_data;
+	struct joydev_client *client = file->private_data;
+	struct joydev *joydev = client->joydev;
 
 	joydev_fasync(-1, file, 0);
 
-	list_del(&list->node);
+	list_del(&client->node);
+	kfree(client);
 
-	if (!--list->joydev->open) {
-		if (list->joydev->exist)
-			input_close_device(&list->joydev->handle);
+	if (!--joydev->open) {
+		if (joydev->exist)
+			input_close_device(&joydev->handle);
 		else
-			joydev_free(list->joydev);
+			joydev_free(joydev);
 	}
 
-	kfree(list);
 	return 0;
 }
 
 static int joydev_open(struct inode *inode, struct file *file)
 {
-	struct joydev_list *list;
+	struct joydev_client *client;
+	struct joydev *joydev;
 	int i = iminor(inode) - JOYDEV_MINOR_BASE;
+	int error;
 
-	if (i >= JOYDEV_MINORS || !joydev_table[i])
+	if (i >= JOYDEV_MINORS)
 		return -ENODEV;
 
-	if (!(list = kzalloc(sizeof(struct joydev_list), GFP_KERNEL)))
+	joydev = joydev_table[i];
+	if (!joydev || !joydev->exist)
+		return -ENODEV;
+
+	client = kzalloc(sizeof(struct joydev_client), GFP_KERNEL);
+	if (!client)
 		return -ENOMEM;
 
-	list->joydev = joydev_table[i];
-	list_add_tail(&list->node, &joydev_table[i]->list);
-	file->private_data = list;
+	client->joydev = joydev;
+	list_add_tail(&client->node, &joydev->client_list);
 
-	if (!list->joydev->open++)
-		if (list->joydev->exist)
-			input_open_device(&list->joydev->handle);
+	if (!joydev->open++ && joydev->exist) {
+		error = input_open_device(&joydev->handle);
+		if (error) {
+			list_del(&client->node);
+			kfree(client);
+			return error;
+		}
+	}
 
+	file->private_data = client;
 	return 0;
 }
 
-static ssize_t joydev_write(struct file * file, const char __user * buffer, size_t count, loff_t *ppos)
+static ssize_t joydev_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
 {
 	return -EINVAL;
 }
 
 static ssize_t joydev_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
 {
-	struct joydev_list *list = file->private_data;
-	struct joydev *joydev = list->joydev;
+	struct joydev_client *client = file->private_data;
+	struct joydev *joydev = client->joydev;
 	struct input_dev *input = joydev->handle.dev;
 	int retval = 0;
 
-	if (!list->joydev->exist)
+	if (!joydev->exist)
 		return -ENODEV;
 
 	if (count < sizeof(struct js_event))
@@ -217,56 +230,55 @@
 		if (copy_to_user(buf, &data, sizeof(struct JS_DATA_TYPE)))
 			return -EFAULT;
 
-		list->startup = 0;
-		list->tail = list->head;
+		client->startup = 0;
+		client->tail = client->head;
 
 		return sizeof(struct JS_DATA_TYPE);
 	}
 
-	if (list->startup == joydev->nabs + joydev->nkey &&
-	    list->head == list->tail && (file->f_flags & O_NONBLOCK))
+	if (client->startup == joydev->nabs + joydev->nkey &&
+	    client->head == client->tail && (file->f_flags & O_NONBLOCK))
 		return -EAGAIN;
 
-	retval = wait_event_interruptible(list->joydev->wait,
-					  !list->joydev->exist ||
-					  list->startup < joydev->nabs + joydev->nkey ||
-					  list->head != list->tail);
-
+	retval = wait_event_interruptible(joydev->wait,
+					  !joydev->exist ||
+					  client->startup < joydev->nabs + joydev->nkey ||
+					  client->head != client->tail);
 	if (retval)
 		return retval;
 
-	if (!list->joydev->exist)
+	if (!joydev->exist)
 		return -ENODEV;
 
-	while (list->startup < joydev->nabs + joydev->nkey && retval + sizeof(struct js_event) <= count) {
+	while (client->startup < joydev->nabs + joydev->nkey && retval + sizeof(struct js_event) <= count) {
 
 		struct js_event event;
 
 		event.time = jiffies_to_msecs(jiffies);
 
-		if (list->startup < joydev->nkey) {
+		if (client->startup < joydev->nkey) {
 			event.type = JS_EVENT_BUTTON | JS_EVENT_INIT;
-			event.number = list->startup;
+			event.number = client->startup;
 			event.value = !!test_bit(joydev->keypam[event.number], input->key);
 		} else {
 			event.type = JS_EVENT_AXIS | JS_EVENT_INIT;
-			event.number = list->startup - joydev->nkey;
+			event.number = client->startup - joydev->nkey;
 			event.value = joydev->abs[event.number];
 		}
 
 		if (copy_to_user(buf + retval, &event, sizeof(struct js_event)))
 			return -EFAULT;
 
-		list->startup++;
+		client->startup++;
 		retval += sizeof(struct js_event);
 	}
 
-	while (list->head != list->tail && retval + sizeof(struct js_event) <= count) {
+	while (client->head != client->tail && retval + sizeof(struct js_event) <= count) {
 
-		if (copy_to_user(buf + retval, list->buffer + list->tail, sizeof(struct js_event)))
+		if (copy_to_user(buf + retval, client->buffer + client->tail, sizeof(struct js_event)))
 			return -EFAULT;
 
-		list->tail = (list->tail + 1) & (JOYDEV_BUFFER_SIZE - 1);
+		client->tail = (client->tail + 1) & (JOYDEV_BUFFER_SIZE - 1);
 		retval += sizeof(struct js_event);
 	}
 
@@ -276,11 +288,12 @@
 /* No kernel lock - fine */
 static unsigned int joydev_poll(struct file *file, poll_table *wait)
 {
-	struct joydev_list *list = file->private_data;
+	struct joydev_client *client = file->private_data;
+	struct joydev *joydev = client->joydev;
 
-	poll_wait(file, &list->joydev->wait, wait);
-	return ((list->head != list->tail || list->startup < list->joydev->nabs + list->joydev->nkey) ?
-		(POLLIN | POLLRDNORM) : 0) | (list->joydev->exist ? 0 : (POLLHUP | POLLERR));
+	poll_wait(file, &joydev->wait, wait);
+	return ((client->head != client->tail || client->startup < joydev->nabs + joydev->nkey) ?
+		(POLLIN | POLLRDNORM) : 0) | (joydev->exist ? 0 : (POLLHUP | POLLERR));
 }
 
 static int joydev_ioctl_common(struct joydev *joydev, unsigned int cmd, void __user *argp)
@@ -374,8 +387,8 @@
 #ifdef CONFIG_COMPAT
 static long joydev_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
-	struct joydev_list *list = file->private_data;
-	struct joydev *joydev = list->joydev;
+	struct joydev_client *client = file->private_data;
+	struct joydev *joydev = client->joydev;
 	void __user *argp = (void __user *)arg;
 	s32 tmp32;
 	struct JS_DATA_SAVE_TYPE_32 ds32;
@@ -428,8 +441,8 @@
 
 static int joydev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
 {
-	struct joydev_list *list = file->private_data;
-	struct joydev *joydev = list->joydev;
+	struct joydev_client *client = file->private_data;
+	struct joydev *joydev = client->joydev;
 	void __user *argp = (void __user *)arg;
 
 	if (!joydev->exist)
@@ -465,23 +478,26 @@
 	.fasync =	joydev_fasync,
 };
 
-static struct input_handle *joydev_connect(struct input_handler *handler, struct input_dev *dev,
-					   const struct input_device_id *id)
+static int joydev_connect(struct input_handler *handler, struct input_dev *dev,
+			  const struct input_device_id *id)
 {
 	struct joydev *joydev;
 	struct class_device *cdev;
+	dev_t devt;
 	int i, j, t, minor;
+	int error;
 
 	for (minor = 0; minor < JOYDEV_MINORS && joydev_table[minor]; minor++);
 	if (minor == JOYDEV_MINORS) {
 		printk(KERN_ERR "joydev: no more free joydev devices\n");
-		return NULL;
+		return -ENFILE;
 	}
 
-	if (!(joydev = kzalloc(sizeof(struct joydev), GFP_KERNEL)))
-		return NULL;
+	joydev = kzalloc(sizeof(struct joydev), GFP_KERNEL);
+	if (!joydev)
+		return -ENOMEM;
 
-	INIT_LIST_HEAD(&joydev->list);
+	INIT_LIST_HEAD(&joydev->client_list);
 	init_waitqueue_head(&joydev->wait);
 
 	joydev->minor = minor;
@@ -534,31 +550,54 @@
 
 	joydev_table[minor] = joydev;
 
-	cdev = class_device_create(&input_class, &dev->cdev,
-			MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor),
-			dev->cdev.dev, joydev->name);
+	devt = MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor),
+
+	cdev = class_device_create(&input_class, &dev->cdev, devt,
+				   dev->cdev.dev, joydev->name);
+	if (IS_ERR(cdev)) {
+		error = PTR_ERR(cdev);
+		goto err_free_joydev;
+	}
 
 	/* temporary symlink to keep userspace happy */
-	sysfs_create_link(&input_class.subsys.kset.kobj, &cdev->kobj,
-			  joydev->name);
+	error = sysfs_create_link(&input_class.subsys.kobj,
+				  &cdev->kobj, joydev->name);
+	if (error)
+		goto err_cdev_destroy;
 
-	return &joydev->handle;
+	error = input_register_handle(&joydev->handle);
+	if (error)
+		goto err_remove_link;
+
+	return 0;
+
+ err_remove_link:
+	sysfs_remove_link(&input_class.subsys.kobj, joydev->name);
+ err_cdev_destroy:
+	class_device_destroy(&input_class, devt);
+ err_free_joydev:
+	joydev_table[minor] = NULL;
+	kfree(joydev);
+	return error;
 }
 
+
 static void joydev_disconnect(struct input_handle *handle)
 {
 	struct joydev *joydev = handle->private;
-	struct joydev_list *list;
+	struct joydev_client *client;
 
-	sysfs_remove_link(&input_class.subsys.kset.kobj, joydev->name);
+	input_unregister_handle(handle);
+
+	sysfs_remove_link(&input_class.subsys.kobj, joydev->name);
 	class_device_destroy(&input_class, MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + joydev->minor));
 	joydev->exist = 0;
 
 	if (joydev->open) {
 		input_close_device(handle);
 		wake_up_interruptible(&joydev->wait);
-		list_for_each_entry(list, &joydev->list, node)
-			kill_fasync(&list->fasync, SIGIO, POLL_HUP);
+		list_for_each_entry(client, &joydev->client_list, node)
+			kill_fasync(&client->fasync, SIGIO, POLL_HUP);
 	} else
 		joydev_free(joydev);
 }
diff --git a/drivers/input/joystick/a3d.c b/drivers/input/joystick/a3d.c
index b11a4bb..ff701ab 100644
--- a/drivers/input/joystick/a3d.c
+++ b/drivers/input/joystick/a3d.c
@@ -241,7 +241,7 @@
 
 static int a3d_open(struct input_dev *dev)
 {
-	struct a3d *a3d = dev->private;
+	struct a3d *a3d = input_get_drvdata(dev);
 
 	gameport_start_polling(a3d->gameport);
 	return 0;
@@ -253,7 +253,7 @@
 
 static void a3d_close(struct input_dev *dev)
 {
-	struct a3d *a3d = dev->private;
+	struct a3d *a3d = input_get_drvdata(dev);
 
 	gameport_stop_polling(a3d->gameport);
 }
@@ -314,11 +314,12 @@
 	input_dev->id.vendor = GAMEPORT_ID_VENDOR_MADCATZ;
 	input_dev->id.product = a3d->mode;
 	input_dev->id.version = 0x0100;
-	input_dev->cdev.dev = &gameport->dev;
-	input_dev->private = a3d;
+	input_dev->dev.parent = &gameport->dev;
 	input_dev->open = a3d_open;
 	input_dev->close = a3d_close;
 
+	input_set_drvdata(input_dev, a3d);
+
 	if (a3d->mode == A3D_MODE_PXL) {
 
 		int axes[] = { ABS_X, ABS_Y, ABS_THROTTLE, ABS_RUDDER };
diff --git a/drivers/input/joystick/adi.c b/drivers/input/joystick/adi.c
index 6279ced..28140c4 100644
--- a/drivers/input/joystick/adi.c
+++ b/drivers/input/joystick/adi.c
@@ -290,7 +290,7 @@
 
 static int adi_open(struct input_dev *dev)
 {
-	struct adi_port *port = dev->private;
+	struct adi_port *port = input_get_drvdata(dev);
 
 	gameport_start_polling(port->gameport);
 	return 0;
@@ -302,7 +302,7 @@
 
 static void adi_close(struct input_dev *dev)
 {
-	struct adi_port *port = dev->private;
+	struct adi_port *port = input_get_drvdata(dev);
 
 	gameport_stop_polling(port->gameport);
 }
@@ -424,8 +424,9 @@
 	input_dev->id.vendor = GAMEPORT_ID_VENDOR_LOGITECH;
 	input_dev->id.product = adi->id;
 	input_dev->id.version = 0x0100;
-	input_dev->cdev.dev = &port->gameport->dev;
-	input_dev->private = port;
+	input_dev->dev.parent = &port->gameport->dev;
+
+	input_set_drvdata(input_dev, port);
 
 	input_dev->open = adi_open;
 	input_dev->close = adi_close;
diff --git a/drivers/input/joystick/analog.c b/drivers/input/joystick/analog.c
index 51f1e4b..1c1afb5 100644
--- a/drivers/input/joystick/analog.c
+++ b/drivers/input/joystick/analog.c
@@ -343,7 +343,7 @@
 
 static int analog_open(struct input_dev *dev)
 {
-	struct analog_port *port = dev->private;
+	struct analog_port *port = input_get_drvdata(dev);
 
 	gameport_start_polling(port->gameport);
 	return 0;
@@ -355,7 +355,7 @@
 
 static void analog_close(struct input_dev *dev)
 {
-	struct analog_port *port = dev->private;
+	struct analog_port *port = input_get_drvdata(dev);
 
 	gameport_stop_polling(port->gameport);
 }
@@ -449,10 +449,13 @@
 	input_dev->id.vendor = GAMEPORT_ID_VENDOR_ANALOG;
 	input_dev->id.product = analog->mask >> 4;
 	input_dev->id.version = 0x0100;
+	input_dev->dev.parent = &port->gameport->dev;
+
+	input_set_drvdata(input_dev, port);
 
 	input_dev->open = analog_open;
 	input_dev->close = analog_close;
-	input_dev->private = port;
+
 	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
 
 	for (i = j = 0; i < 4; i++)
diff --git a/drivers/input/joystick/cobra.c b/drivers/input/joystick/cobra.c
index 034ec39..d3352a8 100644
--- a/drivers/input/joystick/cobra.c
+++ b/drivers/input/joystick/cobra.c
@@ -142,7 +142,7 @@
 
 static int cobra_open(struct input_dev *dev)
 {
-	struct cobra *cobra = dev->private;
+	struct cobra *cobra = input_get_drvdata(dev);
 
 	gameport_start_polling(cobra->gameport);
 	return 0;
@@ -150,7 +150,7 @@
 
 static void cobra_close(struct input_dev *dev)
 {
-	struct cobra *cobra = dev->private;
+	struct cobra *cobra = input_get_drvdata(dev);
 
 	gameport_stop_polling(cobra->gameport);
 }
@@ -211,8 +211,9 @@
 		input_dev->id.vendor = GAMEPORT_ID_VENDOR_CREATIVE;
 		input_dev->id.product = 0x0008;
 		input_dev->id.version = 0x0100;
-		input_dev->cdev.dev = &gameport->dev;
-		input_dev->private = cobra;
+		input_dev->dev.parent = &gameport->dev;
+
+		input_set_drvdata(input_dev, cobra);
 
 		input_dev->open = cobra_open;
 		input_dev->close = cobra_close;
diff --git a/drivers/input/joystick/db9.c b/drivers/input/joystick/db9.c
index b41bd2e..c27593b 100644
--- a/drivers/input/joystick/db9.c
+++ b/drivers/input/joystick/db9.c
@@ -518,7 +518,7 @@
 
 static int db9_open(struct input_dev *dev)
 {
-	struct db9 *db9 = dev->private;
+	struct db9 *db9 = input_get_drvdata(dev);
 	struct parport *port = db9->pd->port;
 	int err;
 
@@ -542,7 +542,7 @@
 
 static void db9_close(struct input_dev *dev)
 {
-	struct db9 *db9 = dev->private;
+	struct db9 *db9 = input_get_drvdata(dev);
 	struct parport *port = db9->pd->port;
 
 	mutex_lock(&db9->mutex);
@@ -625,7 +625,8 @@
 		input_dev->id.vendor = 0x0002;
 		input_dev->id.product = mode;
 		input_dev->id.version = 0x0100;
-		input_dev->private = db9;
+
+		input_set_drvdata(input_dev, db9);
 
 		input_dev->open = db9_open;
 		input_dev->close = db9_close;
diff --git a/drivers/input/joystick/gamecon.c b/drivers/input/joystick/gamecon.c
index 711e4b3..c71b58f 100644
--- a/drivers/input/joystick/gamecon.c
+++ b/drivers/input/joystick/gamecon.c
@@ -591,7 +591,7 @@
 
 static int gc_open(struct input_dev *dev)
 {
-	struct gc *gc = dev->private;
+	struct gc *gc = input_get_drvdata(dev);
 	int err;
 
 	err = mutex_lock_interruptible(&gc->mutex);
@@ -610,7 +610,7 @@
 
 static void gc_close(struct input_dev *dev)
 {
-	struct gc *gc = dev->private;
+	struct gc *gc = input_get_drvdata(dev);
 
 	mutex_lock(&gc->mutex);
 	if (!--gc->used) {
@@ -646,7 +646,8 @@
 	input_dev->id.vendor = 0x0001;
 	input_dev->id.product = pad_type;
 	input_dev->id.version = 0x0100;
-	input_dev->private = gc;
+
+	input_set_drvdata(input_dev, gc);
 
 	input_dev->open = gc_open;
 	input_dev->close = gc_close;
diff --git a/drivers/input/joystick/gf2k.c b/drivers/input/joystick/gf2k.c
index bacbab5d..d514aeb 100644
--- a/drivers/input/joystick/gf2k.c
+++ b/drivers/input/joystick/gf2k.c
@@ -220,7 +220,7 @@
 
 static int gf2k_open(struct input_dev *dev)
 {
-	struct gf2k *gf2k = dev->private;
+	struct gf2k *gf2k = input_get_drvdata(dev);
 
 	gameport_start_polling(gf2k->gameport);
 	return 0;
@@ -228,7 +228,7 @@
 
 static void gf2k_close(struct input_dev *dev)
 {
-	struct gf2k *gf2k = dev->private;
+	struct gf2k *gf2k = input_get_drvdata(dev);
 
 	gameport_stop_polling(gf2k->gameport);
 }
@@ -308,11 +308,13 @@
 	input_dev->id.vendor = GAMEPORT_ID_VENDOR_GENIUS;
 	input_dev->id.product = gf2k->id;
 	input_dev->id.version = 0x0100;
-	input_dev->cdev.dev = &gameport->dev;
-	input_dev->private = gf2k;
+	input_dev->dev.parent = &gameport->dev;
+
+	input_set_drvdata(input_dev, gf2k);
 
 	input_dev->open = gf2k_open;
 	input_dev->close = gf2k_close;
+
 	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
 
 	for (i = 0; i < gf2k_axes[gf2k->id]; i++)
diff --git a/drivers/input/joystick/grip.c b/drivers/input/joystick/grip.c
index 17a90c4..73eb5ab 100644
--- a/drivers/input/joystick/grip.c
+++ b/drivers/input/joystick/grip.c
@@ -285,7 +285,7 @@
 
 static int grip_open(struct input_dev *dev)
 {
-	struct grip *grip = dev->private;
+	struct grip *grip = input_get_drvdata(dev);
 
 	gameport_start_polling(grip->gameport);
 	return 0;
@@ -293,7 +293,7 @@
 
 static void grip_close(struct input_dev *dev)
 {
-	struct grip *grip = dev->private;
+	struct grip *grip = input_get_drvdata(dev);
 
 	gameport_stop_polling(grip->gameport);
 }
@@ -363,8 +363,9 @@
 		input_dev->id.vendor = GAMEPORT_ID_VENDOR_GRAVIS;
 		input_dev->id.product = grip->mode[i];
 		input_dev->id.version = 0x0100;
-		input_dev->cdev.dev = &gameport->dev;
-		input_dev->private = grip;
+		input_dev->dev.parent = &gameport->dev;
+
+		input_set_drvdata(input_dev, grip);
 
 		input_dev->open = grip_open;
 		input_dev->close = grip_close;
diff --git a/drivers/input/joystick/grip_mp.c b/drivers/input/joystick/grip_mp.c
index 8120a9c..555319e 100644
--- a/drivers/input/joystick/grip_mp.c
+++ b/drivers/input/joystick/grip_mp.c
@@ -562,7 +562,7 @@
 
 static int grip_open(struct input_dev *dev)
 {
-	struct grip_mp *grip = dev->private;
+	struct grip_mp *grip = input_get_drvdata(dev);
 
 	gameport_start_polling(grip->gameport);
 	return 0;
@@ -574,9 +574,9 @@
 
 static void grip_close(struct input_dev *dev)
 {
-	struct grip_mp *grip = dev->private;
+	struct grip_mp *grip = input_get_drvdata(dev);
 
-	gameport_start_polling(grip->gameport);
+	gameport_stop_polling(grip->gameport);
 }
 
 /*
@@ -599,8 +599,9 @@
 	input_dev->id.vendor = GAMEPORT_ID_VENDOR_GRAVIS;
 	input_dev->id.product = 0x0100 + port->mode;
 	input_dev->id.version = 0x0100;
-	input_dev->cdev.dev = &grip->gameport->dev;
-	input_dev->private = grip;
+	input_dev->dev.parent = &grip->gameport->dev;
+
+	input_set_drvdata(input_dev, grip);
 
 	input_dev->open = grip_open;
 	input_dev->close = grip_close;
diff --git a/drivers/input/joystick/guillemot.c b/drivers/input/joystick/guillemot.c
index dbc5d92..d4e8073 100644
--- a/drivers/input/joystick/guillemot.c
+++ b/drivers/input/joystick/guillemot.c
@@ -156,7 +156,7 @@
 
 static int guillemot_open(struct input_dev *dev)
 {
-	struct guillemot *guillemot = dev->private;
+	struct guillemot *guillemot = input_get_drvdata(dev);
 
 	gameport_start_polling(guillemot->gameport);
 	return 0;
@@ -168,7 +168,7 @@
 
 static void guillemot_close(struct input_dev *dev)
 {
-	struct guillemot *guillemot = dev->private;
+	struct guillemot *guillemot = input_get_drvdata(dev);
 
 	gameport_stop_polling(guillemot->gameport);
 }
@@ -231,8 +231,9 @@
 	input_dev->id.vendor = GAMEPORT_ID_VENDOR_GUILLEMOT;
 	input_dev->id.product = guillemot_type[i].id;
 	input_dev->id.version = (int)data[14] << 8 | data[15];
-	input_dev->cdev.dev = &gameport->dev;
-	input_dev->private = guillemot;
+	input_dev->dev.parent = &gameport->dev;
+
+	input_set_drvdata(input_dev, guillemot);
 
 	input_dev->open = guillemot_open;
 	input_dev->close = guillemot_close;
diff --git a/drivers/input/joystick/iforce/iforce-ff.c b/drivers/input/joystick/iforce/iforce-ff.c
index 8fb0c19..f2a4381 100644
--- a/drivers/input/joystick/iforce/iforce-ff.c
+++ b/drivers/input/joystick/iforce/iforce-ff.c
@@ -2,7 +2,7 @@
  * $Id: iforce-ff.c,v 1.9 2002/02/02 19:28:35 jdeneux Exp $
  *
  *  Copyright (c) 2000-2002 Vojtech Pavlik <vojtech@ucw.cz>
- *  Copyright (c) 2001-2002 Johann Deneux <deneux@ifrance.com>
+ *  Copyright (c) 2001-2002, 2007 Johann Deneux <johann.deneux@gmail.com>
  *
  *  USB/RS232 I-Force joysticks and wheels.
  */
@@ -205,7 +205,7 @@
 	int i;
 
 	if (new->type != FF_SPRING && new->type != FF_FRICTION) {
-		printk(KERN_WARNING "iforce.c: bad effect type in need_condition_modifier\n");
+		warn("bad effect type in need_condition_modifier");
 		return 0;
 	}
 
@@ -227,7 +227,7 @@
 static int need_magnitude_modifier(struct ff_effect *old, struct ff_effect *effect)
 {
 	if (effect->type != FF_CONSTANT) {
-		printk(KERN_WARNING "iforce.c: bad effect type in need_envelope_modifier\n");
+		warn("bad effect type in need_envelope_modifier");
 		return 0;
 	}
 
@@ -258,7 +258,7 @@
 		break;
 
 	default:
-		printk(KERN_WARNING "iforce.c: bad effect type in need_envelope_modifier\n");
+		warn("bad effect type in need_envelope_modifier");
 	}
 
 	return 0;
@@ -271,7 +271,7 @@
 static int need_period_modifier(struct ff_effect *old, struct ff_effect *new)
 {
 	if (new->type != FF_PERIODIC) {
-		printk(KERN_WARNING "iforce.c: bad effect type in need_period_modifier\n");
+		warn("bad effect type in need_period_modifier");
 		return 0;
 	}
 	return (old->u.periodic.period != new->u.periodic.period
diff --git a/drivers/input/joystick/iforce/iforce-main.c b/drivers/input/joystick/iforce/iforce-main.c
index 3393a37..fb129c4 100644
--- a/drivers/input/joystick/iforce/iforce-main.c
+++ b/drivers/input/joystick/iforce/iforce-main.c
@@ -2,7 +2,7 @@
  * $Id: iforce-main.c,v 1.19 2002/07/07 10:22:50 jdeneux Exp $
  *
  *  Copyright (c) 2000-2002 Vojtech Pavlik <vojtech@ucw.cz>
- *  Copyright (c) 2001-2002 Johann Deneux <deneux@ifrance.com>
+ *  Copyright (c) 2001-2002, 2007 Johann Deneux <johann.deneux@gmail.com>
  *
  *  USB/RS232 I-Force joysticks and wheels.
  */
@@ -29,7 +29,7 @@
 
 #include "iforce.h"
 
-MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>, Johann Deneux <deneux@ifrance.com>");
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>, Johann Deneux <johann.deneux@gmail.com>");
 MODULE_DESCRIPTION("USB/RS232 I-Force joysticks and wheels driver");
 MODULE_LICENSE("GPL");
 
@@ -220,7 +220,7 @@
 		/* Check: no effects should be present in memory */
 		for (i = 0; i < dev->ff->max_effects; i++) {
 			if (test_bit(FF_CORE_IS_USED, iforce->core_effects[i].flags)) {
-				printk(KERN_WARNING "iforce_release: Device still owns effects\n");
+				warn("iforce_release: Device still owns effects");
 				break;
 			}
 		}
@@ -232,7 +232,7 @@
 	switch (iforce->bus) {
 #ifdef CONFIG_JOYSTICK_IFORCE_USB
 		case IFORCE_USB:
-			usb_unlink_urb(iforce->irq);
+			usb_kill_urb(iforce->irq);
 
 			/* The device was unplugged before the file
 			 * was released */
@@ -287,13 +287,13 @@
 #ifdef CONFIG_JOYSTICK_IFORCE_USB
 	case IFORCE_USB:
 		input_dev->id.bustype = BUS_USB;
-		input_dev->cdev.dev = &iforce->usbdev->dev;
+		input_dev->dev.parent = &iforce->usbdev->dev;
 		break;
 #endif
 #ifdef CONFIG_JOYSTICK_IFORCE_232
 	case IFORCE_232:
 		input_dev->id.bustype = BUS_RS232;
-		input_dev->cdev.dev = &iforce->serio->dev;
+		input_dev->dev.parent = &iforce->serio->dev;
 		break;
 #endif
 	}
@@ -324,7 +324,7 @@
 			break;
 
 	if (i == 20) { /* 5 seconds */
-		printk(KERN_ERR "iforce-main.c: Timeout waiting for response from device.\n");
+		err("Timeout waiting for response from device.");
 		error = -ENODEV;
 		goto fail;
 	}
@@ -336,26 +336,26 @@
 	if (!iforce_get_id_packet(iforce, "M"))
 		input_dev->id.vendor = (iforce->edata[2] << 8) | iforce->edata[1];
 	else
-		printk(KERN_WARNING "iforce-main.c: Device does not respond to id packet M\n");
+		warn("Device does not respond to id packet M");
 
 	if (!iforce_get_id_packet(iforce, "P"))
 		input_dev->id.product = (iforce->edata[2] << 8) | iforce->edata[1];
 	else
-		printk(KERN_WARNING "iforce-main.c: Device does not respond to id packet P\n");
+		warn("Device does not respond to id packet P");
 
 	if (!iforce_get_id_packet(iforce, "B"))
 		iforce->device_memory.end = (iforce->edata[2] << 8) | iforce->edata[1];
 	else
-		printk(KERN_WARNING "iforce-main.c: Device does not respond to id packet B\n");
+		warn("Device does not respond to id packet B");
 
 	if (!iforce_get_id_packet(iforce, "N"))
 		ff_effects = iforce->edata[1];
 	else
-		printk(KERN_WARNING "iforce-main.c: Device does not respond to id packet N\n");
+		warn("Device does not respond to id packet N");
 
 	/* Check if the device can store more effects than the driver can really handle */
 	if (ff_effects > IFORCE_EFFECTS_MAX) {
-		printk(KERN_WARNING "iforce: Limiting number of effects to %d (device reports %d)\n",
+		warn("Limiting number of effects to %d (device reports %d)",
 		       IFORCE_EFFECTS_MAX, ff_effects);
 		ff_effects = IFORCE_EFFECTS_MAX;
 	}
@@ -457,8 +457,6 @@
 	if (error)
 		goto fail;
 
-	printk(KERN_DEBUG "iforce->dev->open = %p\n", iforce->dev->open);
-
 	return 0;
 
  fail:	input_free_device(input_dev);
diff --git a/drivers/input/joystick/iforce/iforce-packets.c b/drivers/input/joystick/iforce/iforce-packets.c
index 808f059..21c4e13 100644
--- a/drivers/input/joystick/iforce/iforce-packets.c
+++ b/drivers/input/joystick/iforce/iforce-packets.c
@@ -2,7 +2,7 @@
  * $Id: iforce-packets.c,v 1.16 2002/07/07 10:22:50 jdeneux Exp $
  *
  *  Copyright (c) 2000-2002 Vojtech Pavlik <vojtech@ucw.cz>
- *  Copyright (c) 2001-2002 Johann Deneux <deneux@ifrance.com>
+ *  Copyright (c) 2001-2002, 2007 Johann Deneux <johann.deneux@gmail.com>
  *
  *  USB/RS232 I-Force joysticks and wheels.
  */
@@ -39,10 +39,10 @@
 {
 	int i;
 
-	printk(KERN_DEBUG "iforce.c: %s ( cmd = %04x, data = ", msg, cmd);
+	printk(KERN_DEBUG __FILE__ ": %s cmd = %04x, data = ", msg, cmd);
 	for (i = 0; i < LO(cmd); i++)
 		printk("%02x ", data[i]);
-	printk(")\n");
+	printk("\n");
 }
 
 /*
@@ -65,8 +65,9 @@
 	head = iforce->xmit.head;
 	tail = iforce->xmit.tail;
 
+
 	if (CIRC_SPACE(head, tail, XMIT_SIZE) < n+2) {
-		printk(KERN_WARNING "iforce.c: not enough space in xmit buffer to send new packet\n");
+		warn("not enough space in xmit buffer to send new packet");
 		spin_unlock_irqrestore(&iforce->xmit_lock, flags);
 		return -1;
 	}
@@ -126,8 +127,6 @@
 {
 	unsigned char data[3];
 
-printk(KERN_DEBUG "iforce-packets.c: control_playback %d %d\n", id, value);
-
 	data[0] = LO(id);
 	data[1] = (value > 0) ? ((value > 1) ? 0x41 : 0x01) : 0;
 	data[2] = LO(value);
@@ -151,7 +150,7 @@
 			return 0;
 		}
 	}
-	printk(KERN_WARNING "iforce-packets.c: unused effect %04x updated !!!\n", addr);
+	warn("unused effect %04x updated !!!", addr);
 	return -1;
 }
 
@@ -162,7 +161,7 @@
 	static int being_used = 0;
 
 	if (being_used)
-		printk(KERN_WARNING "iforce-packets.c: re-entrant call to iforce_process %d\n", being_used);
+		warn("re-entrant call to iforce_process %d", being_used);
 	being_used++;
 
 #ifdef CONFIG_JOYSTICK_IFORCE_232
@@ -266,7 +265,7 @@
 			return -1;
 		}
 #else
-		printk(KERN_ERR "iforce_get_id_packet: iforce->bus = USB!\n");
+		err("iforce_get_id_packet: iforce->bus = USB!");
 #endif
 		break;
 
@@ -284,13 +283,12 @@
 			return -1;
 		}
 #else
-		printk(KERN_ERR "iforce_get_id_packet: iforce->bus = SERIO!\n");
+		err("iforce_get_id_packet: iforce->bus = SERIO!");
 #endif
 		break;
 
 	default:
-		printk(KERN_ERR "iforce_get_id_packet: iforce->bus = %d\n",
-		       iforce->bus);
+		err("iforce_get_id_packet: iforce->bus = %d", iforce->bus);
 		break;
 	}
 
diff --git a/drivers/input/joystick/iforce/iforce-serio.c b/drivers/input/joystick/iforce/iforce-serio.c
index ec4be53..7b4bc19 100644
--- a/drivers/input/joystick/iforce/iforce-serio.c
+++ b/drivers/input/joystick/iforce/iforce-serio.c
@@ -2,7 +2,7 @@
  * $Id: iforce-serio.c,v 1.4 2002/01/28 22:45:00 jdeneux Exp $
  *
  *  Copyright (c) 2000-2001 Vojtech Pavlik <vojtech@ucw.cz>
- *  Copyright (c) 2001 Johann Deneux <deneux@ifrance.com>
+ *  Copyright (c) 2001, 2007 Johann Deneux <johann.deneux@gmail.com>
  *
  *  USB/RS232 I-Force joysticks and wheels.
  */
diff --git a/drivers/input/joystick/iforce/iforce-usb.c b/drivers/input/joystick/iforce/iforce-usb.c
index 80cdebc..750099d 100644
--- a/drivers/input/joystick/iforce/iforce-usb.c
+++ b/drivers/input/joystick/iforce/iforce-usb.c
@@ -2,7 +2,7 @@
  * $Id: iforce-usb.c,v 1.16 2002/06/09 11:08:04 jdeneux Exp $
  *
  *  Copyright (c) 2000-2002 Vojtech Pavlik <vojtech@ucw.cz>
- *  Copyright (c) 2001-2002 Johann Deneux <deneux@ifrance.com>
+ *  Copyright (c) 2001-2002, 2007 Johann Deneux <johann.deneux@gmail.com>
  *
  *  USB/RS232 I-Force joysticks and wheels.
  */
@@ -65,7 +65,7 @@
 	XMIT_INC(iforce->xmit.tail, n);
 
 	if ( (n=usb_submit_urb(iforce->out, GFP_ATOMIC)) ) {
-		printk(KERN_WARNING "iforce-usb.c: iforce_usb_xmit: usb_submit_urb failed %d\n", n);
+		warn("usb_submit_urb failed %d\n", n);
 	}
 
 	/* The IFORCE_XMIT_RUNNING bit is not cleared here. That's intended.
@@ -110,7 +110,7 @@
 	struct iforce *iforce = urb->context;
 
 	if (urb->status) {
-		printk(KERN_DEBUG "iforce_usb_out: urb->status %d, exiting", urb->status);
+		dbg("urb->status %d, exiting", urb->status);
 		return;
 	}
 
@@ -190,10 +190,9 @@
 /* Called by iforce_delete() */
 void iforce_usb_delete(struct iforce* iforce)
 {
-	usb_unlink_urb(iforce->irq);
-/* Is it ok to unlink those ? */
-	usb_unlink_urb(iforce->out);
-	usb_unlink_urb(iforce->ctrl);
+	usb_kill_urb(iforce->irq);
+	usb_kill_urb(iforce->out);
+	usb_kill_urb(iforce->ctrl);
 
 	usb_free_urb(iforce->irq);
 	usb_free_urb(iforce->out);
diff --git a/drivers/input/joystick/iforce/iforce.h b/drivers/input/joystick/iforce/iforce.h
index ffaeaef..dadcf4f 100644
--- a/drivers/input/joystick/iforce/iforce.h
+++ b/drivers/input/joystick/iforce/iforce.h
@@ -2,7 +2,7 @@
  * $Id: iforce.h,v 1.13 2002/07/07 10:22:50 jdeneux Exp $
  *
  *  Copyright (c) 2000-2002 Vojtech Pavlik <vojtech@ucw.cz>
- *  Copyright (c) 2001-2002 Johann Deneux <deneux@ifrance.com>
+ *  Copyright (c) 2001-2002, 2007 Johann Deneux <johann.deneux@gmail.com>
  *
  *  USB/RS232 I-Force joysticks and wheels.
  */
diff --git a/drivers/input/joystick/interact.c b/drivers/input/joystick/interact.c
index fec8b3d..1aec1e9 100644
--- a/drivers/input/joystick/interact.c
+++ b/drivers/input/joystick/interact.c
@@ -185,7 +185,7 @@
 
 static int interact_open(struct input_dev *dev)
 {
-	struct interact *interact = dev->private;
+	struct interact *interact = input_get_drvdata(dev);
 
 	gameport_start_polling(interact->gameport);
 	return 0;
@@ -197,7 +197,7 @@
 
 static void interact_close(struct input_dev *dev)
 {
-	struct interact *interact = dev->private;
+	struct interact *interact = input_get_drvdata(dev);
 
 	gameport_stop_polling(interact->gameport);
 }
@@ -262,7 +262,9 @@
 	input_dev->id.vendor = GAMEPORT_ID_VENDOR_INTERACT;
 	input_dev->id.product = interact_type[i].id;
 	input_dev->id.version = 0x0100;
-	input_dev->private = interact;
+	input_dev->dev.parent = &gameport->dev;
+
+	input_set_drvdata(input_dev, interact);
 
 	input_dev->open = interact_open;
 	input_dev->close = interact_close;
diff --git a/drivers/input/joystick/magellan.c b/drivers/input/joystick/magellan.c
index 4112789..b35604e 100644
--- a/drivers/input/joystick/magellan.c
+++ b/drivers/input/joystick/magellan.c
@@ -168,8 +168,7 @@
 	input_dev->id.vendor = SERIO_MAGELLAN;
 	input_dev->id.product = 0x0001;
 	input_dev->id.version = 0x0100;
-	input_dev->cdev.dev = &serio->dev;
-	input_dev->private = magellan;
+	input_dev->dev.parent = &serio->dev;
 
 	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
 
diff --git a/drivers/input/joystick/sidewinder.c b/drivers/input/joystick/sidewinder.c
index e58b22c..2adf73f 100644
--- a/drivers/input/joystick/sidewinder.c
+++ b/drivers/input/joystick/sidewinder.c
@@ -509,7 +509,7 @@
 
 static int sw_open(struct input_dev *dev)
 {
-	struct sw *sw = dev->private;
+	struct sw *sw = input_get_drvdata(dev);
 
 	gameport_start_polling(sw->gameport);
 	return 0;
@@ -517,7 +517,7 @@
 
 static void sw_close(struct input_dev *dev)
 {
-	struct sw *sw = dev->private;
+	struct sw *sw = input_get_drvdata(dev);
 
 	gameport_stop_polling(sw->gameport);
 }
@@ -751,8 +751,9 @@
 		input_dev->id.vendor = GAMEPORT_ID_VENDOR_MICROSOFT;
 		input_dev->id.product = sw->type;
 		input_dev->id.version = 0x0100;
-		input_dev->cdev.dev = &gameport->dev;
-		input_dev->private = sw;
+		input_dev->dev.parent = &gameport->dev;
+
+		input_set_drvdata(input_dev, sw);
 
 		input_dev->open = sw_open;
 		input_dev->close = sw_close;
diff --git a/drivers/input/joystick/spaceball.c b/drivers/input/joystick/spaceball.c
index 08bf113..abb7c4c 100644
--- a/drivers/input/joystick/spaceball.c
+++ b/drivers/input/joystick/spaceball.c
@@ -226,8 +226,7 @@
 	input_dev->id.vendor = SERIO_SPACEBALL;
 	input_dev->id.product = id;
 	input_dev->id.version = 0x0100;
-	input_dev->cdev.dev = &serio->dev;
-	input_dev->private = spaceball;
+	input_dev->dev.parent = &serio->dev;
 
 	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
 
diff --git a/drivers/input/joystick/spaceorb.c b/drivers/input/joystick/spaceorb.c
index c9c7921..c4937f1 100644
--- a/drivers/input/joystick/spaceorb.c
+++ b/drivers/input/joystick/spaceorb.c
@@ -183,8 +183,7 @@
 	input_dev->id.vendor = SERIO_SPACEORB;
 	input_dev->id.product = 0x0001;
 	input_dev->id.version = 0x0100;
-	input_dev->cdev.dev = &serio->dev;
-	input_dev->private = spaceorb;
+	input_dev->dev.parent = &serio->dev;
 
 	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
 
diff --git a/drivers/input/joystick/stinger.c b/drivers/input/joystick/stinger.c
index ecb0916..8581ee9 100644
--- a/drivers/input/joystick/stinger.c
+++ b/drivers/input/joystick/stinger.c
@@ -154,8 +154,7 @@
 	input_dev->id.vendor = SERIO_STINGER;
 	input_dev->id.product = 0x0001;
 	input_dev->id.version = 0x0100;
-	input_dev->cdev.dev = &serio->dev;
-	input_dev->private = stinger;
+	input_dev->dev.parent = &serio->dev;
 
 	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
 	input_dev->keybit[LONG(BTN_A)] = BIT(BTN_A) | BIT(BTN_B) | BIT(BTN_C) | BIT(BTN_X) |
diff --git a/drivers/input/joystick/tmdc.c b/drivers/input/joystick/tmdc.c
index bb23ed2..3b36ee0 100644
--- a/drivers/input/joystick/tmdc.c
+++ b/drivers/input/joystick/tmdc.c
@@ -265,7 +265,7 @@
 
 static int tmdc_open(struct input_dev *dev)
 {
-	struct tmdc *tmdc = dev->private;
+	struct tmdc *tmdc = input_get_drvdata(dev);
 
 	gameport_start_polling(tmdc->gameport);
 	return 0;
@@ -273,7 +273,7 @@
 
 static void tmdc_close(struct input_dev *dev)
 {
-	struct tmdc *tmdc = dev->private;
+	struct tmdc *tmdc = input_get_drvdata(dev);
 
 	gameport_stop_polling(tmdc->gameport);
 }
@@ -326,8 +326,9 @@
 	input_dev->id.vendor = GAMEPORT_ID_VENDOR_THRUSTMASTER;
 	input_dev->id.product = model->id;
 	input_dev->id.version = 0x0100;
-	input_dev->cdev.dev = &tmdc->gameport->dev;
-	input_dev->private = tmdc;
+	input_dev->dev.parent = &tmdc->gameport->dev;
+
+	input_set_drvdata(input_dev, tmdc);
 
 	input_dev->open = tmdc_open;
 	input_dev->close = tmdc_close;
diff --git a/drivers/input/joystick/turbografx.c b/drivers/input/joystick/turbografx.c
index 037d348..0f2c608 100644
--- a/drivers/input/joystick/turbografx.c
+++ b/drivers/input/joystick/turbografx.c
@@ -122,7 +122,7 @@
 
 static int tgfx_open(struct input_dev *dev)
 {
-	struct tgfx *tgfx = dev->private;
+	struct tgfx *tgfx = input_get_drvdata(dev);
 	int err;
 
 	err = mutex_lock_interruptible(&tgfx->sem);
@@ -141,7 +141,7 @@
 
 static void tgfx_close(struct input_dev *dev)
 {
-	struct tgfx *tgfx = dev->private;
+	struct tgfx *tgfx = input_get_drvdata(dev);
 
 	mutex_lock(&tgfx->sem);
 	if (!--tgfx->used) {
@@ -224,7 +224,8 @@
 		input_dev->id.product = n_buttons[i];
 		input_dev->id.version = 0x0100;
 
-		input_dev->private = tgfx;
+		input_set_drvdata(input_dev, tgfx);
+
 		input_dev->open = tgfx_open;
 		input_dev->close = tgfx_close;
 
diff --git a/drivers/input/joystick/twidjoy.c b/drivers/input/joystick/twidjoy.c
index 9cf17d6c..c91504e 100644
--- a/drivers/input/joystick/twidjoy.c
+++ b/drivers/input/joystick/twidjoy.c
@@ -205,11 +205,9 @@
 	input_dev->id.vendor = SERIO_TWIDJOY;
 	input_dev->id.product = 0x0001;
 	input_dev->id.version = 0x0100;
-	input_dev->cdev.dev = &serio->dev;
-	input_dev->private = twidjoy;
+	input_dev->dev.parent = &serio->dev;
 
 	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
-	input_dev->absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
 	input_set_abs_params(input_dev, ABS_X, -50, 50, 4, 4);
 	input_set_abs_params(input_dev, ABS_Y, -50, 50, 4, 4);
 
diff --git a/drivers/input/joystick/warrior.c b/drivers/input/joystick/warrior.c
index 29d339a..4e85f72 100644
--- a/drivers/input/joystick/warrior.c
+++ b/drivers/input/joystick/warrior.c
@@ -160,8 +160,7 @@
 	input_dev->id.vendor = SERIO_WARRIOR;
 	input_dev->id.product = 0x0001;
 	input_dev->id.version = 0x0100;
-	input_dev->cdev.dev = &serio->dev;
-	input_dev->private = warrior;
+	input_dev->dev.parent = &serio->dev;
 
 	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL) | BIT(EV_ABS);
 	input_dev->keybit[LONG(BTN_TRIGGER)] = BIT(BTN_TRIGGER) | BIT(BTN_THUMB) | BIT(BTN_TOP) | BIT(BTN_TOP2);
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index f17e9c7..9f42e4d 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -164,6 +164,17 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called amikbd.
 
+config KEYBOARD_ATARI
+	tristate "Atari keyboard"
+	depends on ATARI
+	select ATARI_KBD_CORE
+	help
+	  Say Y here if you are running Linux on any Atari and have a keyboard
+	  attached.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called atakbd.
+
 config KEYBOARD_HIL_OLD
 	tristate "HP HIL keyboard support (simple driver)"
 	depends on GSC || HP300
@@ -203,6 +214,15 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called omap-keypad.
 
+config KEYBOARD_PXA27x
+	tristate "PXA27x keyboard support"
+	depends on PXA27x
+	help
+	  Enable support for PXA27x matrix keyboard controller
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called pxa27x_keyboard.
+
 config KEYBOARD_AAED2000
 	tristate "AAED-2000 keyboard"
 	depends on MACH_AAED2000
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile
index 586a0fe..28d211b 100644
--- a/drivers/input/keyboard/Makefile
+++ b/drivers/input/keyboard/Makefile
@@ -9,6 +9,7 @@
 obj-$(CONFIG_KEYBOARD_LKKBD)		+= lkkbd.o
 obj-$(CONFIG_KEYBOARD_XTKBD)		+= xtkbd.o
 obj-$(CONFIG_KEYBOARD_AMIGA)		+= amikbd.o
+obj-$(CONFIG_KEYBOARD_ATARI)		+= atakbd.o
 obj-$(CONFIG_KEYBOARD_LOCOMO)		+= locomokbd.o
 obj-$(CONFIG_KEYBOARD_NEWTON)		+= newtonkbd.o
 obj-$(CONFIG_KEYBOARD_STOWAWAY)		+= stowaway.o
@@ -17,6 +18,7 @@
 obj-$(CONFIG_KEYBOARD_HIL)		+= hil_kbd.o
 obj-$(CONFIG_KEYBOARD_HIL_OLD)		+= hilkbd.o
 obj-$(CONFIG_KEYBOARD_OMAP)		+= omap-keypad.o
+obj-$(CONFIG_KEYBOARD_PXA27x)		+= pxa27x_keyboard.o
 obj-$(CONFIG_KEYBOARD_AAED2000)		+= aaed2000_kbd.o
 obj-$(CONFIG_KEYBOARD_GPIO)		+= gpio_keys.o
 
diff --git a/drivers/input/keyboard/aaed2000_kbd.c b/drivers/input/keyboard/aaed2000_kbd.c
index 65fcb6a..3a37505 100644
--- a/drivers/input/keyboard/aaed2000_kbd.c
+++ b/drivers/input/keyboard/aaed2000_kbd.c
@@ -97,7 +97,7 @@
 
 static int aaedkbd_open(struct input_dev *indev)
 {
-	struct aaedkbd *aaedkbd = indev->private;
+	struct aaedkbd *aaedkbd = input_get_drvdata(indev);
 
 	schedule_delayed_work(&aaedkbd->workq, msecs_to_jiffies(SCAN_INTERVAL));
 
@@ -106,7 +106,7 @@
 
 static void aaedkbd_close(struct input_dev *indev)
 {
-	struct aaedkbd *aaedkbd = indev->private;
+	struct aaedkbd *aaedkbd = input_get_drvdata(indev);
 
 	cancel_delayed_work(&aaedkbd->workq);
 	flush_scheduled_work();
@@ -141,8 +141,9 @@
 	input_dev->id.vendor = 0x0001;
 	input_dev->id.product = 0x0001;
 	input_dev->id.version = 0x0100;
-	input_dev->cdev.dev = &pdev->dev;
-	input_dev->private = aaedkbd;
+	input_dev->dev.parent = &pdev->dev;
+
+	input_set_drvdata(input_dev, aaedkbd);
 
 	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
 	input_dev->keycode = aaedkbd->keycode;
diff --git a/drivers/input/keyboard/atakbd.c b/drivers/input/keyboard/atakbd.c
new file mode 100644
index 0000000..ded1d6a
--- /dev/null
+++ b/drivers/input/keyboard/atakbd.c
@@ -0,0 +1,134 @@
+/*
+ *  atakbd.c
+ *
+ *  Copyright (c) 2005 Michael Schmitz
+ *
+ * Based on amikbd.c, which is
+ *
+ *  Copyright (c) 2000-2001 Vojtech Pavlik
+ *
+ *  Based on the work of:
+ *	Hamish Macdonald
+ */
+
+/*
+ * Atari keyboard driver for Linux/m68k
+ *
+ * The low level init and interrupt stuff is handled in arch/mm68k/atari/atakeyb.c
+ * (the keyboard ACIA also handles the mouse and joystick data, and the keyboard
+ * interrupt is shared with the MIDI ACIA so MIDI data also get handled there).
+ * This driver only deals with handing key events off to the input layer.
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or 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
+ *
+ * Should you need to contact me, the author, you can do so either by
+ * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
+ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+
+#include <asm/atariints.h>
+#include <asm/atarihw.h>
+#include <asm/atarikb.h>
+#include <asm/irq.h>
+
+MODULE_AUTHOR("Michael Schmitz <schmitz@biophys.uni-duesseldorf.de>");
+MODULE_DESCRIPTION("Atari keyboard driver");
+MODULE_LICENSE("GPL");
+
+static unsigned char atakbd_keycode[0x72];
+
+static struct input_dev *atakbd_dev;
+
+static void atakbd_interrupt(unsigned char scancode, char down)
+{
+
+	if (scancode < 0x72) {		/* scancodes < 0xf2 are keys */
+
+		// report raw events here?
+
+		scancode = atakbd_keycode[scancode];
+
+		if (scancode == KEY_CAPSLOCK) {	/* CapsLock is a toggle switch key on Amiga */
+			input_report_key(atakbd_dev, scancode, 1);
+			input_report_key(atakbd_dev, scancode, 0);
+			input_sync(atakbd_dev);
+		} else {
+			input_report_key(atakbd_dev, scancode, down);
+			input_sync(atakbd_dev);
+		}
+	} else				/* scancodes >= 0xf2 are mouse data, most likely */
+		printk(KERN_INFO "atakbd: unhandled scancode %x\n", scancode);
+
+	return;
+}
+
+static int __init atakbd_init(void)
+{
+	int i;
+
+	if (!ATARIHW_PRESENT(ST_MFP))
+		return -EIO;
+
+	// TODO: request_mem_region if not done in arch code
+
+	if (!(atakbd_dev = input_allocate_device()))
+		return -ENOMEM;
+
+	// need to init core driver if not already done so
+	if (atari_keyb_init())
+		return -ENODEV;
+
+	atakbd_dev->name = "Atari Keyboard";
+	atakbd_dev->phys = "atakbd/input0";
+	atakbd_dev->id.bustype = BUS_ATARI;
+	atakbd_dev->id.vendor = 0x0001;
+	atakbd_dev->id.product = 0x0001;
+	atakbd_dev->id.version = 0x0100;
+
+	atakbd_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
+	atakbd_dev->keycode = atakbd_keycode;
+	atakbd_dev->keycodesize = sizeof(unsigned char);
+	atakbd_dev->keycodemax = ARRAY_SIZE(atakbd_keycode);
+
+	for (i = 1; i < 0x72; i++) {
+		atakbd_keycode[i] = i;
+		set_bit(atakbd_keycode[i], atakbd_dev->keybit);
+	}
+
+	input_register_device(atakbd_dev);
+
+	atari_input_keyboard_interrupt_hook = atakbd_interrupt;
+
+	printk(KERN_INFO "input: %s at IKBD ACIA\n", atakbd_dev->name);
+
+	return 0;
+}
+
+static void __exit atakbd_exit(void)
+{
+	atari_input_keyboard_interrupt_hook = NULL;
+	input_unregister_device(atakbd_dev);
+}
+
+module_init(atakbd_init);
+module_exit(atakbd_exit);
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c
index 6638770..be1fe46 100644
--- a/drivers/input/keyboard/atkbd.c
+++ b/drivers/input/keyboard/atkbd.c
@@ -586,7 +586,7 @@
 
 static int atkbd_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
 {
-	struct atkbd *atkbd = dev->private;
+	struct atkbd *atkbd = input_get_drvdata(dev);
 
 	if (!atkbd->write)
 		return -1;
@@ -883,8 +883,9 @@
 	input_dev->id.product = atkbd->translated ? 1 : atkbd->set;
 	input_dev->id.version = atkbd->id;
 	input_dev->event = atkbd_event;
-	input_dev->private = atkbd;
-	input_dev->cdev.dev = &atkbd->ps2dev.serio->dev;
+	input_dev->dev.parent = &atkbd->ps2dev.serio->dev;
+
+	input_set_drvdata(input_dev, atkbd);
 
 	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_MSC);
 
diff --git a/drivers/input/keyboard/corgikbd.c b/drivers/input/keyboard/corgikbd.c
index 1016c94..6578bff 100644
--- a/drivers/input/keyboard/corgikbd.c
+++ b/drivers/input/keyboard/corgikbd.c
@@ -323,8 +323,7 @@
 	input_dev->id.vendor = 0x0001;
 	input_dev->id.product = 0x0001;
 	input_dev->id.version = 0x0100;
-	input_dev->cdev.dev = &pdev->dev;
-	input_dev->private = corgikbd;
+	input_dev->dev.parent = &pdev->dev;
 
 	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_PWR) | BIT(EV_SW);
 	input_dev->keycode = corgikbd->keycode;
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c
index ccf6df3..7392122 100644
--- a/drivers/input/keyboard/gpio_keys.c
+++ b/drivers/input/keyboard/gpio_keys.c
@@ -35,11 +35,14 @@
 	struct input_dev *input = platform_get_drvdata(pdev);
 
 	for (i = 0; i < pdata->nbuttons; i++) {
-		int gpio = pdata->buttons[i].gpio;
-		if (irq == gpio_to_irq(gpio)) {
-			int state = (gpio_get_value(gpio) ? 1 : 0) ^ (pdata->buttons[i].active_low);
+		struct gpio_keys_button *button = &pdata->buttons[i];
+		int gpio = button->gpio;
 
-			input_report_key(input, pdata->buttons[i].keycode, state);
+		if (irq == gpio_to_irq(gpio)) {
+			unsigned int type = button->type ?: EV_KEY;
+			int state = (gpio_get_value(gpio) ? 1 : 0) ^ button->active_low;
+
+			input_event(input, type, button->code, !!state);
 			input_sync(input);
 		}
 	}
@@ -63,8 +66,7 @@
 
 	input->name = pdev->name;
 	input->phys = "gpio-keys/input0";
-	input->cdev.dev = &pdev->dev;
-	input->private = pdata;
+	input->dev.parent = &pdev->dev;
 
 	input->id.bustype = BUS_HOST;
 	input->id.vendor = 0x0001;
@@ -72,19 +74,21 @@
 	input->id.version = 0x0100;
 
 	for (i = 0; i < pdata->nbuttons; i++) {
-		int code = pdata->buttons[i].keycode;
-		int irq = gpio_to_irq(pdata->buttons[i].gpio);
+		struct gpio_keys_button *button = &pdata->buttons[i];
+		int irq = gpio_to_irq(button->gpio);
+		unsigned int type = button->type ?: EV_KEY;
 
 		set_irq_type(irq, IRQ_TYPE_EDGE_BOTH);
 		error = request_irq(irq, gpio_keys_isr, IRQF_SAMPLE_RANDOM,
-				     pdata->buttons[i].desc ? pdata->buttons[i].desc : "gpio_keys",
+				     button->desc ? button->desc : "gpio_keys",
 				     pdev);
 		if (error) {
 			printk(KERN_ERR "gpio-keys: unable to claim irq %d; error %d\n",
 				irq, error);
 			goto fail;
 		}
-		set_bit(code, input->keybit);
+
+		input_set_capability(input, type, button->code);
 	}
 
 	error = input_register_device(input);
diff --git a/drivers/input/keyboard/hil_kbd.c b/drivers/input/keyboard/hil_kbd.c
index 7cc9728..cdd254f 100644
--- a/drivers/input/keyboard/hil_kbd.c
+++ b/drivers/input/keyboard/hil_kbd.c
@@ -51,7 +51,7 @@
 
 #define HIL_KBD_SET1_UPBIT 0x01
 #define HIL_KBD_SET1_SHIFT 1
-static unsigned int hil_kbd_set1[HIL_KEYCODES_SET1_TBLSIZE] = 
+static unsigned int hil_kbd_set1[HIL_KEYCODES_SET1_TBLSIZE] __read_mostly =
 	{ HIL_KEYCODES_SET1 };
 
 #define HIL_KBD_SET2_UPBIT 0x01
@@ -60,10 +60,10 @@
 
 #define HIL_KBD_SET3_UPBIT 0x80
 #define HIL_KBD_SET3_SHIFT 0
-static unsigned int hil_kbd_set3[HIL_KEYCODES_SET3_TBLSIZE] =
+static unsigned int hil_kbd_set3[HIL_KEYCODES_SET3_TBLSIZE] __read_mostly =
 	{ HIL_KEYCODES_SET3 };
 
-static char hil_language[][16] = { HIL_LOCALE_MAP };
+static const char hil_language[][16] = { HIL_LOCALE_MAP };
 
 struct hil_kbd {
 	struct input_dev *dev;
@@ -94,10 +94,12 @@
 	idx = kbd->idx4/4;
 	p = data[idx - 1];
 
-	if ((p & ~HIL_CMDCT_POL) == 
-	    (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_POL)) goto report;
-	if ((p & ~HIL_CMDCT_RPL) == 
-	    (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_RPL)) goto report;
+	if ((p & ~HIL_CMDCT_POL) ==
+	    (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_POL))
+		goto report;
+	if ((p & ~HIL_CMDCT_RPL) ==
+	    (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_RPL))
+		goto report;
 
 	/* Not a poll response.  See if we are loading config records. */
 	switch (p & HIL_PKT_DATA_MASK) {
@@ -107,27 +109,32 @@
 		for (; i < HIL_KBD_MAX_LENGTH; i++)
 			kbd->idd[i] = 0;
 		break;
+
 	case HIL_CMD_RSC:
 		for (i = 0; i < idx; i++)
 			kbd->rsc[i] = kbd->data[i] & HIL_PKT_DATA_MASK;
 		for (; i < HIL_KBD_MAX_LENGTH; i++)
 			kbd->rsc[i] = 0;
 		break;
+
 	case HIL_CMD_EXD:
 		for (i = 0; i < idx; i++)
 			kbd->exd[i] = kbd->data[i] & HIL_PKT_DATA_MASK;
 		for (; i < HIL_KBD_MAX_LENGTH; i++)
 			kbd->exd[i] = 0;
 		break;
+
 	case HIL_CMD_RNM:
 		for (i = 0; i < idx; i++)
 			kbd->rnm[i] = kbd->data[i] & HIL_PKT_DATA_MASK;
 		for (; i < HIL_KBD_MAX_LENGTH + 1; i++)
 			kbd->rnm[i] = '\0';
 		break;
+
 	default:
 		/* These occur when device isn't present */
-		if (p == (HIL_ERR_INT | HIL_PKT_CMD)) break; 
+		if (p == (HIL_ERR_INT | HIL_PKT_CMD))
+			break;
 		/* Anything else we'd like to know about. */
 		printk(KERN_WARNING PREFIX "Device sent unknown record %x\n", p);
 		break;
@@ -139,16 +146,19 @@
 	switch (kbd->data[0] & HIL_POL_CHARTYPE_MASK) {
 	case HIL_POL_CHARTYPE_NONE:
 		break;
+
 	case HIL_POL_CHARTYPE_ASCII:
 		while (cnt < idx - 1)
 			input_report_key(dev, kbd->data[cnt++] & 0x7f, 1);
 		break;
+
 	case HIL_POL_CHARTYPE_RSVD1:
 	case HIL_POL_CHARTYPE_RSVD2:
 	case HIL_POL_CHARTYPE_BINARY:
 		while (cnt < idx - 1)
 			input_report_key(dev, kbd->data[cnt++], 1);
 		break;
+
 	case HIL_POL_CHARTYPE_SET1:
 		while (cnt < idx - 1) {
 			unsigned int key;
@@ -161,6 +171,7 @@
 				input_report_key(dev, key, !up);
 		}
 		break;
+
 	case HIL_POL_CHARTYPE_SET2:
 		while (cnt < idx - 1) {
 			unsigned int key;
@@ -173,6 +184,7 @@
 				input_report_key(dev, key, !up);
 		}
 		break;
+
 	case HIL_POL_CHARTYPE_SET3:
 		while (cnt < idx - 1) {
 			unsigned int key;
@@ -191,42 +203,43 @@
 	up(&kbd->sem);
 }
 
-static void hil_kbd_process_err(struct hil_kbd *kbd) {
+static void hil_kbd_process_err(struct hil_kbd *kbd)
+{
 	printk(KERN_WARNING PREFIX "errored HIL packet\n");
 	kbd->idx4 = 0;
 	up(&kbd->sem);
 }
 
-static irqreturn_t hil_kbd_interrupt(struct serio *serio, 
-	      unsigned char data, unsigned int flags)
+static irqreturn_t hil_kbd_interrupt(struct serio *serio,
+				unsigned char data, unsigned int flags)
 {
 	struct hil_kbd *kbd;
 	hil_packet packet;
 	int idx;
 
 	kbd = serio_get_drvdata(serio);
-	if (kbd == NULL) {
-		BUG();
-		return IRQ_HANDLED;
-	}
+	BUG_ON(kbd == NULL);
 
 	if (kbd->idx4 >= (HIL_KBD_MAX_LENGTH * sizeof(hil_packet))) {
 		hil_kbd_process_err(kbd);
 		return IRQ_HANDLED;
 	}
 	idx = kbd->idx4/4;
-	if (!(kbd->idx4 % 4)) kbd->data[idx] = 0;
+	if (!(kbd->idx4 % 4))
+		kbd->data[idx] = 0;
 	packet = kbd->data[idx];
 	packet |= ((hil_packet)data) << ((3 - (kbd->idx4 % 4)) * 8);
 	kbd->data[idx] = packet;
 
 	/* Records of N 4-byte hil_packets must terminate with a command. */
-	if ((++(kbd->idx4)) % 4) return IRQ_HANDLED;
+	if ((++(kbd->idx4)) % 4)
+		return IRQ_HANDLED;
 	if ((packet & 0xffff0000) != HIL_ERR_INT) {
 		hil_kbd_process_err(kbd);
 		return IRQ_HANDLED;
 	}
-	if (packet & HIL_PKT_CMD) hil_kbd_process_record(kbd);
+	if (packet & HIL_PKT_CMD)
+		hil_kbd_process_record(kbd);
 	return IRQ_HANDLED;
 }
 
@@ -235,10 +248,7 @@
 	struct hil_kbd *kbd;
 
 	kbd = serio_get_drvdata(serio);
-	if (kbd == NULL) {
-		BUG();
-		return;
-	}
+	BUG_ON(kbd == NULL);
 
 	serio_close(serio);
 	input_unregister_device(kbd->dev);
@@ -259,42 +269,40 @@
 	if (!kbd->dev)
 		goto bail0;
 
-	kbd->dev->private = kbd;
-
 	if (serio_open(serio, drv))
 		goto bail1;
 
 	serio_set_drvdata(serio, kbd);
 	kbd->serio = serio;
 
-	init_MUTEX_LOCKED(&(kbd->sem));
+	init_MUTEX_LOCKED(&kbd->sem);
 
 	/* Get device info.  MLC driver supplies devid/status/etc. */
 	serio->write(serio, 0);
 	serio->write(serio, 0);
 	serio->write(serio, HIL_PKT_CMD >> 8);
 	serio->write(serio, HIL_CMD_IDD);
-	down(&(kbd->sem));
+	down(&kbd->sem);
 
 	serio->write(serio, 0);
 	serio->write(serio, 0);
 	serio->write(serio, HIL_PKT_CMD >> 8);
 	serio->write(serio, HIL_CMD_RSC);
-	down(&(kbd->sem));
+	down(&kbd->sem);
 
 	serio->write(serio, 0);
 	serio->write(serio, 0);
 	serio->write(serio, HIL_PKT_CMD >> 8);
 	serio->write(serio, HIL_CMD_RNM);
-	down(&(kbd->sem));
+	down(&kbd->sem);
 
 	serio->write(serio, 0);
 	serio->write(serio, 0);
 	serio->write(serio, HIL_PKT_CMD >> 8);
 	serio->write(serio, HIL_CMD_EXD);
-	down(&(kbd->sem));
+	down(&kbd->sem);
 
-	up(&(kbd->sem));
+	up(&kbd->sem);
 
 	did = kbd->idd[0];
 	idd = kbd->idd + 1;
@@ -310,12 +318,11 @@
 		goto bail2;
 	}
 
-	if(HIL_IDD_NUM_BUTTONS(idd) || HIL_IDD_NUM_AXES_PER_SET(*idd)) {
+	if (HIL_IDD_NUM_BUTTONS(idd) || HIL_IDD_NUM_AXES_PER_SET(*idd)) {
 		printk(KERN_INFO PREFIX "keyboards only, no combo devices supported.\n");
 		goto bail2;
 	}
 
-
 	kbd->dev->evbit[0]	= BIT(EV_KEY) | BIT(EV_REP);
 	kbd->dev->ledbit[0]	= BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL);
 	kbd->dev->keycodemax	= HIL_KEYCODES_SET1_TBLSIZE;
@@ -328,7 +335,7 @@
 	kbd->dev->id.vendor	= PCI_VENDOR_ID_HP;
 	kbd->dev->id.product	= 0x0001; /* TODO: get from kbd->rsc */
 	kbd->dev->id.version	= 0x0100; /* TODO: get from kbd->rsc */
-	kbd->dev->cdev.dev	= &serio->dev;
+	kbd->dev->dev.parent	= &serio->dev;
 
 	for (i = 0; i < 128; i++) {
 		set_bit(hil_kbd_set1[i], kbd->dev->keybit);
@@ -344,8 +351,8 @@
 	serio->write(serio, 0);
 	serio->write(serio, HIL_PKT_CMD >> 8);
 	serio->write(serio, HIL_CMD_EK1); /* Enable Keyswitch Autorepeat 1 */
-	down(&(kbd->sem));
-	up(&(kbd->sem));
+	down(&kbd->sem);
+	up(&kbd->sem);
 
 	return 0;
  bail2:
@@ -368,26 +375,26 @@
 	{ 0 }
 };
 
-struct serio_driver hil_kbd_serio_drv = {
+static struct serio_driver hil_kbd_serio_drv = {
 	.driver		= {
 		.name	= "hil_kbd",
 	},
 	.description	= "HP HIL keyboard driver",
 	.id_table	= hil_kbd_ids,
-	.connect 	= hil_kbd_connect,
-	.disconnect 	= hil_kbd_disconnect,
-	.interrupt 	= hil_kbd_interrupt
+	.connect	= hil_kbd_connect,
+	.disconnect	= hil_kbd_disconnect,
+	.interrupt	= hil_kbd_interrupt
 };
 
 static int __init hil_kbd_init(void)
 {
 	return serio_register_driver(&hil_kbd_serio_drv);
 }
-                
+
 static void __exit hil_kbd_exit(void)
 {
 	serio_unregister_driver(&hil_kbd_serio_drv);
 }
-                        
+
 module_init(hil_kbd_init);
 module_exit(hil_kbd_exit);
diff --git a/drivers/input/keyboard/hilkbd.c b/drivers/input/keyboard/hilkbd.c
index 4de4dc2..499b697 100644
--- a/drivers/input/keyboard/hilkbd.c
+++ b/drivers/input/keyboard/hilkbd.c
@@ -3,7 +3,7 @@
  *
  *  Copyright (C) 1998 Philip Blundell <philb@gnu.org>
  *  Copyright (C) 1999 Matthew Wilcox <willy@bofh.ai>
- *  Copyright (C) 1999-2006 Helge Deller <deller@gmx.de>
+ *  Copyright (C) 1999-2007 Helge Deller <deller@gmx.de>
  *
  *  Very basic HP Human Interface Loop (HIL) driver.
  *  This driver handles the keyboard on HP300 (m68k) and on some
@@ -52,7 +52,7 @@
 
 #elif defined(CONFIG_HP300)
 
- #define HILBASE		0xf0428000 /* HP300 (m86k) port address */
+ #define HILBASE		0xf0428000UL /* HP300 (m68k) port address */
  #define HIL_DATA		0x1
  #define HIL_CMD		0x3
  #define HIL_IRQ		2
@@ -89,7 +89,7 @@
 #define	HIL_READKBDSADR		0xF9
 #define	HIL_WRITEKBDSADR	0xE9
 
-static unsigned int hphilkeyb_keycode[HIL_KEYCODES_SET1_TBLSIZE] =
+static unsigned int hphilkeyb_keycode[HIL_KEYCODES_SET1_TBLSIZE] __read_mostly =
 	{ HIL_KEYCODES_SET1 };
 
 /* HIL structure */
@@ -211,10 +211,10 @@
 		return -ENODEV; /* already initialized */
 	}
 
+	spin_lock_init(&hil_dev.lock);
 	hil_dev.dev = input_allocate_device();
 	if (!hil_dev.dev)
 		return -ENOMEM;
-	hil_dev.dev->private = &hil_dev;
 
 #if defined(CONFIG_HP300)
 	if (!hwreg_present((void *)(HILBASE + HIL_DATA))) {
diff --git a/drivers/input/keyboard/lkkbd.c b/drivers/input/keyboard/lkkbd.c
index 3d4d0a0..1b08f4e 100644
--- a/drivers/input/keyboard/lkkbd.c
+++ b/drivers/input/keyboard/lkkbd.c
@@ -515,7 +515,7 @@
 lkkbd_event (struct input_dev *dev, unsigned int type, unsigned int code,
 		int value)
 {
-	struct lkkbd *lk = dev->private;
+	struct lkkbd *lk = input_get_drvdata (dev);
 	unsigned char leds_on = 0;
 	unsigned char leds_off = 0;
 
@@ -666,9 +666,10 @@
 	input_dev->id.vendor = SERIO_LKKBD;
 	input_dev->id.product = 0;
 	input_dev->id.version = 0x0100;
-	input_dev->cdev.dev = &serio->dev;
+	input_dev->dev.parent = &serio->dev;
 	input_dev->event = lkkbd_event;
-	input_dev->private = lk;
+
+	input_set_drvdata (input_dev, lk);
 
 	set_bit (EV_KEY, input_dev->evbit);
 	set_bit (EV_LED, input_dev->evbit);
diff --git a/drivers/input/keyboard/locomokbd.c b/drivers/input/keyboard/locomokbd.c
index 2ade518..7a41b27 100644
--- a/drivers/input/keyboard/locomokbd.c
+++ b/drivers/input/keyboard/locomokbd.c
@@ -231,7 +231,7 @@
 	input_dev->id.vendor = 0x0001;
 	input_dev->id.product = 0x0001;
 	input_dev->id.version = 0x0100;
-	input_dev->private = locomokbd;
+	input_dev->dev.parent = &dev->dev;
 
 	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
 	input_dev->keycode = locomokbd->keycode;
diff --git a/drivers/input/keyboard/newtonkbd.c b/drivers/input/keyboard/newtonkbd.c
index aa29b50..b97a41e 100644
--- a/drivers/input/keyboard/newtonkbd.c
+++ b/drivers/input/keyboard/newtonkbd.c
@@ -104,8 +104,7 @@
 	input_dev->id.vendor = SERIO_NEWTON;
 	input_dev->id.product = 0x0001;
 	input_dev->id.version = 0x0100;
-	input_dev->cdev.dev = &serio->dev;
-	input_dev->private = nkbd;
+	input_dev->dev.parent = &serio->dev;
 
 	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
 	input_dev->keycode = nkbd->keycode;
diff --git a/drivers/input/keyboard/omap-keypad.c b/drivers/input/keyboard/omap-keypad.c
index 5680a6d..3a22863 100644
--- a/drivers/input/keyboard/omap-keypad.c
+++ b/drivers/input/keyboard/omap-keypad.c
@@ -370,8 +370,7 @@
 		set_bit(keymap[i] & KEY_MAX, input_dev->keybit);
 	input_dev->name = "omap-keypad";
 	input_dev->phys = "omap-keypad/input0";
-	input_dev->cdev.dev = &pdev->dev;
-	input_dev->private = omap_kp;
+	input_dev->dev.parent = &pdev->dev;
 
 	input_dev->id.bustype = BUS_HOST;
 	input_dev->id.vendor = 0x0001;
diff --git a/drivers/input/keyboard/pxa27x_keyboard.c b/drivers/input/keyboard/pxa27x_keyboard.c
new file mode 100644
index 0000000..06eaf76
--- /dev/null
+++ b/drivers/input/keyboard/pxa27x_keyboard.c
@@ -0,0 +1,258 @@
+/*
+ * linux/drivers/input/keyboard/pxa27x_keyboard.c
+ *
+ * Driver for the pxa27x matrix keyboard controller.
+ *
+ * Created:	Feb 22, 2007
+ * Author:	Rodolfo Giometti <giometti@linux.it>
+ *
+ * Based on a previous implementations by Kevin O'Connor
+ * <kevin_at_koconnor.net> and Alex Osborne <bobofdoom@gmail.com> and
+ * on some suggestions by Nicolas Pitre <nico@cam.org>.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/input.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <asm/arch/hardware.h>
+#include <asm/arch/pxa-regs.h>
+#include <asm/arch/irqs.h>
+#include <asm/arch/pxa27x_keyboard.h>
+
+#define DRIVER_NAME		"pxa27x-keyboard"
+
+#define KPASMKP(col)		(col/2 == 0 ? KPASMKP0 : \
+				 col/2 == 1 ? KPASMKP1 : \
+				 col/2 == 2 ? KPASMKP2 : KPASMKP3)
+#define KPASMKPx_MKC(row, col)	(1 << (row + 16 * (col % 2)))
+
+static irqreturn_t pxakbd_irq_handler(int irq, void *dev_id)
+{
+	struct platform_device *pdev = dev_id;
+	struct pxa27x_keyboard_platform_data *pdata = pdev->dev.platform_data;
+	struct input_dev *input_dev = platform_get_drvdata(pdev);
+	unsigned long kpc = KPC;
+	int p, row, col, rel;
+
+	if (kpc & KPC_DI) {
+		unsigned long kpdk = KPDK;
+
+		if (!(kpdk & KPDK_DKP)) {
+			/* better luck next time */
+		} else if (kpc & KPC_REE0) {
+			unsigned long kprec = KPREC;
+			KPREC = 0x7f;
+
+			if (kprec & KPREC_OF0)
+				rel = (kprec & 0xff) + 0x7f;
+			else if (kprec & KPREC_UF0)
+				rel = (kprec & 0xff) - 0x7f - 0xff;
+			else
+				rel = (kprec & 0xff) - 0x7f;
+
+			if (rel) {
+				input_report_rel(input_dev, REL_WHEEL, rel);
+				input_sync(input_dev);
+			}
+		}
+	}
+
+	if (kpc & KPC_MI) {
+		/* report the status of every button */
+		for (row = 0; row < pdata->nr_rows; row++) {
+			for (col = 0; col < pdata->nr_cols; col++) {
+				p = KPASMKP(col) & KPASMKPx_MKC(row, col) ?
+					1 : 0;
+				pr_debug("keycode %x - pressed %x\n",
+						pdata->keycodes[row][col], p);
+				input_report_key(input_dev,
+						pdata->keycodes[row][col], p);
+			}
+		}
+		input_sync(input_dev);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int pxakbd_open(struct input_dev *dev)
+{
+	/* Set keypad control register */
+	KPC |= (KPC_ASACT |
+		KPC_MS_ALL |
+		(2 << 6) | KPC_REE0 | KPC_DK_DEB_SEL |
+		KPC_ME | KPC_MIE | KPC_DE | KPC_DIE);
+
+	KPC &= ~KPC_AS;         /* disable automatic scan */
+	KPC &= ~KPC_IMKP;       /* do not ignore multiple keypresses */
+
+	/* Set rotary count to mid-point value */
+	KPREC = 0x7F;
+
+	/* Enable unit clock */
+	pxa_set_cken(CKEN19_KEYPAD, 1);
+
+	return 0;
+}
+
+static void pxakbd_close(struct input_dev *dev)
+{
+	/* Disable clock unit */
+	pxa_set_cken(CKEN19_KEYPAD, 0);
+}
+
+#ifdef CONFIG_PM
+static int pxakbd_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	struct pxa27x_keyboard_platform_data *pdata = pdev->dev.platform_data;
+
+	/* Save controller status */
+	pdata->reg_kpc = KPC;
+	pdata->reg_kprec = KPREC;
+
+	return 0;
+}
+
+static int pxakbd_resume(struct platform_device *pdev)
+{
+	struct pxa27x_keyboard_platform_data *pdata = pdev->dev.platform_data;
+	struct input_dev *input_dev = platform_get_drvdata(pdev);
+
+	mutex_lock(&input_dev->mutex);
+
+	if (input_dev->users) {
+		/* Restore controller status */
+		KPC = pdata->reg_kpc;
+		KPREC = pdata->reg_kprec;
+
+		/* Enable unit clock */
+		pxa_set_cken(CKEN19_KEYPAD, 1);
+	}
+
+	mutex_unlock(&input_dev->mutex);
+
+	return 0;
+}
+#else
+#define pxakbd_suspend	NULL
+#define pxakbd_resume	NULL
+#endif
+
+static int __devinit pxakbd_probe(struct platform_device *pdev)
+{
+	struct pxa27x_keyboard_platform_data *pdata = pdev->dev.platform_data;
+	struct input_dev *input_dev;
+	int i, row, col, error;
+
+	/* Create and register the input driver. */
+	input_dev = input_allocate_device();
+	if (!input_dev) {
+		printk(KERN_ERR "Cannot request keypad device\n");
+		return -ENOMEM;
+	}
+
+	input_dev->name = DRIVER_NAME;
+	input_dev->id.bustype = BUS_HOST;
+	input_dev->open = pxakbd_open;
+	input_dev->close = pxakbd_close;
+	input_dev->dev.parent = &pdev->dev;
+
+	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_REL);
+	input_dev->relbit[LONG(REL_WHEEL)] = BIT(REL_WHEEL);
+	for (row = 0; row < pdata->nr_rows; row++) {
+		for (col = 0; col < pdata->nr_cols; col++) {
+			int code = pdata->keycodes[row][col];
+			if (code > 0)
+				set_bit(code, input_dev->keybit);
+		}
+	}
+
+	error = request_irq(IRQ_KEYPAD, pxakbd_irq_handler, IRQF_DISABLED,
+			    DRIVER_NAME, pdev);
+	if (error) {
+		printk(KERN_ERR "Cannot request keypad IRQ\n");
+		pxa_set_cken(CKEN19_KEYPAD, 0);
+		goto err_free_dev;
+	}
+
+	platform_set_drvdata(pdev, input_dev);
+
+	/* Register the input device */
+	error = input_register_device(input_dev);
+	if (error)
+		goto err_free_irq;
+
+	/* Setup GPIOs. */
+	for (i = 0; i < pdata->nr_rows + pdata->nr_cols; i++)
+		pxa_gpio_mode(pdata->gpio_modes[i]);
+
+	/*
+	 * Store rows/cols info into keyboard registers.
+	 */
+
+	KPC |= (pdata->nr_rows - 1) << 26;
+	KPC |= (pdata->nr_cols - 1) << 23;
+
+	for (col = 0; col < pdata->nr_cols; col++)
+		KPC |= KPC_MS0 << col;
+
+	return 0;
+
+ err_free_irq:
+	platform_set_drvdata(pdev, NULL);
+	free_irq(IRQ_KEYPAD, pdev);
+ err_free_dev:
+	input_free_device(input_dev);
+	return error;
+}
+
+static int __devexit pxakbd_remove(struct platform_device *pdev)
+{
+	struct input_dev *input_dev = platform_get_drvdata(pdev);
+
+	input_unregister_device(input_dev);
+	free_irq(IRQ_KEYPAD, pdev);
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
+static struct platform_driver pxakbd_driver = {
+	.probe		= pxakbd_probe,
+	.remove		= __devexit_p(pxakbd_remove),
+	.suspend	= pxakbd_suspend,
+	.resume		= pxakbd_resume,
+	.driver		= {
+		.name	= DRIVER_NAME,
+	},
+};
+
+static int __init pxakbd_init(void)
+{
+	return platform_driver_register(&pxakbd_driver);
+}
+
+static void __exit pxakbd_exit(void)
+{
+	platform_driver_unregister(&pxakbd_driver);
+}
+
+module_init(pxakbd_init);
+module_exit(pxakbd_exit);
+
+MODULE_DESCRIPTION("PXA27x Matrix Keyboard Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/keyboard/spitzkbd.c b/drivers/input/keyboard/spitzkbd.c
index 8a2166c..41b8038 100644
--- a/drivers/input/keyboard/spitzkbd.c
+++ b/drivers/input/keyboard/spitzkbd.c
@@ -372,10 +372,9 @@
 
 	spitzkbd->input = input_dev;
 
-	input_dev->private = spitzkbd;
 	input_dev->name = "Spitz Keyboard";
 	input_dev->phys = spitzkbd->phys;
-	input_dev->cdev.dev = &dev->dev;
+	input_dev->dev.parent = &dev->dev;
 
 	input_dev->id.bustype = BUS_HOST;
 	input_dev->id.vendor = 0x0001;
diff --git a/drivers/input/keyboard/stowaway.c b/drivers/input/keyboard/stowaway.c
index f7b5c5b..b44b068 100644
--- a/drivers/input/keyboard/stowaway.c
+++ b/drivers/input/keyboard/stowaway.c
@@ -108,8 +108,7 @@
 	input_dev->id.vendor = SERIO_STOWAWAY;
 	input_dev->id.product = 0x0001;
 	input_dev->id.version = 0x0100;
-	input_dev->cdev.dev = &serio->dev;
-	input_dev->private = skbd;
+	input_dev->dev.parent = &serio->dev;
 
 	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
 	input_dev->keycode = skbd->keycode;
diff --git a/drivers/input/keyboard/sunkbd.c b/drivers/input/keyboard/sunkbd.c
index cc02383..1d4e396 100644
--- a/drivers/input/keyboard/sunkbd.c
+++ b/drivers/input/keyboard/sunkbd.c
@@ -146,7 +146,7 @@
 
 static int sunkbd_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
 {
-	struct sunkbd *sunkbd = dev->private;
+	struct sunkbd *sunkbd = input_get_drvdata(dev);
 
 	switch (type) {
 
@@ -271,8 +271,10 @@
 	input_dev->id.vendor  = SERIO_SUNKBD;
 	input_dev->id.product = sunkbd->type;
 	input_dev->id.version = 0x0100;
-	input_dev->cdev.dev = &serio->dev;
-	input_dev->private = sunkbd;
+	input_dev->dev.parent = &serio->dev;
+
+	input_set_drvdata(input_dev, sunkbd);
+
 	input_dev->event = sunkbd_event;
 
 	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_SND) | BIT(EV_REP);
diff --git a/drivers/input/keyboard/xtkbd.c b/drivers/input/keyboard/xtkbd.c
index a820934..f3a56eb 100644
--- a/drivers/input/keyboard/xtkbd.c
+++ b/drivers/input/keyboard/xtkbd.c
@@ -108,8 +108,7 @@
 	input_dev->id.vendor  = 0x0001;
 	input_dev->id.product = 0x0001;
 	input_dev->id.version = 0x0100;
-	input_dev->cdev.dev = &serio->dev;
-	input_dev->private = xtkbd;
+	input_dev->dev.parent = &serio->dev;
 
 	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
 	input_dev->keycode = xtkbd->keycode;
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index 41b4258..1d0d3e7 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -40,6 +40,16 @@
 	tristate "M68k Beeper support"
 	depends on M68K
 
+config INPUT_COBALT_BTNS
+	tristate "Cobalt button interface"
+	depends on MIPS_COBALT
+	select INPUT_POLLDEV
+	help
+	  Say Y here if you want to support MIPS Cobalt button interface.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called cobalt_btns.
+
 config INPUT_WISTRON_BTNS
 	tristate "x86 Wistron laptop button interface"
 	depends on X86 && !X86_64
@@ -81,8 +91,19 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called uinput.
 
+config INPUT_POLLDEV
+	tristate "Polled input device skeleton"
+	help
+	  Say Y here if you are using a driver for an input
+	  device that periodically polls hardware state. This
+	  option is only useful for out-of-tree drivers since
+	  in-tree drivers select it automatically.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called input-polldev.
+
 config HP_SDC_RTC
-	tristate "HP SDC Real Time Clock"       
+	tristate "HP SDC Real Time Clock"
 	depends on GSC || HP300
 	select HP_SDC
 	help
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
index e0a8d58..21e3cca 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -4,10 +4,12 @@
 
 # Each configuration option enables a list of files.
 
+obj-$(CONFIG_INPUT_POLLDEV)		+= input-polldev.o
 obj-$(CONFIG_INPUT_SPARCSPKR)		+= sparcspkr.o
 obj-$(CONFIG_INPUT_PCSPKR)		+= pcspkr.o
 obj-$(CONFIG_INPUT_M68K_BEEP)		+= m68kspkr.o
 obj-$(CONFIG_INPUT_UINPUT)		+= uinput.o
+obj-$(CONFIG_INPUT_COBALT_BTNS)		+= cobalt_btns.o
 obj-$(CONFIG_INPUT_WISTRON_BTNS)	+= wistron_btns.o
 obj-$(CONFIG_INPUT_ATLAS_BTNS)		+= atlas_btns.o
 obj-$(CONFIG_HP_SDC_RTC)		+= hp_sdc_rtc.o
diff --git a/drivers/input/misc/cobalt_btns.c b/drivers/input/misc/cobalt_btns.c
new file mode 100644
index 0000000..064b079
--- /dev/null
+++ b/drivers/input/misc/cobalt_btns.c
@@ -0,0 +1,172 @@
+/*
+ *  Cobalt button interface driver.
+ *
+ *  Copyright (C) 2007  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#include <linux/init.h>
+#include <linux/input-polldev.h>
+#include <linux/ioport.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#define BUTTONS_POLL_INTERVAL	30	/* msec */
+#define BUTTONS_COUNT_THRESHOLD	3
+#define BUTTONS_STATUS_MASK	0xfe000000
+
+struct buttons_dev {
+	struct input_polled_dev *poll_dev;
+	void __iomem *reg;
+};
+
+struct buttons_map {
+	uint32_t mask;
+	int keycode;
+	int count;
+};
+
+static struct buttons_map buttons_map[] = {
+	{ 0x02000000, KEY_RESTART, },
+	{ 0x04000000, KEY_LEFT, },
+	{ 0x08000000, KEY_UP, },
+	{ 0x10000000, KEY_DOWN, },
+	{ 0x20000000, KEY_RIGHT, },
+	{ 0x40000000, KEY_ENTER, },
+	{ 0x80000000, KEY_SELECT, },
+};
+
+static void handle_buttons(struct input_polled_dev *dev)
+{
+	struct buttons_map *button = buttons_map;
+	struct buttons_dev *bdev = dev->private;
+	struct input_dev *input = dev->input;
+	uint32_t status;
+	int i;
+
+	status = readl(bdev->reg);
+	status = ~status & BUTTONS_STATUS_MASK;
+
+	for (i = 0; i < ARRAY_SIZE(buttons_map); i++) {
+		if (status & button->mask) {
+			button->count++;
+		} else {
+			if (button->count >= BUTTONS_COUNT_THRESHOLD) {
+				input_report_key(input, button->keycode, 0);
+				input_sync(input);
+			}
+			button->count = 0;
+		}
+
+		if (button->count == BUTTONS_COUNT_THRESHOLD) {
+			input_report_key(input, button->keycode, 1);
+			input_sync(input);
+		}
+
+		button++;
+	}
+}
+
+static int __devinit cobalt_buttons_probe(struct platform_device *pdev)
+{
+	struct buttons_dev *bdev;
+	struct input_polled_dev *poll_dev;
+	struct input_dev *input;
+	struct resource *res;
+	int error, i;
+
+	bdev = kzalloc(sizeof(struct buttons_dev), GFP_KERNEL);
+	poll_dev = input_allocate_polled_device();
+	if (!bdev || !poll_dev) {
+		error = -ENOMEM;
+		goto err_free_mem;
+	}
+
+	poll_dev->private = bdev;
+	poll_dev->poll = handle_buttons;
+	poll_dev->poll_interval = BUTTONS_POLL_INTERVAL;
+
+	input = poll_dev->input;
+	input->name = "Cobalt buttons";
+	input->phys = "cobalt/input0";
+	input->id.bustype = BUS_HOST;
+	input->cdev.dev = &pdev->dev;
+
+	input->evbit[0] = BIT(EV_KEY);
+	for (i = 0; i < ARRAY_SIZE(buttons_map); i++) {
+		set_bit(buttons_map[i].keycode, input->keybit);
+		buttons_map[i].count = 0;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		error = -EBUSY;
+		goto err_free_mem;
+	}
+
+	bdev->poll_dev = poll_dev;
+	bdev->reg = ioremap(res->start, res->end - res->start + 1);
+	dev_set_drvdata(&pdev->dev, bdev);
+
+	error = input_register_polled_device(poll_dev);
+	if (error)
+		goto err_iounmap;
+
+	return 0;
+
+ err_iounmap:
+	iounmap(bdev->reg);
+ err_free_mem:
+	input_free_polled_device(poll_dev);
+	kfree(bdev);
+	dev_set_drvdata(&pdev->dev, NULL);
+	return error;
+}
+
+static int __devexit cobalt_buttons_remove(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct buttons_dev *bdev = dev_get_drvdata(dev);
+
+	input_unregister_polled_device(bdev->poll_dev);
+	input_free_polled_device(bdev->poll_dev);
+	iounmap(bdev->reg);
+	kfree(bdev);
+	dev_set_drvdata(dev, NULL);
+
+	return 0;
+}
+
+static struct platform_driver cobalt_buttons_driver = {
+	.probe	= cobalt_buttons_probe,
+	.remove	= __devexit_p(cobalt_buttons_remove),
+	.driver	= {
+		.name	= "Cobalt buttons",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init cobalt_buttons_init(void)
+{
+	return platform_driver_register(&cobalt_buttons_driver);
+}
+
+static void __exit cobalt_buttons_exit(void)
+{
+	platform_driver_unregister(&cobalt_buttons_driver);
+}
+
+module_init(cobalt_buttons_init);
+module_exit(cobalt_buttons_exit);
diff --git a/drivers/input/misc/input-polldev.c b/drivers/input/misc/input-polldev.c
new file mode 100644
index 0000000..1b2b9c9
--- /dev/null
+++ b/drivers/input/misc/input-polldev.c
@@ -0,0 +1,171 @@
+/*
+ * Generic implementation of a polled input device
+
+ * Copyright (c) 2007 Dmitry Torokhov
+ *
+ * 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/jiffies.h>
+#include <linux/mutex.h>
+#include <linux/input-polldev.h>
+
+static DEFINE_MUTEX(polldev_mutex);
+static int polldev_users;
+static struct workqueue_struct *polldev_wq;
+
+static int input_polldev_start_workqueue(void)
+{
+	int retval;
+
+	retval = mutex_lock_interruptible(&polldev_mutex);
+	if (retval)
+		return retval;
+
+	if (!polldev_users) {
+		polldev_wq = create_singlethread_workqueue("ipolldevd");
+		if (!polldev_wq) {
+			printk(KERN_ERR "input-polldev: failed to create "
+				"ipolldevd workqueue\n");
+			retval = -ENOMEM;
+			goto out;
+		}
+	}
+
+	polldev_users++;
+
+ out:
+	mutex_unlock(&polldev_mutex);
+	return retval;
+}
+
+static void input_polldev_stop_workqueue(void)
+{
+	mutex_lock(&polldev_mutex);
+
+	if (!--polldev_users)
+		destroy_workqueue(polldev_wq);
+
+	mutex_unlock(&polldev_mutex);
+}
+
+static void input_polled_device_work(struct work_struct *work)
+{
+	struct input_polled_dev *dev =
+		container_of(work, struct input_polled_dev, work.work);
+
+	dev->poll(dev);
+	queue_delayed_work(polldev_wq, &dev->work,
+			   msecs_to_jiffies(dev->poll_interval));
+}
+
+static int input_open_polled_device(struct input_dev *input)
+{
+	struct input_polled_dev *dev = input->private;
+	int error;
+
+	error = input_polldev_start_workqueue();
+	if (error)
+		return error;
+
+	if (dev->flush)
+		dev->flush(dev);
+
+	queue_delayed_work(polldev_wq, &dev->work,
+			   msecs_to_jiffies(dev->poll_interval));
+
+	return 0;
+}
+
+static void input_close_polled_device(struct input_dev *input)
+{
+	struct input_polled_dev *dev = input->private;
+
+	cancel_rearming_delayed_workqueue(polldev_wq, &dev->work);
+	input_polldev_stop_workqueue();
+}
+
+/**
+ * input_allocate_polled_device - allocated memory polled device
+ *
+ * The function allocates memory for a polled device and also
+ * for an input device associated with this polled device.
+ */
+struct input_polled_dev *input_allocate_polled_device(void)
+{
+	struct input_polled_dev *dev;
+
+	dev = kzalloc(sizeof(struct input_polled_dev), GFP_KERNEL);
+	if (!dev)
+		return NULL;
+
+	dev->input = input_allocate_device();
+	if (!dev->input) {
+		kfree(dev);
+		return NULL;
+	}
+
+	return dev;
+}
+EXPORT_SYMBOL(input_allocate_polled_device);
+
+/**
+ * input_free_polled_device - free memory allocated for polled device
+ * @dev: device to free
+ *
+ * The function frees memory allocated for polling device and drops
+ * reference to the associated input device (if present).
+ */
+void input_free_polled_device(struct input_polled_dev *dev)
+{
+	if (dev) {
+		input_free_device(dev->input);
+		kfree(dev);
+	}
+}
+EXPORT_SYMBOL(input_free_polled_device);
+
+/**
+ * input_register_polled_device - register polled device
+ * @dev: device to register
+ *
+ * The function registers previously initialized polled input device
+ * with input layer. The device should be allocated with call to
+ * input_allocate_polled_device(). Callers should also set up poll()
+ * method and set up capabilities (id, name, phys, bits) of the
+ * corresponing input_dev structure.
+ */
+int input_register_polled_device(struct input_polled_dev *dev)
+{
+	struct input_dev *input = dev->input;
+
+	INIT_DELAYED_WORK(&dev->work, input_polled_device_work);
+	if (!dev->poll_interval)
+		dev->poll_interval = 500;
+	input->private = dev;
+	input->open = input_open_polled_device;
+	input->close = input_close_polled_device;
+
+	return input_register_device(input);
+}
+EXPORT_SYMBOL(input_register_polled_device);
+
+/**
+ * input_unregister_polled_device - unregister polled device
+ * @dev: device to unregister
+ *
+ * The function unregisters previously registered polled input
+ * device from input layer. Polling is stopped and device is
+ * ready to be freed with call to input_free_polled_device().
+ * Callers should not attempt to access dev->input pointer
+ * after calling this function.
+ */
+void input_unregister_polled_device(struct input_polled_dev *dev)
+{
+	input_unregister_device(dev->input);
+	dev->input = NULL;
+}
+EXPORT_SYMBOL(input_unregister_polled_device);
+
diff --git a/drivers/input/misc/ixp4xx-beeper.c b/drivers/input/misc/ixp4xx-beeper.c
index 105c6fc..3d4b619 100644
--- a/drivers/input/misc/ixp4xx-beeper.c
+++ b/drivers/input/misc/ixp4xx-beeper.c
@@ -51,7 +51,7 @@
 
 static int ixp4xx_spkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
 {
-	unsigned int pin = (unsigned int) dev->private;
+	unsigned int pin = (unsigned int) input_get_drvdata(input_dev);
 	unsigned int count = 0;
 
 	if (type != EV_SND)
@@ -99,14 +99,15 @@
 	if (!input_dev)
 		return -ENOMEM;
 
-	input_dev->private = (void *) dev->id;
+	input_set_drvdata(input_dev, (void *) dev->id);
+
 	input_dev->name = "ixp4xx beeper",
 	input_dev->phys = "ixp4xx/gpio";
 	input_dev->id.bustype = BUS_HOST;
 	input_dev->id.vendor  = 0x001f;
 	input_dev->id.product = 0x0001;
 	input_dev->id.version = 0x0100;
-	input_dev->cdev.dev = &dev->dev;
+	input_dev->dev.parent = &dev->dev;
 
 	input_dev->evbit[0] = BIT(EV_SND);
 	input_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
@@ -136,7 +137,7 @@
 static int __devexit ixp4xx_spkr_remove(struct platform_device *dev)
 {
 	struct input_dev *input_dev = platform_get_drvdata(dev);
-	unsigned int pin = (unsigned int) input_dev->private;
+	unsigned int pin = (unsigned int) input_get_drvdata(input_dev);
 
 	input_unregister_device(input_dev);
 	platform_set_drvdata(dev, NULL);
@@ -153,7 +154,7 @@
 static void ixp4xx_spkr_shutdown(struct platform_device *dev)
 {
 	struct input_dev *input_dev = platform_get_drvdata(dev);
-	unsigned int pin = (unsigned int) input_dev->private;
+	unsigned int pin = (unsigned int) input_get_drvdata(input_dev);
 
 	/* turn off the speaker */
 	disable_irq(IRQ_IXP4XX_TIMER2);
diff --git a/drivers/input/misc/m68kspkr.c b/drivers/input/misc/m68kspkr.c
index 8d6c383..e9f26e7 100644
--- a/drivers/input/misc/m68kspkr.c
+++ b/drivers/input/misc/m68kspkr.c
@@ -63,7 +63,7 @@
 	input_dev->id.vendor  = 0x001f;
 	input_dev->id.product = 0x0001;
 	input_dev->id.version = 0x0100;
-	input_dev->cdev.dev = &dev->dev;
+	input_dev->dev.parent = &dev->dev;
 
 	input_dev->evbit[0] = BIT(EV_SND);
 	input_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
diff --git a/drivers/input/misc/pcspkr.c b/drivers/input/misc/pcspkr.c
index afd3221..31989dc 100644
--- a/drivers/input/misc/pcspkr.c
+++ b/drivers/input/misc/pcspkr.c
@@ -78,7 +78,7 @@
 	pcspkr_dev->id.vendor = 0x001f;
 	pcspkr_dev->id.product = 0x0001;
 	pcspkr_dev->id.version = 0x0100;
-	pcspkr_dev->cdev.dev = &dev->dev;
+	pcspkr_dev->dev.parent = &dev->dev;
 
 	pcspkr_dev->evbit[0] = BIT(EV_SND);
 	pcspkr_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
diff --git a/drivers/input/misc/sparcspkr.c b/drivers/input/misc/sparcspkr.c
index 106c94f..e36ec1d 100644
--- a/drivers/input/misc/sparcspkr.c
+++ b/drivers/input/misc/sparcspkr.c
@@ -28,7 +28,7 @@
 
 static int ebus_spkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
 {
-	struct sparcspkr_state *state = dev_get_drvdata(dev->cdev.dev);
+	struct sparcspkr_state *state = dev_get_drvdata(dev->dev.parent);
 	unsigned int count = 0;
 	unsigned long flags;
 
@@ -61,7 +61,7 @@
 
 static int isa_spkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
 {
-	struct sparcspkr_state *state = dev_get_drvdata(dev->cdev.dev);
+	struct sparcspkr_state *state = dev_get_drvdata(dev->dev.parent);
 	unsigned int count = 0;
 	unsigned long flags;
 
@@ -113,7 +113,7 @@
 	input_dev->id.vendor = 0x001f;
 	input_dev->id.product = 0x0001;
 	input_dev->id.version = 0x0100;
-	input_dev->cdev.dev = dev;
+	input_dev->dev.parent = dev;
 
 	input_dev->evbit[0] = BIT(EV_SND);
 	input_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c
index 4255623..031467e 100644
--- a/drivers/input/misc/uinput.c
+++ b/drivers/input/misc/uinput.c
@@ -41,9 +41,7 @@
 
 static int uinput_dev_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
 {
-	struct uinput_device	*udev;
-
-	udev = dev->private;
+	struct uinput_device	*udev = input_get_drvdata(dev);
 
 	udev->buff[udev->head].type = type;
 	udev->buff[udev->head].code = code;
@@ -136,7 +134,7 @@
 	request.u.upload.effect = effect;
 	request.u.upload.old = old;
 
-	retval = uinput_request_reserve_slot(dev->private, &request);
+	retval = uinput_request_reserve_slot(input_get_drvdata(dev), &request);
 	if (!retval)
 		retval = uinput_request_submit(dev, &request);
 
@@ -156,7 +154,7 @@
 	request.code = UI_FF_ERASE;
 	request.u.effect_id = effect_id;
 
-	retval = uinput_request_reserve_slot(dev->private, &request);
+	retval = uinput_request_reserve_slot(input_get_drvdata(dev), &request);
 	if (!retval)
 		retval = uinput_request_submit(dev, &request);
 
@@ -274,7 +272,7 @@
 		return -ENOMEM;
 
 	udev->dev->event = uinput_dev_event;
-	udev->dev->private = udev;
+	input_set_drvdata(udev->dev, udev);
 
 	return 0;
 }
diff --git a/drivers/input/misc/wistron_btns.c b/drivers/input/misc/wistron_btns.c
index e1183ae..961aad7 100644
--- a/drivers/input/misc/wistron_btns.c
+++ b/drivers/input/misc/wistron_btns.c
@@ -50,7 +50,7 @@
 MODULE_AUTHOR("Miloslav Trmac <mitr@volny.cz>");
 MODULE_DESCRIPTION("Wistron laptop button driver");
 MODULE_LICENSE("GPL v2");
-MODULE_VERSION("0.1");
+MODULE_VERSION("0.2");
 
 static int force; /* = 0; */
 module_param(force, bool, 0);
@@ -58,7 +58,7 @@
 
 static char *keymap_name; /* = NULL; */
 module_param_named(keymap, keymap_name, charp, 0);
-MODULE_PARM_DESC(keymap, "Keymap name, if it can't be autodetected");
+MODULE_PARM_DESC(keymap, "Keymap name, if it can't be autodetected [generic, 1557/MS2141]");
 
 static struct platform_device *wistron_device;
 
@@ -233,10 +233,20 @@
 struct key_entry {
 	char type;		/* See KE_* below */
 	u8 code;
-	unsigned keycode;	/* For KE_KEY */
+	union {
+		u16 keycode;		/* For KE_KEY */
+		struct {		/* For KE_SW */
+			u8 code;
+			u8 value;
+		} sw;
+	};
 };
 
-enum { KE_END, KE_KEY, KE_WIFI, KE_BLUETOOTH };
+enum { KE_END, KE_KEY, KE_SW, KE_WIFI, KE_BLUETOOTH };
+
+#define FE_MAIL_LED 0x01
+#define FE_WIFI_LED 0x02
+#define FE_UNTESTED 0x80
 
 static const struct key_entry *keymap; /* = NULL; Current key map */
 static int have_wifi;
@@ -256,93 +266,341 @@
 	return 1;
 }
 
-static struct key_entry keymap_empty[] = {
+static struct key_entry keymap_empty[] __initdata = {
 	{ KE_END, 0 }
 };
 
-static struct key_entry keymap_fs_amilo_pro_v2000[] = {
-	{ KE_KEY,  0x01, KEY_HELP },
-	{ KE_KEY,  0x11, KEY_PROG1 },
-	{ KE_KEY,  0x12, KEY_PROG2 },
-	{ KE_WIFI, 0x30, 0 },
-	{ KE_KEY,  0x31, KEY_MAIL },
-	{ KE_KEY,  0x36, KEY_WWW },
+static struct key_entry keymap_fs_amilo_pro_v2000[] __initdata = {
+	{ KE_KEY,  0x01, {KEY_HELP} },
+	{ KE_KEY,  0x11, {KEY_PROG1} },
+	{ KE_KEY,  0x12, {KEY_PROG2} },
+	{ KE_WIFI, 0x30 },
+	{ KE_KEY,  0x31, {KEY_MAIL} },
+	{ KE_KEY,  0x36, {KEY_WWW} },
 	{ KE_END,  0 }
 };
 
-static struct key_entry keymap_fujitsu_n3510[] = {
-	{ KE_KEY, 0x11, KEY_PROG1 },
-	{ KE_KEY, 0x12, KEY_PROG2 },
-	{ KE_KEY, 0x36, KEY_WWW },
-	{ KE_KEY, 0x31, KEY_MAIL },
-	{ KE_KEY, 0x71, KEY_STOPCD },
-	{ KE_KEY, 0x72, KEY_PLAYPAUSE },
-	{ KE_KEY, 0x74, KEY_REWIND },
-	{ KE_KEY, 0x78, KEY_FORWARD },
+static struct key_entry keymap_fujitsu_n3510[] __initdata = {
+	{ KE_KEY, 0x11, {KEY_PROG1} },
+	{ KE_KEY, 0x12, {KEY_PROG2} },
+	{ KE_KEY, 0x36, {KEY_WWW} },
+	{ KE_KEY, 0x31, {KEY_MAIL} },
+	{ KE_KEY, 0x71, {KEY_STOPCD} },
+	{ KE_KEY, 0x72, {KEY_PLAYPAUSE} },
+	{ KE_KEY, 0x74, {KEY_REWIND} },
+	{ KE_KEY, 0x78, {KEY_FORWARD} },
 	{ KE_END, 0 }
 };
 
-static struct key_entry keymap_wistron_ms2111[] = {
-	{ KE_KEY,  0x11, KEY_PROG1 },
-	{ KE_KEY,  0x12, KEY_PROG2 },
-	{ KE_KEY,  0x13, KEY_PROG3 },
-	{ KE_KEY,  0x31, KEY_MAIL },
-	{ KE_KEY,  0x36, KEY_WWW },
+static struct key_entry keymap_wistron_ms2111[] __initdata = {
+	{ KE_KEY,  0x11, {KEY_PROG1} },
+	{ KE_KEY,  0x12, {KEY_PROG2} },
+	{ KE_KEY,  0x13, {KEY_PROG3} },
+	{ KE_KEY,  0x31, {KEY_MAIL} },
+	{ KE_KEY,  0x36, {KEY_WWW} },
+	{ KE_END, FE_MAIL_LED }
+};
+
+static struct key_entry keymap_wistron_md40100[] __initdata = {
+	{ KE_KEY, 0x01, {KEY_HELP} },
+	{ KE_KEY, 0x02, {KEY_CONFIG} },
+	{ KE_KEY, 0x31, {KEY_MAIL} },
+	{ KE_KEY, 0x36, {KEY_WWW} },
+	{ KE_KEY, 0x37, {KEY_DISPLAYTOGGLE} }, /* Display on/off */
+	{ KE_END, FE_MAIL_LED | FE_WIFI_LED | FE_UNTESTED }
+};
+
+static struct key_entry keymap_wistron_ms2141[] __initdata = {
+	{ KE_KEY,  0x11, {KEY_PROG1} },
+	{ KE_KEY,  0x12, {KEY_PROG2} },
+	{ KE_WIFI, 0x30 },
+	{ KE_KEY,  0x22, {KEY_REWIND} },
+	{ KE_KEY,  0x23, {KEY_FORWARD} },
+	{ KE_KEY,  0x24, {KEY_PLAYPAUSE} },
+	{ KE_KEY,  0x25, {KEY_STOPCD} },
+	{ KE_KEY,  0x31, {KEY_MAIL} },
+	{ KE_KEY,  0x36, {KEY_WWW} },
 	{ KE_END,  0 }
 };
 
-static struct key_entry keymap_wistron_ms2141[] = {
-	{ KE_KEY,  0x11, KEY_PROG1 },
-	{ KE_KEY,  0x12, KEY_PROG2 },
-	{ KE_WIFI, 0x30, 0 },
-	{ KE_KEY,  0x22, KEY_REWIND },
-	{ KE_KEY,  0x23, KEY_FORWARD },
-	{ KE_KEY,  0x24, KEY_PLAYPAUSE },
-	{ KE_KEY,  0x25, KEY_STOPCD },
-	{ KE_KEY,  0x31, KEY_MAIL },
-	{ KE_KEY,  0x36, KEY_WWW },
-	{ KE_END,  0 }
+static struct key_entry keymap_acer_aspire_1500[] __initdata = {
+	{ KE_KEY, 0x01, {KEY_HELP} },
+	{ KE_KEY, 0x03, {KEY_POWER} },
+	{ KE_KEY, 0x11, {KEY_PROG1} },
+	{ KE_KEY, 0x12, {KEY_PROG2} },
+	{ KE_WIFI, 0x30 },
+	{ KE_KEY, 0x31, {KEY_MAIL} },
+	{ KE_KEY, 0x36, {KEY_WWW} },
+	{ KE_KEY, 0x49, {KEY_CONFIG} },
+	{ KE_BLUETOOTH, 0x44 },
+	{ KE_END, FE_UNTESTED }
 };
 
-static struct key_entry keymap_acer_aspire_1500[] = {
-	{ KE_KEY, 0x11, KEY_PROG1 },
-	{ KE_KEY, 0x12, KEY_PROG2 },
-	{ KE_WIFI, 0x30, 0 },
-	{ KE_KEY, 0x31, KEY_MAIL },
-	{ KE_KEY, 0x36, KEY_WWW },
-	{ KE_BLUETOOTH, 0x44, 0 },
-	{ KE_END, 0 }
+static struct key_entry keymap_acer_aspire_1600[] __initdata = {
+	{ KE_KEY, 0x01, {KEY_HELP} },
+	{ KE_KEY, 0x03, {KEY_POWER} },
+	{ KE_KEY, 0x08, {KEY_MUTE} },
+	{ KE_KEY, 0x11, {KEY_PROG1} },
+	{ KE_KEY, 0x12, {KEY_PROG2} },
+	{ KE_KEY, 0x13, {KEY_PROG3} },
+	{ KE_KEY, 0x31, {KEY_MAIL} },
+	{ KE_KEY, 0x36, {KEY_WWW} },
+	{ KE_KEY, 0x49, {KEY_CONFIG} },
+	{ KE_WIFI, 0x30 },
+	{ KE_BLUETOOTH, 0x44 },
+	{ KE_END, FE_MAIL_LED | FE_UNTESTED }
 };
 
-static struct key_entry keymap_acer_travelmate_240[] = {
-	{ KE_KEY, 0x31, KEY_MAIL },
-	{ KE_KEY, 0x36, KEY_WWW },
-	{ KE_KEY, 0x11, KEY_PROG1 },
-	{ KE_KEY, 0x12, KEY_PROG2 },
-	{ KE_BLUETOOTH, 0x44, 0 },
-	{ KE_WIFI, 0x30, 0 },
-	{ KE_END, 0 }
+/* 3020 has been tested */
+static struct key_entry keymap_acer_aspire_5020[] __initdata = {
+	{ KE_KEY, 0x01, {KEY_HELP} },
+	{ KE_KEY, 0x03, {KEY_POWER} },
+	{ KE_KEY, 0x05, {KEY_SWITCHVIDEOMODE} }, /* Display selection */
+	{ KE_KEY, 0x11, {KEY_PROG1} },
+	{ KE_KEY, 0x12, {KEY_PROG2} },
+	{ KE_KEY, 0x31, {KEY_MAIL} },
+	{ KE_KEY, 0x36, {KEY_WWW} },
+	{ KE_KEY, 0x6a, {KEY_CONFIG} },
+	{ KE_WIFI, 0x30 },
+	{ KE_BLUETOOTH, 0x44 },
+	{ KE_END, FE_MAIL_LED | FE_UNTESTED }
 };
 
-static struct key_entry keymap_aopen_1559as[] = {
-	{ KE_KEY,  0x01, KEY_HELP },
-	{ KE_KEY,  0x06, KEY_PROG3 },
-	{ KE_KEY,  0x11, KEY_PROG1 },
-	{ KE_KEY,  0x12, KEY_PROG2 },
-	{ KE_WIFI, 0x30, 0 },
-	{ KE_KEY,  0x31, KEY_MAIL },
-	{ KE_KEY,  0x36, KEY_WWW },
+static struct key_entry keymap_acer_travelmate_2410[] __initdata = {
+	{ KE_KEY, 0x01, {KEY_HELP} },
+	{ KE_KEY, 0x6d, {KEY_POWER} },
+	{ KE_KEY, 0x11, {KEY_PROG1} },
+	{ KE_KEY, 0x12, {KEY_PROG2} },
+	{ KE_KEY, 0x31, {KEY_MAIL} },
+	{ KE_KEY, 0x36, {KEY_WWW} },
+	{ KE_KEY, 0x6a, {KEY_CONFIG} },
+	{ KE_WIFI, 0x30 },
+	{ KE_BLUETOOTH, 0x44 },
+	{ KE_END, FE_MAIL_LED | FE_UNTESTED }
+};
+
+static struct key_entry keymap_acer_travelmate_110[] __initdata = {
+	{ KE_KEY, 0x01, {KEY_HELP} },
+	{ KE_KEY, 0x02, {KEY_CONFIG} },
+	{ KE_KEY, 0x03, {KEY_POWER} },
+	{ KE_KEY, 0x08, {KEY_MUTE} },
+	{ KE_KEY, 0x11, {KEY_PROG1} },
+	{ KE_KEY, 0x12, {KEY_PROG2} },
+	{ KE_KEY, 0x20, {KEY_VOLUMEUP} },
+	{ KE_KEY, 0x21, {KEY_VOLUMEDOWN} },
+	{ KE_KEY, 0x31, {KEY_MAIL} },
+	{ KE_KEY, 0x36, {KEY_WWW} },
+	{ KE_SW, 0x4a, {.sw = {SW_LID, 1}} }, /* lid close */
+	{ KE_SW, 0x4b, {.sw = {SW_LID, 0}} }, /* lid open */
+	{ KE_WIFI, 0x30 },
+	{ KE_END, FE_MAIL_LED | FE_UNTESTED }
+};
+
+static struct key_entry keymap_acer_travelmate_300[] __initdata = {
+	{ KE_KEY, 0x01, {KEY_HELP} },
+	{ KE_KEY, 0x02, {KEY_CONFIG} },
+	{ KE_KEY, 0x03, {KEY_POWER} },
+	{ KE_KEY, 0x08, {KEY_MUTE} },
+	{ KE_KEY, 0x11, {KEY_PROG1} },
+	{ KE_KEY, 0x12, {KEY_PROG2} },
+	{ KE_KEY, 0x20, {KEY_VOLUMEUP} },
+	{ KE_KEY, 0x21, {KEY_VOLUMEDOWN} },
+	{ KE_KEY, 0x31, {KEY_MAIL} },
+	{ KE_KEY, 0x36, {KEY_WWW} },
+	{ KE_WIFI, 0x30 },
+	{ KE_BLUETOOTH, 0x44 },
+	{ KE_END, FE_MAIL_LED | FE_UNTESTED }
+};
+
+static struct key_entry keymap_acer_travelmate_380[] __initdata = {
+	{ KE_KEY, 0x01, {KEY_HELP} },
+	{ KE_KEY, 0x02, {KEY_CONFIG} },
+	{ KE_KEY, 0x03, {KEY_POWER} }, /* not 370 */
+	{ KE_KEY, 0x11, {KEY_PROG1} },
+	{ KE_KEY, 0x12, {KEY_PROG2} },
+	{ KE_KEY, 0x13, {KEY_PROG3} },
+	{ KE_KEY, 0x31, {KEY_MAIL} },
+	{ KE_KEY, 0x36, {KEY_WWW} },
+	{ KE_WIFI, 0x30 },
+	{ KE_END, FE_MAIL_LED | FE_UNTESTED }
+};
+
+/* unusual map */
+static struct key_entry keymap_acer_travelmate_220[] __initdata = {
+	{ KE_KEY, 0x01, {KEY_HELP} },
+	{ KE_KEY, 0x02, {KEY_CONFIG} },
+	{ KE_KEY, 0x11, {KEY_MAIL} },
+	{ KE_KEY, 0x12, {KEY_WWW} },
+	{ KE_KEY, 0x13, {KEY_PROG2} },
+	{ KE_KEY, 0x31, {KEY_PROG1} },
+	{ KE_END, FE_WIFI_LED | FE_UNTESTED }
+};
+
+static struct key_entry keymap_acer_travelmate_230[] __initdata = {
+	{ KE_KEY, 0x01, {KEY_HELP} },
+	{ KE_KEY, 0x02, {KEY_CONFIG} },
+	{ KE_KEY, 0x11, {KEY_PROG1} },
+	{ KE_KEY, 0x12, {KEY_PROG2} },
+	{ KE_KEY, 0x31, {KEY_MAIL} },
+	{ KE_KEY, 0x36, {KEY_WWW} },
+	{ KE_END, FE_WIFI_LED | FE_UNTESTED }
+};
+
+static struct key_entry keymap_acer_travelmate_240[] __initdata = {
+	{ KE_KEY, 0x01, {KEY_HELP} },
+	{ KE_KEY, 0x02, {KEY_CONFIG} },
+	{ KE_KEY, 0x03, {KEY_POWER} },
+	{ KE_KEY, 0x08, {KEY_MUTE} },
+	{ KE_KEY, 0x31, {KEY_MAIL} },
+	{ KE_KEY, 0x36, {KEY_WWW} },
+	{ KE_KEY, 0x11, {KEY_PROG1} },
+	{ KE_KEY, 0x12, {KEY_PROG2} },
+	{ KE_BLUETOOTH, 0x44 },
+	{ KE_WIFI, 0x30 },
+	{ KE_END, FE_UNTESTED }
+};
+
+static struct key_entry keymap_acer_travelmate_350[] __initdata = {
+	{ KE_KEY, 0x01, {KEY_HELP} },
+	{ KE_KEY, 0x02, {KEY_CONFIG} },
+	{ KE_KEY, 0x11, {KEY_PROG1} },
+	{ KE_KEY, 0x12, {KEY_PROG2} },
+	{ KE_KEY, 0x13, {KEY_MAIL} },
+	{ KE_KEY, 0x14, {KEY_PROG3} },
+	{ KE_KEY, 0x15, {KEY_WWW} },
+	{ KE_END, FE_MAIL_LED | FE_WIFI_LED | FE_UNTESTED }
+};
+
+static struct key_entry keymap_acer_travelmate_360[] __initdata = {
+	{ KE_KEY, 0x01, {KEY_HELP} },
+	{ KE_KEY, 0x02, {KEY_CONFIG} },
+	{ KE_KEY, 0x11, {KEY_PROG1} },
+	{ KE_KEY, 0x12, {KEY_PROG2} },
+	{ KE_KEY, 0x13, {KEY_MAIL} },
+	{ KE_KEY, 0x14, {KEY_PROG3} },
+	{ KE_KEY, 0x15, {KEY_WWW} },
+	{ KE_KEY, 0x40, {KEY_WLAN} },
+	{ KE_END, FE_WIFI_LED | FE_UNTESTED } /* no mail led */
+};
+
+/* Wifi subsystem only activates the led. Therefore we need to pass
+ * wifi event as a normal key, then userspace can really change the wifi state.
+ * TODO we need to export led state to userspace (wifi and mail) */
+static struct key_entry keymap_acer_travelmate_610[] __initdata = {
+	{ KE_KEY, 0x01, {KEY_HELP} },
+	{ KE_KEY, 0x02, {KEY_CONFIG} },
+	{ KE_KEY, 0x11, {KEY_PROG1} },
+	{ KE_KEY, 0x12, {KEY_PROG2} },
+	{ KE_KEY, 0x13, {KEY_PROG3} },
+	{ KE_KEY, 0x14, {KEY_MAIL} },
+	{ KE_KEY, 0x15, {KEY_WWW} },
+	{ KE_KEY, 0x40, {KEY_WLAN} },
+	{ KE_END, FE_MAIL_LED | FE_WIFI_LED }
+};
+
+static struct key_entry keymap_acer_travelmate_630[] __initdata = {
+	{ KE_KEY, 0x01, {KEY_HELP} },
+	{ KE_KEY, 0x02, {KEY_CONFIG} },
+	{ KE_KEY, 0x03, {KEY_POWER} },
+	{ KE_KEY, 0x08, {KEY_MUTE} }, /* not 620 */
+	{ KE_KEY, 0x11, {KEY_PROG1} },
+	{ KE_KEY, 0x12, {KEY_PROG2} },
+	{ KE_KEY, 0x13, {KEY_PROG3} },
+	{ KE_KEY, 0x20, {KEY_VOLUMEUP} },
+	{ KE_KEY, 0x21, {KEY_VOLUMEDOWN} },
+	{ KE_KEY, 0x31, {KEY_MAIL} },
+	{ KE_KEY, 0x36, {KEY_WWW} },
+	{ KE_WIFI, 0x30 },
+	{ KE_END, FE_MAIL_LED | FE_UNTESTED }
+};
+
+static struct key_entry keymap_aopen_1559as[] __initdata = {
+	{ KE_KEY,  0x01, {KEY_HELP} },
+	{ KE_KEY,  0x06, {KEY_PROG3} },
+	{ KE_KEY,  0x11, {KEY_PROG1} },
+	{ KE_KEY,  0x12, {KEY_PROG2} },
+	{ KE_WIFI, 0x30 },
+	{ KE_KEY,  0x31, {KEY_MAIL} },
+	{ KE_KEY,  0x36, {KEY_WWW} },
 	{ KE_END,  0 },
 };
 
-static struct key_entry keymap_fs_amilo_d88x0[] = {
-	{ KE_KEY, 0x01, KEY_HELP },
-	{ KE_KEY, 0x08, KEY_MUTE },
-	{ KE_KEY, 0x31, KEY_MAIL },
-	{ KE_KEY, 0x36, KEY_WWW },
-	{ KE_KEY, 0x11, KEY_PROG1 },
-	{ KE_KEY, 0x12, KEY_PROG2 },
-	{ KE_KEY, 0x13, KEY_PROG3 },
+static struct key_entry keymap_fs_amilo_d88x0[] __initdata = {
+	{ KE_KEY, 0x01, {KEY_HELP} },
+	{ KE_KEY, 0x08, {KEY_MUTE} },
+	{ KE_KEY, 0x31, {KEY_MAIL} },
+	{ KE_KEY, 0x36, {KEY_WWW} },
+	{ KE_KEY, 0x11, {KEY_PROG1} },
+	{ KE_KEY, 0x12, {KEY_PROG2} },
+	{ KE_KEY, 0x13, {KEY_PROG3} },
+	{ KE_END, FE_MAIL_LED | FE_WIFI_LED | FE_UNTESTED }
+};
+
+static struct key_entry keymap_wistron_md2900[] __initdata = {
+	{ KE_KEY, 0x01, {KEY_HELP} },
+	{ KE_KEY, 0x02, {KEY_CONFIG} },
+	{ KE_KEY, 0x11, {KEY_PROG1} },
+	{ KE_KEY, 0x12, {KEY_PROG2} },
+	{ KE_KEY, 0x31, {KEY_MAIL} },
+	{ KE_KEY, 0x36, {KEY_WWW} },
+	{ KE_WIFI, 0x30 },
+	{ KE_END, FE_MAIL_LED | FE_UNTESTED }
+};
+
+static struct key_entry keymap_wistron_md96500[] __initdata = {
+	{ KE_KEY, 0x01, {KEY_HELP} },
+	{ KE_KEY, 0x02, {KEY_CONFIG} },
+	{ KE_KEY, 0x05, {KEY_SWITCHVIDEOMODE} }, /* Display selection */
+	{ KE_KEY, 0x06, {KEY_DISPLAYTOGGLE} }, /* Display on/off */
+	{ KE_KEY, 0x08, {KEY_MUTE} },
+	{ KE_KEY, 0x11, {KEY_PROG1} },
+	{ KE_KEY, 0x12, {KEY_PROG2} },
+	{ KE_KEY, 0x20, {KEY_VOLUMEUP} },
+	{ KE_KEY, 0x21, {KEY_VOLUMEDOWN} },
+	{ KE_KEY, 0x22, {KEY_REWIND} },
+	{ KE_KEY, 0x23, {KEY_FORWARD} },
+	{ KE_KEY, 0x24, {KEY_PLAYPAUSE} },
+	{ KE_KEY, 0x25, {KEY_STOPCD} },
+	{ KE_KEY, 0x31, {KEY_MAIL} },
+	{ KE_KEY, 0x36, {KEY_WWW} },
+	{ KE_WIFI, 0x30 },
+	{ KE_BLUETOOTH, 0x44 },
+	{ KE_END, FE_UNTESTED }
+};
+
+static struct key_entry keymap_wistron_generic[] __initdata = {
+	{ KE_KEY, 0x01, {KEY_HELP} },
+	{ KE_KEY, 0x02, {KEY_CONFIG} },
+	{ KE_KEY, 0x03, {KEY_POWER} },
+	{ KE_KEY, 0x05, {KEY_SWITCHVIDEOMODE} }, /* Display selection */
+	{ KE_KEY, 0x06, {KEY_DISPLAYTOGGLE} }, /* Display on/off */
+	{ KE_KEY, 0x08, {KEY_MUTE} },
+	{ KE_KEY, 0x11, {KEY_PROG1} },
+	{ KE_KEY, 0x12, {KEY_PROG2} },
+	{ KE_KEY, 0x13, {KEY_PROG3} },
+	{ KE_KEY, 0x14, {KEY_MAIL} },
+	{ KE_KEY, 0x15, {KEY_WWW} },
+	{ KE_KEY, 0x20, {KEY_VOLUMEUP} },
+	{ KE_KEY, 0x21, {KEY_VOLUMEDOWN} },
+	{ KE_KEY, 0x22, {KEY_REWIND} },
+	{ KE_KEY, 0x23, {KEY_FORWARD} },
+	{ KE_KEY, 0x24, {KEY_PLAYPAUSE} },
+	{ KE_KEY, 0x25, {KEY_STOPCD} },
+	{ KE_KEY, 0x31, {KEY_MAIL} },
+	{ KE_KEY, 0x36, {KEY_WWW} },
+	{ KE_KEY, 0x37, {KEY_DISPLAYTOGGLE} }, /* Display on/off */
+	{ KE_KEY, 0x40, {KEY_WLAN} },
+	{ KE_KEY, 0x49, {KEY_CONFIG} },
+	{ KE_SW, 0x4a, {.sw = {SW_LID, 1}} }, /* lid close */
+	{ KE_SW, 0x4b, {.sw = {SW_LID, 0}} }, /* lid open */
+	{ KE_KEY, 0x6a, {KEY_CONFIG} },
+	{ KE_KEY, 0x6d, {KEY_POWER} },
+	{ KE_KEY, 0x71, {KEY_STOPCD} },
+	{ KE_KEY, 0x72, {KEY_PLAYPAUSE} },
+	{ KE_KEY, 0x74, {KEY_REWIND} },
+	{ KE_KEY, 0x78, {KEY_FORWARD} },
+	{ KE_WIFI, 0x30 },
+	{ KE_BLUETOOTH, 0x44 },
 	{ KE_END, 0 }
 };
 
@@ -390,6 +648,133 @@
 	},
 	{
 		.callback = dmi_matched,
+		.ident = "Acer Aspire 1600",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 1600"),
+		},
+		.driver_data = keymap_acer_aspire_1600
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Acer Aspire 3020",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 3020"),
+		},
+		.driver_data = keymap_acer_aspire_5020
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Acer Aspire 5020",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5020"),
+		},
+		.driver_data = keymap_acer_aspire_5020
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Acer TravelMate 2100",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 2100"),
+		},
+		.driver_data = keymap_acer_aspire_5020
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Acer TravelMate 2410",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 2410"),
+		},
+		.driver_data = keymap_acer_travelmate_2410
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Acer TravelMate C300",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate C300"),
+		},
+		.driver_data = keymap_acer_travelmate_300
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Acer TravelMate C100",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate C100"),
+		},
+		.driver_data = keymap_acer_travelmate_300
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Acer TravelMate C110",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate C110"),
+		},
+		.driver_data = keymap_acer_travelmate_110
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Acer TravelMate 380",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 380"),
+		},
+		.driver_data = keymap_acer_travelmate_380
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Acer TravelMate 370",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 370"),
+		},
+		.driver_data = keymap_acer_travelmate_380 /* keyboard minus 1 key */
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Acer TravelMate 220",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 220"),
+		},
+		.driver_data = keymap_acer_travelmate_220
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Acer TravelMate 260",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 260"),
+		},
+		.driver_data = keymap_acer_travelmate_220
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Acer TravelMate 230",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 230"),
+			/* acerhk looks for "TravelMate F4..." ?! */
+		},
+		.driver_data = keymap_acer_travelmate_230
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Acer TravelMate 280",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 280"),
+		},
+		.driver_data = keymap_acer_travelmate_230
+	},
+	{
+		.callback = dmi_matched,
 		.ident = "Acer TravelMate 240",
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
@@ -399,6 +784,15 @@
 	},
 	{
 		.callback = dmi_matched,
+		.ident = "Acer TravelMate 250",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 250"),
+		},
+		.driver_data = keymap_acer_travelmate_240
+	},
+	{
+		.callback = dmi_matched,
 		.ident = "Acer TravelMate 2424NWXCi",
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
@@ -408,6 +802,51 @@
 	},
 	{
 		.callback = dmi_matched,
+		.ident = "Acer TravelMate 350",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 350"),
+		},
+		.driver_data = keymap_acer_travelmate_350
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Acer TravelMate 360",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 360"),
+		},
+		.driver_data = keymap_acer_travelmate_360
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Acer TravelMate 610",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "ACER"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 610"),
+		},
+		.driver_data = keymap_acer_travelmate_610
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Acer TravelMate 620",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 620"),
+		},
+		.driver_data = keymap_acer_travelmate_630
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Acer TravelMate 630",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 630"),
+		},
+		.driver_data = keymap_acer_travelmate_630
+	},
+	{
+		.callback = dmi_matched,
 		.ident = "AOpen 1559AS",
 		.matches = {
 			DMI_MATCH(DMI_PRODUCT_NAME, "E2U"),
@@ -426,6 +865,51 @@
 	},
 	{
 		.callback = dmi_matched,
+		.ident = "Medion MD 40100",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "MEDIONNB"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "WID2000"),
+		},
+		.driver_data = keymap_wistron_md40100
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Medion MD 2900",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "MEDIONNB"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "WIM 2000"),
+		},
+		.driver_data = keymap_wistron_md2900
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Medion MD 96500",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "MEDIONPC"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "WIM 2040"),
+		},
+		.driver_data = keymap_wistron_md96500
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Medion MD 95400",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "MEDIONPC"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "WIM 2050"),
+		},
+		.driver_data = keymap_wistron_md96500
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Fujitsu Siemens Amilo D7820",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), /* not sure */
+			DMI_MATCH(DMI_PRODUCT_NAME, "Amilo D"),
+		},
+		.driver_data = keymap_fs_amilo_d88x0
+	},
+	{
+		.callback = dmi_matched,
 		.ident = "Fujitsu Siemens Amilo D88x0",
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
@@ -436,17 +920,39 @@
 	{ NULL, }
 };
 
+/* Copy the good keymap, as the original ones are free'd */
+static int __init copy_keymap(void)
+{
+	const struct key_entry *key;
+	struct key_entry *new_keymap;
+	unsigned int length = 1;
+
+	for (key = keymap; key->type != KE_END; key++)
+		length++;
+
+	new_keymap = kmalloc(length * sizeof(struct key_entry), GFP_KERNEL);
+	if (!new_keymap)
+		return -ENOMEM;
+
+	memcpy(new_keymap, keymap, length * sizeof(struct key_entry));
+	keymap = new_keymap;
+
+	return 0;
+}
+
 static int __init select_keymap(void)
 {
+	dmi_check_system(dmi_ids);
 	if (keymap_name != NULL) {
 		if (strcmp (keymap_name, "1557/MS2141") == 0)
 			keymap = keymap_wistron_ms2141;
+		else if (strcmp (keymap_name, "generic") == 0)
+			keymap = keymap_wistron_generic;
 		else {
 			printk(KERN_ERR "wistron_btns: Keymap unknown\n");
 			return -EINVAL;
 		}
 	}
-	dmi_check_system(dmi_ids);
 	if (keymap == NULL) {
 		if (!force) {
 			printk(KERN_ERR "wistron_btns: System unknown\n");
@@ -454,7 +960,8 @@
 		}
 		keymap = keymap_empty;
 	}
-	return 0;
+
+	return copy_keymap();
 }
 
  /* Input layer interface */
@@ -476,12 +983,28 @@
 	input_dev->cdev.dev = &wistron_device->dev;
 
 	for (key = keymap; key->type != KE_END; key++) {
-		if (key->type == KE_KEY) {
-			input_dev->evbit[LONG(EV_KEY)] = BIT(EV_KEY);
-			set_bit(key->keycode, input_dev->keybit);
+		switch (key->type) {
+			case KE_KEY:
+				set_bit(EV_KEY, input_dev->evbit);
+				set_bit(key->keycode, input_dev->keybit);
+				break;
+
+			case KE_SW:
+				set_bit(EV_SW, input_dev->evbit);
+				set_bit(key->sw.code, input_dev->swbit);
+				break;
+
+			default:
+				;
 		}
 	}
 
+	/* reads information flags on KE_END */
+	if (key->code & FE_UNTESTED)
+		printk(KERN_WARNING "Untested laptop multimedia keys, "
+			"please report success or failure to eric.piel"
+			"@tremplin-utc.net\n");
+
 	error = input_register_device(input_dev);
 	if (error) {
 		input_free_device(input_dev);
@@ -499,6 +1022,12 @@
 	input_sync(input_dev);
 }
 
+static void report_switch(unsigned code, int value)
+{
+	input_report_switch(input_dev, code, value);
+	input_sync(input_dev);
+}
+
  /* Driver core */
 
 static int wifi_enabled;
@@ -519,6 +1048,10 @@
 				report_key(key->keycode);
 				break;
 
+			case KE_SW:
+				report_switch(key->sw.code, key->sw.value);
+				break;
+
 			case KE_WIFI:
 				if (have_wifi) {
 					wifi_enabled = !wifi_enabled;
@@ -534,6 +1067,7 @@
 				break;
 
 			case KE_END:
+				break;
 			default:
 				BUG();
 			}
@@ -690,6 +1224,7 @@
 	platform_device_unregister(wistron_device);
 	platform_driver_unregister(&wistron_driver);
 	unmap_bios();
+	kfree(keymap);
 }
 
 module_init(wb_module_init);
diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig
index 35d998c..81dd8c7 100644
--- a/drivers/input/mouse/Kconfig
+++ b/drivers/input/mouse/Kconfig
@@ -37,6 +37,65 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called psmouse.
 
+config MOUSE_PS2_ALPS
+	bool "ALPS PS/2 mouse protocol extension" if EMBEDDED
+	default y
+	depends on MOUSE_PS2
+	---help---
+	  Say Y here if you have an ALPS PS/2 touchpad connected to
+	  your system.
+
+	  If unsure, say Y.
+
+config MOUSE_PS2_LOGIPS2PP
+	bool "Logictech PS/2++ mouse protocol extension" if EMBEDDED
+	default y
+	depends on MOUSE_PS2
+	---help---
+	  Say Y here if you have a Logictech PS/2++ mouse connected to
+	  your system.
+
+	  If unsure, say Y.
+
+config MOUSE_PS2_SYNAPTICS
+	bool "Synaptics PS/2 mouse protocol extension" if EMBEDDED
+	default y
+	depends on MOUSE_PS2
+	---help---
+	  Say Y here if you have a Synaptics PS/2 TouchPad connected to
+	  your system.
+
+	  If unsure, say Y.
+
+config MOUSE_PS2_LIFEBOOK
+	bool "Fujitsu Lifebook PS/2 mouse protocol extension" if EMBEDDED
+	default y
+	depends on MOUSE_PS2
+	---help---
+	  Say Y here if you have a Fujitsu B-series Lifebook PS/2
+	  TouchScreen connected to your system.
+
+	  If unsure, say Y.
+
+config MOUSE_PS2_TRACKPOINT
+	bool "IBM Trackpoint PS/2 mouse protocol extension" if EMBEDDED
+	default y
+	depends on MOUSE_PS2
+	---help---
+	  Say Y here if you have an IBM Trackpoint PS/2 mouse connected
+	  to your system.
+
+	  If unsure, say Y.
+
+config MOUSE_PS2_TOUCHKIT
+	bool "eGalax TouchKit PS/2 protocol extension"
+	depends on MOUSE_PS2
+	---help---
+	  Say Y here if you have an eGalax TouchKit PS/2 touchscreen
+	  connected to your system.
+
+	  If unsure, say N.
+
 config MOUSE_SERIAL
 	tristate "Serial mouse"
 	select SERIO
@@ -96,6 +155,17 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called amimouse.
 
+config MOUSE_ATARI
+	tristate "Atari mouse"
+	depends on ATARI
+	select ATARI_KBD_CORE
+	help
+	  Say Y here if you have an Atari and want its native mouse
+	  supported by the kernel.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called atarimouse.
+
 config MOUSE_RISCPC
 	tristate "Acorn RiscPC mouse"
 	depends on ARCH_ACORN
@@ -118,7 +188,7 @@
 	  digitizer (VSXXX-AB) DEC produced.
 
 config MOUSE_HIL
-	tristate "HIL pointers (mice etc)."     
+	tristate "HIL pointers (mice etc)."
 	depends on GSC || HP300
 	select HP_SDC
 	select HIL_MLC
diff --git a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile
index 21a1de6..6a8f622 100644
--- a/drivers/input/mouse/Makefile
+++ b/drivers/input/mouse/Makefile
@@ -5,6 +5,7 @@
 # Each configuration option enables a list of files.
 
 obj-$(CONFIG_MOUSE_AMIGA)	+= amimouse.o
+obj-$(CONFIG_MOUSE_ATARI)	+= atarimouse.o
 obj-$(CONFIG_MOUSE_RISCPC)	+= rpcmouse.o
 obj-$(CONFIG_MOUSE_INPORT)	+= inport.o
 obj-$(CONFIG_MOUSE_LOGIBM)	+= logibm.o
@@ -14,4 +15,10 @@
 obj-$(CONFIG_MOUSE_HIL)		+= hil_ptr.o
 obj-$(CONFIG_MOUSE_VSXXXAA)	+= vsxxxaa.o
 
-psmouse-objs  := psmouse-base.o alps.o logips2pp.o synaptics.o lifebook.o trackpoint.o
+psmouse-objs := psmouse-base.o synaptics.o
+
+psmouse-$(CONFIG_MOUSE_PS2_ALPS)	+= alps.o
+psmouse-$(CONFIG_MOUSE_PS2_LOGIPS2PP)	+= logips2pp.o
+psmouse-$(CONFIG_MOUSE_PS2_LIFEBOOK)	+= lifebook.o
+psmouse-$(CONFIG_MOUSE_PS2_TRACKPOINT)	+= trackpoint.o
+psmouse-$(CONFIG_MOUSE_PS2_TOUCHKIT)	+= touchkit_ps2.o
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index 4e71a66..cf3e466 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c
@@ -424,14 +424,15 @@
 	struct input_dev *dev1 = psmouse->dev, *dev2;
 	int version;
 
-	psmouse->private = priv = kzalloc(sizeof(struct alps_data), GFP_KERNEL);
+	priv = kzalloc(sizeof(struct alps_data), GFP_KERNEL);
 	dev2 = input_allocate_device();
 	if (!priv || !dev2)
 		goto init_fail;
 
 	priv->dev2 = dev2;
 
-	if (!(priv->i = alps_get_model(psmouse, &version)))
+	priv->i = alps_get_model(psmouse, &version);
+	if (!priv->i)
 		goto init_fail;
 
 	if ((priv->i->flags & ALPS_PASS) && alps_passthrough_mode(psmouse, 1))
@@ -480,7 +481,8 @@
 	dev2->relbit[LONG(REL_X)] |= BIT(REL_X) | BIT(REL_Y);
 	dev2->keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
 
-	input_register_device(priv->dev2);
+	if (input_register_device(priv->dev2))
+		goto init_fail;
 
 	psmouse->protocol_handler = alps_process_byte;
 	psmouse->poll = alps_poll;
@@ -491,9 +493,11 @@
 	/* We are having trouble resyncing ALPS touchpads so disable it for now */
 	psmouse->resync_time = 0;
 
+	psmouse->private = priv;
 	return 0;
 
 init_fail:
+	psmouse_reset(psmouse);
 	input_free_device(dev2);
 	kfree(priv);
 	return -1;
@@ -504,7 +508,8 @@
 	int version;
 	const struct alps_model_info *model;
 
-	if (!(model = alps_get_model(psmouse, &version)))
+	model = alps_get_model(psmouse, &version);
+	if (!model)
 		return -1;
 
 	if (set_properties) {
diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h
index 69db732..4bbddc9 100644
--- a/drivers/input/mouse/alps.h
+++ b/drivers/input/mouse/alps.h
@@ -12,9 +12,6 @@
 #ifndef _ALPS_H
 #define _ALPS_H
 
-int alps_detect(struct psmouse *psmouse, int set_properties);
-int alps_init(struct psmouse *psmouse);
-
 struct alps_model_info {
         unsigned char signature[3];
         unsigned char byte0, mask0;
@@ -23,10 +20,23 @@
 
 struct alps_data {
 	struct input_dev *dev2;		/* Relative device */
-	char name[32];			/* Name */
 	char phys[32];			/* Phys */
 	const struct alps_model_info *i;/* Info */
 	int prev_fin;			/* Finger bit from previous packet */
 };
 
+#ifdef CONFIG_MOUSE_PS2_ALPS
+int alps_detect(struct psmouse *psmouse, int set_properties);
+int alps_init(struct psmouse *psmouse);
+#else
+inline int alps_detect(struct psmouse *psmouse, int set_properties)
+{
+	return -ENOSYS;
+}
+inline int alps_init(struct psmouse *psmouse)
+{
+	return -ENOSYS;
+}
+#endif /* CONFIG_MOUSE_PS2_ALPS */
+
 #endif
diff --git a/drivers/input/mouse/atarimouse.c b/drivers/input/mouse/atarimouse.c
new file mode 100644
index 0000000..43ab656
--- /dev/null
+++ b/drivers/input/mouse/atarimouse.c
@@ -0,0 +1,160 @@
+/*
+ *  Atari mouse driver for Linux/m68k
+ *
+ *  Copyright (c) 2005 Michael Schmitz
+ *
+ *  Based on:
+ *  Amiga mouse driver for Linux/m68k
+ *
+ *  Copyright (c) 2000-2002 Vojtech Pavlik
+ *
+ */
+/*
+ * The low level init and interrupt stuff is handled in arch/mm68k/atari/atakeyb.c
+ * (the keyboard ACIA also handles the mouse and joystick data, and the keyboard
+ * interrupt is shared with the MIDI ACIA so MIDI data also get handled there).
+ * This driver only deals with handing key events off to the input layer.
+ *
+ * Largely based on the old:
+ *
+ * Atari Mouse Driver for Linux
+ * by Robert de Vries (robert@and.nl) 19Jul93
+ *
+ * 16 Nov 1994 Andreas Schwab
+ * Compatibility with busmouse
+ * Support for three button mouse (shamelessly stolen from MiNT)
+ * third button wired to one of the joystick directions on joystick 1
+ *
+ * 1996/02/11 Andreas Schwab
+ * Module support
+ * Allow multiple open's
+ *
+ * Converted to use new generic busmouse code.  5 Apr 1998
+ *   Russell King <rmk@arm.uk.linux.org>
+ */
+
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+
+#include <asm/irq.h>
+#include <asm/setup.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include <asm/atarihw.h>
+#include <asm/atarikb.h>
+#include <asm/atariints.h>
+
+MODULE_AUTHOR("Michael Schmitz <schmitz@biophys.uni-duesseldorf.de>");
+MODULE_DESCRIPTION("Atari mouse driver");
+MODULE_LICENSE("GPL");
+
+static int mouse_threshold[2] = {2,2};
+
+#ifdef __MODULE__
+MODULE_PARM(mouse_threshold, "2i");
+#endif
+#ifdef FIXED_ATARI_JOYSTICK
+extern int atari_mouse_buttons;
+#endif
+static int atamouse_used = 0;
+
+static struct input_dev *atamouse_dev;
+
+static void atamouse_interrupt(char *buf)
+{
+	int buttons, dx, dy;
+
+/*	ikbd_mouse_disable(); */
+
+	buttons = (buf[0] & 1) | ((buf[0] & 2) << 1);
+#ifdef FIXED_ATARI_JOYSTICK
+	buttons |= atari_mouse_buttons & 2;
+	atari_mouse_buttons = buttons;
+#endif
+/*	ikbd_mouse_rel_pos(); */
+
+	/* only relative events get here */
+	dx =  buf[1];
+	dy = -buf[2];
+
+	input_report_rel(atamouse_dev, REL_X, dx);
+	input_report_rel(atamouse_dev, REL_Y, dy);
+
+	input_report_key(atamouse_dev, BTN_LEFT,   buttons & 0x1);
+	input_report_key(atamouse_dev, BTN_MIDDLE, buttons & 0x2);
+	input_report_key(atamouse_dev, BTN_RIGHT,  buttons & 0x4);
+
+	input_sync(atamouse_dev);
+
+	return;
+}
+
+static int atamouse_open(struct input_dev *dev)
+{
+	if (atamouse_used++)
+		return 0;
+
+#ifdef FIXED_ATARI_JOYSTICK
+	atari_mouse_buttons = 0;
+#endif
+	ikbd_mouse_y0_top();
+	ikbd_mouse_thresh(mouse_threshold[0], mouse_threshold[1]);
+	ikbd_mouse_rel_pos();
+	atari_input_mouse_interrupt_hook = atamouse_interrupt;
+	return 0;
+}
+
+static void atamouse_close(struct input_dev *dev)
+{
+	if (!--atamouse_used) {
+		ikbd_mouse_disable();
+		atari_mouse_interrupt_hook = NULL;
+	}
+}
+
+static int __init atamouse_init(void)
+{
+	if (!MACH_IS_ATARI || !ATARIHW_PRESENT(ST_MFP))
+		return -ENODEV;
+
+	if (!(atamouse_dev = input_allocate_device()))
+		return -ENOMEM;
+
+	if (!(atari_keyb_init()))
+		return -ENODEV;
+
+	atamouse_dev->name = "Atari mouse";
+	atamouse_dev->phys = "atamouse/input0";
+	atamouse_dev->id.bustype = BUS_ATARI;
+	atamouse_dev->id.vendor = 0x0001;
+	atamouse_dev->id.product = 0x0002;
+	atamouse_dev->id.version = 0x0100;
+
+	atamouse_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
+	atamouse_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y);
+	atamouse_dev->keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
+	atamouse_dev->open = atamouse_open;
+	atamouse_dev->close = atamouse_close;
+
+	input_register_device(atamouse_dev);
+
+	printk(KERN_INFO "input: %s at keyboard ACIA\n", atamouse_dev->name);
+	return 0;
+}
+
+static void __exit atamouse_exit(void)
+{
+	input_unregister_device(atamouse_dev);
+}
+
+module_init(atamouse_init);
+module_exit(atamouse_exit);
diff --git a/drivers/input/mouse/hil_ptr.c b/drivers/input/mouse/hil_ptr.c
index bfb174f..449bf4d 100644
--- a/drivers/input/mouse/hil_ptr.c
+++ b/drivers/input/mouse/hil_ptr.c
@@ -88,10 +88,12 @@
 	idx = ptr->idx4/4;
 	p = data[idx - 1];
 
-	if ((p & ~HIL_CMDCT_POL) == 
-	    (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_POL)) goto report;
-	if ((p & ~HIL_CMDCT_RPL) == 
-	    (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_RPL)) goto report;
+	if ((p & ~HIL_CMDCT_POL) ==
+	    (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_POL))
+		goto report;
+	if ((p & ~HIL_CMDCT_RPL) ==
+	    (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_RPL))
+		goto report;
 
 	/* Not a poll response.  See if we are loading config records. */
 	switch (p & HIL_PKT_DATA_MASK) {
@@ -101,27 +103,32 @@
 		for (; i < HIL_PTR_MAX_LENGTH; i++)
 			ptr->idd[i] = 0;
 		break;
+
 	case HIL_CMD_RSC:
 		for (i = 0; i < idx; i++)
 			ptr->rsc[i] = ptr->data[i] & HIL_PKT_DATA_MASK;
 		for (; i < HIL_PTR_MAX_LENGTH; i++)
 			ptr->rsc[i] = 0;
 		break;
+
 	case HIL_CMD_EXD:
 		for (i = 0; i < idx; i++)
 			ptr->exd[i] = ptr->data[i] & HIL_PKT_DATA_MASK;
 		for (; i < HIL_PTR_MAX_LENGTH; i++)
 			ptr->exd[i] = 0;
 		break;
+
 	case HIL_CMD_RNM:
 		for (i = 0; i < idx; i++)
 			ptr->rnm[i] = ptr->data[i] & HIL_PKT_DATA_MASK;
 		for (; i < HIL_PTR_MAX_LENGTH + 1; i++)
-			ptr->rnm[i] = '\0';
+			ptr->rnm[i] = 0;
 		break;
+
 	default:
 		/* These occur when device isn't present */
-		if (p == (HIL_ERR_INT | HIL_PKT_CMD)) break; 
+		if (p == (HIL_ERR_INT | HIL_PKT_CMD))
+			break;
 		/* Anything else we'd like to know about. */
 		printk(KERN_WARNING PREFIX "Device sent unknown record %x\n", p);
 		break;
@@ -130,7 +137,8 @@
 
  report:
 	if ((p & HIL_CMDCT_POL) != idx - 1) {
-		printk(KERN_WARNING PREFIX "Malformed poll packet %x (idx = %i)\n", p, idx);
+		printk(KERN_WARNING PREFIX
+			"Malformed poll packet %x (idx = %i)\n", p, idx);
 		goto out;
 	}
 
@@ -139,7 +147,7 @@
 	laxis += i;
 
 	ax16 = ptr->idd[1] & HIL_IDD_HEADER_16BIT; /* 8 or 16bit resolution */
-	absdev = ptr->idd[1] & HIL_IDD_HEADER_ABS; 
+	absdev = ptr->idd[1] & HIL_IDD_HEADER_ABS;
 
 	for (cnt = 1; i < laxis; i++) {
 		unsigned int lo,hi,val;
@@ -157,7 +165,8 @@
 			input_report_abs(dev, ABS_X + i, val);
 		} else {
 			val = (int) (((int8_t)lo) | ((int8_t)hi<<8));
-			if (i%3) val *= -1;
+			if (i%3)
+				val *= -1;
 			input_report_rel(dev, REL_X + i, val);
 		}
 	}
@@ -168,10 +177,11 @@
 		btn = ptr->data[cnt++];
 		up = btn & 1;
 		btn &= 0xfe;
-		if (btn == 0x8e) {
+		if (btn == 0x8e)
 			continue; /* TODO: proximity == touch? */
-		}
-		else if ((btn > 0x8c) || (btn < 0x80)) continue;
+		else
+			if ((btn > 0x8c) || (btn < 0x80))
+				continue;
 		btn = (btn - 0x80) >> 1;
 		btn = ptr->btnmap[btn];
 		input_report_key(dev, btn, !up);
@@ -182,14 +192,14 @@
 	up(&ptr->sem);
 }
 
-static void hil_ptr_process_err(struct hil_ptr *ptr) {
+static void hil_ptr_process_err(struct hil_ptr *ptr)
+{
 	printk(KERN_WARNING PREFIX "errored HIL packet\n");
 	ptr->idx4 = 0;
 	up(&ptr->sem);
-	return;
 }
 
-static irqreturn_t hil_ptr_interrupt(struct serio *serio, 
+static irqreturn_t hil_ptr_interrupt(struct serio *serio,
         unsigned char data, unsigned int flags)
 {
 	struct hil_ptr *ptr;
@@ -197,29 +207,29 @@
 	int idx;
 
 	ptr = serio_get_drvdata(serio);
-	if (ptr == NULL) {
-		BUG();
-		return IRQ_HANDLED;
-	}
+	BUG_ON(ptr == NULL);
 
 	if (ptr->idx4 >= (HIL_PTR_MAX_LENGTH * sizeof(hil_packet))) {
 		hil_ptr_process_err(ptr);
 		return IRQ_HANDLED;
 	}
 	idx = ptr->idx4/4;
-	if (!(ptr->idx4 % 4)) ptr->data[idx] = 0;
+	if (!(ptr->idx4 % 4))
+		ptr->data[idx] = 0;
 	packet = ptr->data[idx];
 	packet |= ((hil_packet)data) << ((3 - (ptr->idx4 % 4)) * 8);
 	ptr->data[idx] = packet;
 
 	/* Records of N 4-byte hil_packets must terminate with a command. */
-	if ((++(ptr->idx4)) % 4) return IRQ_HANDLED;
+	if ((++(ptr->idx4)) % 4)
+		return IRQ_HANDLED;
 	if ((packet & 0xffff0000) != HIL_ERR_INT) {
 		hil_ptr_process_err(ptr);
 		return IRQ_HANDLED;
 	}
-	if (packet & HIL_PKT_CMD) 
+	if (packet & HIL_PKT_CMD)
 		hil_ptr_process_record(ptr);
+
 	return IRQ_HANDLED;
 }
 
@@ -228,10 +238,7 @@
 	struct hil_ptr *ptr;
 
 	ptr = serio_get_drvdata(serio);
-	if (ptr == NULL) {
-		BUG();
-		return;
-	}
+	BUG_ON(ptr == NULL);
 
 	serio_close(serio);
 	input_unregister_device(ptr->dev);
@@ -241,7 +248,7 @@
 static int hil_ptr_connect(struct serio *serio, struct serio_driver *driver)
 {
 	struct hil_ptr	 *ptr;
-	char		 *txt;
+	const char	 *txt;
 	unsigned int	 i, naxsets, btntype;
 	uint8_t		 did, *idd;
 
@@ -252,42 +259,40 @@
 	if (!ptr->dev)
 		goto bail0;
 
-	ptr->dev->private = ptr;
-
 	if (serio_open(serio, driver))
 		goto bail1;
 
 	serio_set_drvdata(serio, ptr);
 	ptr->serio = serio;
 
-	init_MUTEX_LOCKED(&(ptr->sem));
+	init_MUTEX_LOCKED(&ptr->sem);
 
 	/* Get device info.  MLC driver supplies devid/status/etc. */
 	serio->write(serio, 0);
 	serio->write(serio, 0);
 	serio->write(serio, HIL_PKT_CMD >> 8);
 	serio->write(serio, HIL_CMD_IDD);
-	down(&(ptr->sem));
+	down(&ptr->sem);
 
 	serio->write(serio, 0);
 	serio->write(serio, 0);
 	serio->write(serio, HIL_PKT_CMD >> 8);
 	serio->write(serio, HIL_CMD_RSC);
-	down(&(ptr->sem));
+	down(&ptr->sem);
 
 	serio->write(serio, 0);
 	serio->write(serio, 0);
 	serio->write(serio, HIL_PKT_CMD >> 8);
 	serio->write(serio, HIL_CMD_RNM);
-	down(&(ptr->sem));
+	down(&ptr->sem);
 
 	serio->write(serio, 0);
 	serio->write(serio, 0);
 	serio->write(serio, HIL_PKT_CMD >> 8);
 	serio->write(serio, HIL_CMD_EXD);
-	down(&(ptr->sem));
+	down(&ptr->sem);
 
-	up(&(ptr->sem));
+	up(&ptr->sem);
 
 	did = ptr->idd[0];
 	idd = ptr->idd + 1;
@@ -301,12 +306,12 @@
 		ptr->dev->evbit[0] = BIT(EV_ABS);
 		txt = "absolute";
 	}
-	if (!ptr->dev->evbit[0]) {
+	if (!ptr->dev->evbit[0])
 		goto bail2;
-	}
 
 	ptr->nbtn = HIL_IDD_NUM_BUTTONS(idd);
-	if (ptr->nbtn) ptr->dev->evbit[0] |= BIT(EV_KEY);
+	if (ptr->nbtn)
+		ptr->dev->evbit[0] |= BIT(EV_KEY);
 
 	naxsets = HIL_IDD_NUM_AXSETS(*idd);
 	ptr->naxes = HIL_IDD_NUM_AXES_PER_SET(*idd);
@@ -315,7 +320,7 @@
 			did, txt);
 	printk(KERN_INFO PREFIX "HIL pointer has %i buttons and %i sets of %i axes\n",
 			ptr->nbtn, naxsets, ptr->naxes);
-	
+
 	btntype = BTN_MISC;
 	if ((did & HIL_IDD_DID_ABS_TABLET_MASK) == HIL_IDD_DID_ABS_TABLET)
 #ifdef TABLET_SIMULATES_MOUSE
@@ -325,7 +330,7 @@
 #endif
 	if ((did & HIL_IDD_DID_ABS_TSCREEN_MASK) == HIL_IDD_DID_ABS_TSCREEN)
 		btntype = BTN_TOUCH;
-		
+
 	if ((did & HIL_IDD_DID_REL_MOUSE_MASK) == HIL_IDD_DID_REL_MOUSE)
 		btntype = BTN_MOUSE;
 
@@ -341,12 +346,10 @@
 	}
 
 	if ((did & HIL_IDD_DID_TYPE_MASK) == HIL_IDD_DID_TYPE_REL) {
-		for (i = 0; i < ptr->naxes; i++) {
+		for (i = 0; i < ptr->naxes; i++)
 			set_bit(REL_X + i, ptr->dev->relbit);
-		}
-		for (i = 3; (i < ptr->naxes + 3) && (naxsets > 1); i++) {
+		for (i = 3; (i < ptr->naxes + 3) && (naxsets > 1); i++)
 			set_bit(REL_X + i, ptr->dev->relbit);
-		}
 	} else {
 		for (i = 0; i < ptr->naxes; i++) {
 			set_bit(ABS_X + i, ptr->dev->absbit);
@@ -375,7 +378,7 @@
 	ptr->dev->id.vendor	= PCI_VENDOR_ID_HP;
 	ptr->dev->id.product	= 0x0001; /* TODO: get from ptr->rsc */
 	ptr->dev->id.version	= 0x0100; /* TODO: get from ptr->rsc */
-	ptr->dev->cdev.dev	= &serio->dev;
+	ptr->dev->dev.parent	= &serio->dev;
 
 	input_register_device(ptr->dev);
 	printk(KERN_INFO "input: %s (%s), ID: %d\n",
@@ -419,11 +422,11 @@
 {
 	return serio_register_driver(&hil_ptr_serio_driver);
 }
-                
+
 static void __exit hil_ptr_exit(void)
 {
 	serio_unregister_driver(&hil_ptr_serio_driver);
 }
-                        
+
 module_init(hil_ptr_init);
 module_exit(hil_ptr_exit);
diff --git a/drivers/input/mouse/lifebook.c b/drivers/input/mouse/lifebook.c
index 29542f0..1740cad 100644
--- a/drivers/input/mouse/lifebook.c
+++ b/drivers/input/mouse/lifebook.c
@@ -20,6 +20,27 @@
 #include "psmouse.h"
 #include "lifebook.h"
 
+struct lifebook_data {
+	struct input_dev *dev2;		/* Relative device */
+	char phys[32];
+};
+
+static const char *desired_serio_phys;
+
+static int lifebook_set_serio_phys(struct dmi_system_id *d)
+{
+	desired_serio_phys = d->driver_data;
+	return 0;
+}
+
+static unsigned char lifebook_use_6byte_proto;
+
+static int lifebook_set_6byte_proto(struct dmi_system_id *d)
+{
+	lifebook_use_6byte_proto = 1;
+	return 0;
+}
+
 static struct dmi_system_id lifebook_dmi_table[] = {
 	{
 		.ident = "FLORA-ie 55mi",
@@ -56,6 +77,24 @@
 		.matches = {
 			DMI_MATCH(DMI_PRODUCT_NAME, "CF-18"),
 		},
+		.callback = lifebook_set_serio_phys,
+		.driver_data = "isa0060/serio3",
+	},
+	{
+		.ident = "Panasonic CF-28",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Matsushita"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "CF-28"),
+		},
+		.callback = lifebook_set_6byte_proto,
+	},
+	{
+		.ident = "Panasonic CF-29",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Matsushita"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "CF-29"),
+		},
+		.callback = lifebook_set_6byte_proto,
 	},
 	{
 		.ident = "Lifebook B142",
@@ -68,30 +107,70 @@
 
 static psmouse_ret_t lifebook_process_byte(struct psmouse *psmouse)
 {
+	struct lifebook_data *priv = psmouse->private;
+	struct input_dev *dev1 = psmouse->dev;
+	struct input_dev *dev2 = priv->dev2;
 	unsigned char *packet = psmouse->packet;
-	struct input_dev *dev = psmouse->dev;
+	int relative_packet = packet[0] & 0x08;
 
-	if (psmouse->pktcnt != 3)
-		return PSMOUSE_GOOD_DATA;
-
-	/* calculate X and Y */
-	if ((packet[0] & 0x08) == 0x00) {
-		input_report_abs(dev, ABS_X,
-				 (packet[1] | ((packet[0] & 0x30) << 4)));
-		input_report_abs(dev, ABS_Y,
-				 1024 - (packet[2] | ((packet[0] & 0xC0) << 2)));
+	if (relative_packet || !lifebook_use_6byte_proto) {
+		if (psmouse->pktcnt != 3)
+			return PSMOUSE_GOOD_DATA;
 	} else {
-		input_report_rel(dev, REL_X,
-				((packet[0] & 0x10) ? packet[1] - 256 : packet[1]));
-		input_report_rel(dev, REL_Y,
-				 -(int)((packet[0] & 0x20) ? packet[2] - 256 : packet[2]));
+		switch (psmouse->pktcnt) {
+		case 1:
+			return (packet[0] & 0xf8) == 0x00 ?
+				PSMOUSE_GOOD_DATA : PSMOUSE_BAD_DATA;
+		case 2:
+			return PSMOUSE_GOOD_DATA;
+		case 3:
+			return ((packet[2] & 0x30) << 2) == (packet[2] & 0xc0) ?
+				PSMOUSE_GOOD_DATA : PSMOUSE_BAD_DATA;
+		case 4:
+			return (packet[3] & 0xf8) == 0xc0 ?
+				PSMOUSE_GOOD_DATA : PSMOUSE_BAD_DATA;
+		case 5:
+			return (packet[4] & 0xc0) == (packet[2] & 0xc0) ?
+				PSMOUSE_GOOD_DATA : PSMOUSE_BAD_DATA;
+		case 6:
+			if (((packet[5] & 0x30) << 2) != (packet[5] & 0xc0))
+				return PSMOUSE_BAD_DATA;
+			if ((packet[5] & 0xc0) != (packet[1] & 0xc0))
+				return PSMOUSE_BAD_DATA;
+			break; /* report data */
+		}
 	}
 
-	input_report_key(dev, BTN_LEFT, packet[0] & 0x01);
-	input_report_key(dev, BTN_RIGHT, packet[0] & 0x02);
-	input_report_key(dev, BTN_TOUCH, packet[0] & 0x04);
+	if (relative_packet) {
+		if (!dev2)
+			printk(KERN_WARNING "lifebook.c: got relative packet "
+				"but no relative device set up\n");
+	} else if (lifebook_use_6byte_proto) {
+		input_report_abs(dev1, ABS_X,
+				 ((packet[1] & 0x3f) << 6) | (packet[2] & 0x3f));
+		input_report_abs(dev1, ABS_Y,
+				 4096 - (((packet[4] & 0x3f) << 6) | (packet[5] & 0x3f)));
+	} else {
+		input_report_abs(dev1, ABS_X,
+				 (packet[1] | ((packet[0] & 0x30) << 4)));
+		input_report_abs(dev1, ABS_Y,
+				 1024 - (packet[2] | ((packet[0] & 0xC0) << 2)));
+	}
 
-	input_sync(dev);
+	input_report_key(dev1, BTN_TOUCH, packet[0] & 0x04);
+	input_sync(dev1);
+
+	if (dev2) {
+		if (relative_packet) {
+			input_report_rel(dev2, REL_X,
+				((packet[0] & 0x10) ? packet[1] - 256 : packet[1]));
+			input_report_rel(dev2, REL_Y,
+				 -(int)((packet[0] & 0x20) ? packet[2] - 256 : packet[2]));
+		}
+		input_report_key(dev2, BTN_LEFT, packet[0] & 0x01);
+		input_report_key(dev2, BTN_RIGHT, packet[0] & 0x02);
+		input_sync(dev2);
+	}
 
 	return PSMOUSE_FULL_PACKET;
 }
@@ -109,12 +188,20 @@
 	   you leave this call out the touchsreen will never send
 	   absolute coordinates
 	*/
-	param = 0x07;
+	param = lifebook_use_6byte_proto ? 0x08 : 0x07;
 	ps2_command(ps2dev, &param, PSMOUSE_CMD_SETRES);
 
 	return 0;
 }
 
+static void lifebook_relative_mode(struct psmouse *psmouse)
+{
+	struct ps2dev *ps2dev = &psmouse->ps2dev;
+	unsigned char param = 0x06;
+
+	ps2_command(ps2dev, &param, PSMOUSE_CMD_SETRES);
+}
+
 static void lifebook_set_resolution(struct psmouse *psmouse, unsigned int resolution)
 {
 	static const unsigned char params[] = { 0, 1, 2, 2, 3 };
@@ -131,6 +218,8 @@
 static void lifebook_disconnect(struct psmouse *psmouse)
 {
 	psmouse_reset(psmouse);
+	kfree(psmouse->private);
+	psmouse->private = NULL;
 }
 
 int lifebook_detect(struct psmouse *psmouse, int set_properties)
@@ -138,6 +227,10 @@
         if (!dmi_check_system(lifebook_dmi_table))
                 return -1;
 
+	if (desired_serio_phys &&
+	    strcmp(psmouse->ps2dev.serio->phys, desired_serio_phys))
+		return -1;
+
 	if (set_properties) {
 		psmouse->vendor = "Fujitsu";
 		psmouse->name = "Lifebook TouchScreen";
@@ -146,24 +239,78 @@
         return 0;
 }
 
+static int lifebook_create_relative_device(struct psmouse *psmouse)
+{
+	struct input_dev *dev2;
+	struct lifebook_data *priv;
+	int error = -ENOMEM;
+
+	priv = kzalloc(sizeof(struct lifebook_data), GFP_KERNEL);
+	dev2 = input_allocate_device();
+	if (!priv || !dev2)
+		goto err_out;
+
+	priv->dev2 = dev2;
+	snprintf(priv->phys, sizeof(priv->phys),
+		 "%s/input1", psmouse->ps2dev.serio->phys);
+
+	dev2->phys = priv->phys;
+	dev2->name = "PS/2 Touchpad";
+	dev2->id.bustype = BUS_I8042;
+	dev2->id.vendor  = 0x0002;
+	dev2->id.product = PSMOUSE_LIFEBOOK;
+	dev2->id.version = 0x0000;
+	dev2->dev.parent = &psmouse->ps2dev.serio->dev;
+
+	dev2->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
+	dev2->relbit[LONG(REL_X)] = BIT(REL_X) | BIT(REL_Y);
+	dev2->keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT);
+
+	error = input_register_device(priv->dev2);
+	if (error)
+		goto err_out;
+
+	psmouse->private = priv;
+	return 0;
+
+ err_out:
+	input_free_device(dev2);
+	kfree(priv);
+	return error;
+}
+
 int lifebook_init(struct psmouse *psmouse)
 {
-	struct input_dev *input_dev = psmouse->dev;
+	struct input_dev *dev1 = psmouse->dev;
+	int max_coord = lifebook_use_6byte_proto ? 1024 : 4096;
 
 	if (lifebook_absolute_mode(psmouse))
 		return -1;
 
-	input_dev->evbit[0] = BIT(EV_ABS) | BIT(EV_KEY) | BIT(EV_REL);
-	input_dev->keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
-	input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
-	input_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y);
-	input_set_abs_params(input_dev, ABS_X, 0, 1024, 0, 0);
-	input_set_abs_params(input_dev, ABS_Y, 0, 1024, 0, 0);
+	dev1->evbit[0] = BIT(EV_ABS) | BIT(EV_KEY);
+	dev1->relbit[0] = 0;
+	dev1->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
+	input_set_abs_params(dev1, ABS_X, 0, max_coord, 0, 0);
+	input_set_abs_params(dev1, ABS_Y, 0, max_coord, 0, 0);
+
+	if (!desired_serio_phys) {
+		if (lifebook_create_relative_device(psmouse)) {
+			lifebook_relative_mode(psmouse);
+			return -1;
+		}
+	}
 
 	psmouse->protocol_handler = lifebook_process_byte;
 	psmouse->set_resolution = lifebook_set_resolution;
 	psmouse->disconnect = lifebook_disconnect;
 	psmouse->reconnect  = lifebook_absolute_mode;
+
+	psmouse->model = lifebook_use_6byte_proto ? 6 : 3;
+
+	/*
+	 * Use packet size = 3 even when using 6-byte protocol because
+	 * that's what POLL will return on Lifebooks (according to spec).
+	 */
 	psmouse->pktsize = 3;
 
 	return 0;
diff --git a/drivers/input/mouse/lifebook.h b/drivers/input/mouse/lifebook.h
index be1c094..c1647cf 100644
--- a/drivers/input/mouse/lifebook.h
+++ b/drivers/input/mouse/lifebook.h
@@ -11,7 +11,18 @@
 #ifndef _LIFEBOOK_H
 #define _LIFEBOOK_H
 
+#ifdef CONFIG_MOUSE_PS2_LIFEBOOK
 int lifebook_detect(struct psmouse *psmouse, int set_properties);
 int lifebook_init(struct psmouse *psmouse);
+#else
+inline int lifebook_detect(struct psmouse *psmouse, int set_properties)
+{
+	return -ENOSYS;
+}
+inline int lifebook_init(struct psmouse *psmouse)
+{
+	return -ENOSYS;
+}
+#endif
 
 #endif
diff --git a/drivers/input/mouse/logips2pp.c b/drivers/input/mouse/logips2pp.c
index d3ddea2..9df74b7 100644
--- a/drivers/input/mouse/logips2pp.c
+++ b/drivers/input/mouse/logips2pp.c
@@ -200,6 +200,7 @@
 static const struct ps2pp_info *get_model_info(unsigned char model)
 {
 	static const struct ps2pp_info ps2pp_list[] = {
+		{  1,	0,			0 },	/* Simple 2-button mouse */
 		{ 12,	0,			PS2PP_SIDE_BTN},
 		{ 13,	0,			0 },
 		{ 15,	PS2PP_KIND_MX,					/* MX1000 */
@@ -338,12 +339,12 @@
 	param[1] = 0;
 	ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO);
 
-	if (!param[1])
-		return -1;
-
 	model = ((param[0] >> 4) & 0x07) | ((param[0] << 3) & 0x78);
 	buttons = param[1];
 
+	if (!model || !buttons)
+		return -1;
+
 	if ((model_info = get_model_info(model)) != NULL) {
 
 /*
diff --git a/drivers/input/mouse/logips2pp.h b/drivers/input/mouse/logips2pp.h
index 64a8ec5..6e57125 100644
--- a/drivers/input/mouse/logips2pp.h
+++ b/drivers/input/mouse/logips2pp.h
@@ -11,6 +11,13 @@
 #ifndef _LOGIPS2PP_H
 #define _LOGIPS2PP_H
 
+#ifdef CONFIG_MOUSE_PS2_LOGIPS2PP
 int ps2pp_init(struct psmouse *psmouse, int set_properties);
+#else
+inline int ps2pp_init(struct psmouse *psmouse, int set_properties)
+{
+	return -ENOSYS;
+}
+#endif /* CONFIG_MOUSE_PS2_LOGIPS2PP */
 
 #endif
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c
index 0fe5869..f15f695 100644
--- a/drivers/input/mouse/psmouse-base.c
+++ b/drivers/input/mouse/psmouse-base.c
@@ -28,6 +28,7 @@
 #include "alps.h"
 #include "lifebook.h"
 #include "trackpoint.h"
+#include "touchkit_ps2.h"
 
 #define DRIVER_DESC	"PS/2 mouse driver"
 
@@ -569,7 +570,9 @@
 		return PSMOUSE_THINKPS;
 
 /*
- * Try Synaptics TouchPad
+ * Try Synaptics TouchPad. Note that probing is done even if Synaptics protocol
+ * support is disabled in config - we need to know if it is synaptics so we
+ * can reset it properly after probing for intellimouse.
  */
 	if (max_proto > PSMOUSE_PS2 && synaptics_detect(psmouse, set_properties) == 0) {
 		synaptics_hardware = 1;
@@ -605,14 +608,20 @@
 		}
 	}
 
-	if (max_proto > PSMOUSE_IMEX && genius_detect(psmouse, set_properties) == 0)
-		return PSMOUSE_GENPS;
+	if (max_proto > PSMOUSE_IMEX) {
 
-	if (max_proto > PSMOUSE_IMEX && ps2pp_init(psmouse, set_properties) == 0)
-		return PSMOUSE_PS2PP;
+		if (genius_detect(psmouse, set_properties) == 0)
+			return PSMOUSE_GENPS;
 
-	if (max_proto > PSMOUSE_IMEX && trackpoint_detect(psmouse, set_properties) == 0)
-		return PSMOUSE_TRACKPOINT;
+		if (ps2pp_init(psmouse, set_properties) == 0)
+			return PSMOUSE_PS2PP;
+
+		if (trackpoint_detect(psmouse, set_properties) == 0)
+			return PSMOUSE_TRACKPOINT;
+
+		if (touchkit_ps2_detect(psmouse, set_properties) == 0)
+			return PSMOUSE_TOUCHKIT_PS2;
+	}
 
 /*
  * Reset to defaults in case the device got confused by extended
@@ -654,12 +663,14 @@
 		.maxproto	= 1,
 		.detect		= ps2bare_detect,
 	},
+#ifdef CONFIG_MOUSE_PS2_LOGIPS2PP
 	{
 		.type		= PSMOUSE_PS2PP,
 		.name		= "PS2++",
 		.alias		= "logitech",
 		.detect		= ps2pp_init,
 	},
+#endif
 	{
 		.type		= PSMOUSE_THINKPS,
 		.name		= "ThinkPS/2",
@@ -686,6 +697,7 @@
 		.maxproto	= 1,
 		.detect		= im_explorer_detect,
 	},
+#ifdef CONFIG_MOUSE_PS2_SYNAPTICS
 	{
 		.type		= PSMOUSE_SYNAPTICS,
 		.name		= "SynPS/2",
@@ -693,6 +705,8 @@
 		.detect		= synaptics_detect,
 		.init		= synaptics_init,
 	},
+#endif
+#ifdef CONFIG_MOUSE_PS2_ALPS
 	{
 		.type		= PSMOUSE_ALPS,
 		.name		= "AlpsPS/2",
@@ -700,18 +714,31 @@
 		.detect		= alps_detect,
 		.init		= alps_init,
 	},
+#endif
+#ifdef CONFIG_MOUSE_PS2_LIFEBOOK
 	{
 		.type		= PSMOUSE_LIFEBOOK,
 		.name		= "LBPS/2",
 		.alias		= "lifebook",
 		.init		= lifebook_init,
 	},
+#endif
+#ifdef CONFIG_MOUSE_PS2_TRACKPOINT
 	{
 		.type		= PSMOUSE_TRACKPOINT,
 		.name		= "TPPS/2",
 		.alias		= "trackpoint",
 		.detect		= trackpoint_detect,
 	},
+#endif
+#ifdef CONFIG_MOUSE_PS2_TOUCHKIT
+	{
+		.type		= PSMOUSE_TOUCHKIT_PS2,
+		.name		= "touchkitPS/2",
+		.alias		= "touchkit",
+		.detect		= touchkit_ps2_detect,
+	},
+#endif
 	{
 		.type		= PSMOUSE_AUTO,
 		.name		= "auto",
@@ -823,12 +850,6 @@
 static void psmouse_initialize(struct psmouse *psmouse)
 {
 /*
- * We set the mouse into streaming mode.
- */
-
-	ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSTREAM);
-
-/*
  * We set the mouse report rate, resolution and scaling.
  */
 
@@ -1062,8 +1083,7 @@
 {
 	struct input_dev *input_dev = psmouse->dev;
 
-	input_dev->private = psmouse;
-	input_dev->cdev.dev = &psmouse->ps2dev.serio->dev;
+	input_dev->dev.parent = &psmouse->ps2dev.serio->dev;
 
 	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
 	input_dev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h
index cf1de95..3964e8a 100644
--- a/drivers/input/mouse/psmouse.h
+++ b/drivers/input/mouse/psmouse.h
@@ -87,6 +87,7 @@
 	PSMOUSE_ALPS,
 	PSMOUSE_LIFEBOOK,
 	PSMOUSE_TRACKPOINT,
+	PSMOUSE_TOUCHKIT_PS2,
 	PSMOUSE_AUTO		/* This one should always be last */
 };
 
diff --git a/drivers/input/mouse/sermouse.c b/drivers/input/mouse/sermouse.c
index a85d747..77b8ee2 100644
--- a/drivers/input/mouse/sermouse.c
+++ b/drivers/input/mouse/sermouse.c
@@ -69,7 +69,8 @@
 	switch (sermouse->count) {
 
 		case 0:
-			if ((data & 0xf8) != 0x80) return;
+			if ((data & 0xf8) != 0x80)
+				return;
 			input_report_key(dev, BTN_LEFT,   !(data & 4));
 			input_report_key(dev, BTN_RIGHT,  !(data & 1));
 			input_report_key(dev, BTN_MIDDLE, !(data & 2));
@@ -107,7 +108,10 @@
 	struct input_dev *dev = sermouse->dev;
 	signed char *buf = sermouse->buf;
 
-	if (data & 0x40) sermouse->count = 0;
+	if (data & 0x40)
+		sermouse->count = 0;
+	else if (sermouse->count == 0)
+		return;
 
 	switch (sermouse->count) {
 
@@ -169,7 +173,8 @@
 
 		case 5:
 		case 7: /* Ignore anything besides MZ++ */
-			if (sermouse->type != SERIO_MZPP) break;
+			if (sermouse->type != SERIO_MZPP)
+				break;
 
 			switch (buf[1]) {
 
@@ -206,13 +211,16 @@
 {
 	struct sermouse *sermouse = serio_get_drvdata(serio);
 
-	if (time_after(jiffies, sermouse->last + HZ/10)) sermouse->count = 0;
+	if (time_after(jiffies, sermouse->last + HZ/10))
+		sermouse->count = 0;
+
 	sermouse->last = jiffies;
 
 	if (sermouse->type > SERIO_SUN)
 		sermouse_process_ms(sermouse, data);
 	else
 		sermouse_process_msc(sermouse, data);
+
 	return IRQ_HANDLED;
 }
 
@@ -258,12 +266,11 @@
 	input_dev->id.vendor  = sermouse->type;
 	input_dev->id.product = c;
 	input_dev->id.version = 0x0100;
-	input_dev->cdev.dev = &serio->dev;
+	input_dev->dev.parent = &serio->dev;
 
 	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
 	input_dev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT);
 	input_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y);
-	input_dev->private = sermouse;
 
 	if (c & 0x01) set_bit(BTN_MIDDLE, input_dev->keybit);
 	if (c & 0x02) set_bit(BTN_SIDE, input_dev->keybit);
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
index f0f9413..c77788b 100644
--- a/drivers/input/mouse/synaptics.c
+++ b/drivers/input/mouse/synaptics.c
@@ -40,21 +40,10 @@
 #define YMIN_NOMINAL 1408
 #define YMAX_NOMINAL 4448
 
-/*****************************************************************************
- *	Synaptics communications functions
- ****************************************************************************/
 
-/*
- * Send a command to the synpatics touchpad by special commands
- */
-static int synaptics_send_cmd(struct psmouse *psmouse, unsigned char c, unsigned char *param)
-{
-	if (psmouse_sliced_command(psmouse, c))
-		return -1;
-	if (ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_GETINFO))
-		return -1;
-	return 0;
-}
+/*****************************************************************************
+ *	Stuff we need even when we do not want native Synaptics support
+ ****************************************************************************/
 
 /*
  * Set the synaptics touchpad mode byte by special commands
@@ -71,6 +60,54 @@
 	return 0;
 }
 
+int synaptics_detect(struct psmouse *psmouse, int set_properties)
+{
+	struct ps2dev *ps2dev = &psmouse->ps2dev;
+	unsigned char param[4];
+
+	param[0] = 0;
+
+	ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES);
+	ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES);
+	ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES);
+	ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES);
+	ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO);
+
+	if (param[1] != 0x47)
+		return -ENODEV;
+
+	if (set_properties) {
+		psmouse->vendor = "Synaptics";
+		psmouse->name = "TouchPad";
+	}
+
+	return 0;
+}
+
+void synaptics_reset(struct psmouse *psmouse)
+{
+	/* reset touchpad back to relative mode, gestures enabled */
+	synaptics_mode_cmd(psmouse, 0);
+}
+
+#ifdef CONFIG_MOUSE_PS2_SYNAPTICS
+
+/*****************************************************************************
+ *	Synaptics communications functions
+ ****************************************************************************/
+
+/*
+ * Send a command to the synpatics touchpad by special commands
+ */
+static int synaptics_send_cmd(struct psmouse *psmouse, unsigned char c, unsigned char *param)
+{
+	if (psmouse_sliced_command(psmouse, c))
+		return -1;
+	if (ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_GETINFO))
+		return -1;
+	return 0;
+}
+
 /*
  * Read the model-id bytes from the touchpad
  * see also SYN_MODEL_* macros
@@ -529,12 +566,6 @@
 	clear_bit(REL_Y, dev->relbit);
 }
 
-void synaptics_reset(struct psmouse *psmouse)
-{
-	/* reset touchpad back to relative mode, gestures enabled */
-	synaptics_mode_cmd(psmouse, 0);
-}
-
 static void synaptics_disconnect(struct psmouse *psmouse)
 {
 	synaptics_reset(psmouse);
@@ -569,30 +600,6 @@
 	return 0;
 }
 
-int synaptics_detect(struct psmouse *psmouse, int set_properties)
-{
-	struct ps2dev *ps2dev = &psmouse->ps2dev;
-	unsigned char param[4];
-
-	param[0] = 0;
-
-	ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES);
-	ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES);
-	ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES);
-	ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES);
-	ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO);
-
-	if (param[1] != 0x47)
-		return -1;
-
-	if (set_properties) {
-		psmouse->vendor = "Synaptics";
-		psmouse->name = "TouchPad";
-	}
-
-	return 0;
-}
-
 #if defined(__i386__)
 #include <linux/dmi.h>
 static struct dmi_system_id toshiba_dmi_table[] = {
@@ -648,6 +655,16 @@
 
 	set_input_params(psmouse->dev, priv);
 
+	/*
+	 * Encode touchpad model so that it can be used to set
+	 * input device->id.version and be visible to userspace.
+	 * Because version is __u16 we have to drop something.
+	 * Hardware info bits seem to be good candidates as they
+	 * are documented to be for Synaptics corp. internal use.
+	 */
+	psmouse->model = ((priv->model_id & 0x00ff0000) >> 8) |
+			  (priv->model_id & 0x000000ff);
+
 	psmouse->protocol_handler = synaptics_process_byte;
 	psmouse->set_rate = synaptics_set_rate;
 	psmouse->disconnect = synaptics_disconnect;
@@ -680,4 +697,12 @@
 	return -1;
 }
 
+#else /* CONFIG_MOUSE_PS2_SYNAPTICS */
+
+int synaptics_init(struct psmouse *psmouse)
+{
+	return -ENOSYS;
+}
+
+#endif /* CONFIG_MOUSE_PS2_SYNAPTICS */
 
diff --git a/drivers/input/mouse/synaptics.h b/drivers/input/mouse/synaptics.h
index 68fff1d..02aa4cf 100644
--- a/drivers/input/mouse/synaptics.h
+++ b/drivers/input/mouse/synaptics.h
@@ -9,10 +9,6 @@
 #ifndef _SYNAPTICS_H
 #define _SYNAPTICS_H
 
-extern int synaptics_detect(struct psmouse *psmouse, int set_properties);
-extern int synaptics_init(struct psmouse *psmouse);
-extern void synaptics_reset(struct psmouse *psmouse);
-
 /* synaptics queries */
 #define SYN_QUE_IDENTIFY		0x00
 #define SYN_QUE_MODES			0x01
@@ -62,9 +58,9 @@
 #define SYN_MODE_WMODE(m)		((m) & (1 << 0))
 
 /* synaptics identify query bits */
-#define SYN_ID_MODEL(i) 		(((i) >> 4) & 0x0f)
-#define SYN_ID_MAJOR(i) 		((i) & 0x0f)
-#define SYN_ID_MINOR(i) 		(((i) >> 16) & 0xff)
+#define SYN_ID_MODEL(i)			(((i) >> 4) & 0x0f)
+#define SYN_ID_MAJOR(i)			((i) & 0x0f)
+#define SYN_ID_MINOR(i)			(((i) >> 16) & 0xff)
 #define SYN_ID_IS_SYNAPTICS(i)		((((i) >> 8) & 0xff) == 0x47)
 
 /* synaptics special commands */
@@ -98,8 +94,8 @@
 struct synaptics_data {
 	/* Data read from the touchpad */
 	unsigned long int model_id;		/* Model-ID */
-	unsigned long int capabilities; 	/* Capabilities */
-	unsigned long int ext_cap; 		/* Extended Capabilities */
+	unsigned long int capabilities;		/* Capabilities */
+	unsigned long int ext_cap;		/* Extended Capabilities */
 	unsigned long int identity;		/* Identification */
 
 	unsigned char pkt_type;			/* packet type - old, new, etc */
@@ -107,4 +103,8 @@
 	int scroll;
 };
 
+int synaptics_detect(struct psmouse *psmouse, int set_properties);
+int synaptics_init(struct psmouse *psmouse);
+void synaptics_reset(struct psmouse *psmouse);
+
 #endif /* _SYNAPTICS_H */
diff --git a/drivers/input/mouse/touchkit_ps2.c b/drivers/input/mouse/touchkit_ps2.c
new file mode 100644
index 0000000..7b977fd
--- /dev/null
+++ b/drivers/input/mouse/touchkit_ps2.c
@@ -0,0 +1,100 @@
+/* ----------------------------------------------------------------------------
+ * touchkit_ps2.c  --  Driver for eGalax TouchKit PS/2 Touchscreens
+ *
+ * Copyright (C) 2005 by Stefan Lucke
+ * Copyright (C) 2004 by Daniel Ritz
+ * Copyright (C) by Todd E. Johnson (mtouchusb.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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Based upon touchkitusb.c
+ *
+ * Vendor documentation is available in support section of:
+ * http://www.egalax.com.tw/
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+
+#include <linux/input.h>
+#include <linux/serio.h>
+#include <linux/libps2.h>
+
+#include "psmouse.h"
+#include "touchkit_ps2.h"
+
+#define TOUCHKIT_MAX_XC			0x07ff
+#define TOUCHKIT_MAX_YC			0x07ff
+
+#define TOUCHKIT_CMD			0x0a
+#define TOUCHKIT_CMD_LENGTH		1
+
+#define TOUCHKIT_CMD_ACTIVE		'A'
+#define TOUCHKIT_CMD_FIRMWARE_VERSION	'D'
+#define TOUCHKIT_CMD_CONTROLLER_TYPE	'E'
+
+#define TOUCHKIT_SEND_PARMS(s, r, c)	((s) << 12 | (r) << 8 | (c))
+
+#define TOUCHKIT_GET_TOUCHED(packet)	(((packet)[0]) & 0x01)
+#define TOUCHKIT_GET_X(packet)		(((packet)[1] << 7) | (packet)[2])
+#define TOUCHKIT_GET_Y(packet)		(((packet)[3] << 7) | (packet)[4])
+
+static psmouse_ret_t touchkit_ps2_process_byte(struct psmouse *psmouse)
+{
+	unsigned char *packet = psmouse->packet;
+	struct input_dev *dev = psmouse->dev;
+
+	if (psmouse->pktcnt != 5)
+		return PSMOUSE_GOOD_DATA;
+
+	input_report_abs(dev, ABS_X, TOUCHKIT_GET_X(packet));
+	input_report_abs(dev, ABS_Y, TOUCHKIT_GET_Y(packet));
+	input_report_key(dev, BTN_TOUCH, TOUCHKIT_GET_TOUCHED(packet));
+	input_sync(dev);
+
+	return PSMOUSE_FULL_PACKET;
+}
+
+int touchkit_ps2_detect(struct psmouse *psmouse, int set_properties)
+{
+	struct input_dev *dev = psmouse->dev;
+	unsigned char param[3];
+	int command;
+
+	param[0] = TOUCHKIT_CMD_LENGTH;
+	param[1] = TOUCHKIT_CMD_ACTIVE;
+	command = TOUCHKIT_SEND_PARMS(2, 3, TOUCHKIT_CMD);
+
+	if (ps2_command(&psmouse->ps2dev, param, command))
+		return -ENODEV;
+
+	if (param[0] != TOUCHKIT_CMD || param[1] != 0x01 ||
+	    param[2] != TOUCHKIT_CMD_ACTIVE)
+		return -ENODEV;
+
+	if (set_properties) {
+		dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+		set_bit(BTN_TOUCH, dev->keybit);
+		input_set_abs_params(dev, ABS_X, 0, TOUCHKIT_MAX_XC, 0, 0);
+		input_set_abs_params(dev, ABS_Y, 0, TOUCHKIT_MAX_YC, 0, 0);
+
+		psmouse->vendor = "eGalax";
+		psmouse->name = "Touchscreen";
+		psmouse->protocol_handler = touchkit_ps2_process_byte;
+		psmouse->pktsize = 5;
+	}
+
+	return 0;
+}
diff --git a/drivers/input/mouse/touchkit_ps2.h b/drivers/input/mouse/touchkit_ps2.h
new file mode 100644
index 0000000..61e9dfd
--- /dev/null
+++ b/drivers/input/mouse/touchkit_ps2.h
@@ -0,0 +1,24 @@
+/* ----------------------------------------------------------------------------
+ * touchkit_ps2.h  --  Driver for eGalax TouchKit PS/2 Touchscreens
+ *
+ * Copyright (C) 2005 by Stefan Lucke
+ * Copyright (c) 2005 Vojtech Pavlik
+ *
+ * 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 _TOUCHKIT_PS2_H
+#define _TOUCHKIT_PS2_H
+
+#ifdef CONFIG_MOUSE_PS2_TOUCHKIT
+int touchkit_ps2_detect(struct psmouse *psmouse, int set_properties);
+#else
+inline int touchkit_ps2_detect(struct psmouse *psmouse, int set_properties)
+{
+	return -ENOSYS;
+}
+#endif /* CONFIG_MOUSE_PS2_TOUCHKIT */
+
+#endif
diff --git a/drivers/input/mouse/trackpoint.h b/drivers/input/mouse/trackpoint.h
index 050298b..c10a6e7 100644
--- a/drivers/input/mouse/trackpoint.h
+++ b/drivers/input/mouse/trackpoint.h
@@ -142,6 +142,13 @@
 	unsigned char ext_dev;
 };
 
-extern int trackpoint_detect(struct psmouse *psmouse, int set_properties);
+#ifdef CONFIG_MOUSE_PS2_TRACKPOINT
+int trackpoint_detect(struct psmouse *psmouse, int set_properties);
+#else
+inline int trackpoint_detect(struct psmouse *psmouse, int set_properties)
+{
+	return -ENOSYS;
+}
+#endif /* CONFIG_MOUSE_PS2_TRACKPOINT */
 
 #endif /* _TRACKPOINT_H */
diff --git a/drivers/input/mouse/vsxxxaa.c b/drivers/input/mouse/vsxxxaa.c
index c3d64fc..4a32157 100644
--- a/drivers/input/mouse/vsxxxaa.c
+++ b/drivers/input/mouse/vsxxxaa.c
@@ -508,8 +508,7 @@
 	input_dev->name = mouse->name;
 	input_dev->phys = mouse->phys;
 	input_dev->id.bustype = BUS_RS232;
-	input_dev->cdev.dev = &serio->dev;
-	input_dev->private = mouse;
+	input_dev->dev.parent = &serio->dev;
 
 	set_bit (EV_KEY, input_dev->evbit);		/* We have buttons */
 	set_bit (EV_REL, input_dev->evbit);
diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c
index 664bcc8..7678e98 100644
--- a/drivers/input/mousedev.c
+++ b/drivers/input/mousedev.c
@@ -63,9 +63,12 @@
 	int minor;
 	char name[16];
 	wait_queue_head_t wait;
-	struct list_head list;
+	struct list_head client_list;
 	struct input_handle handle;
 
+	struct list_head mixdev_node;
+	int mixdev_open;
+
 	struct mousedev_hw_data packet;
 	unsigned int pkt_count;
 	int old_x[4], old_y[4];
@@ -85,7 +88,7 @@
 };
 
 #define PACKET_QUEUE_LEN	16
-struct mousedev_list {
+struct mousedev_client {
 	struct fasync_struct *fasync;
 	struct mousedev *mousedev;
 	struct list_head node;
@@ -111,6 +114,7 @@
 
 static struct mousedev *mousedev_table[MOUSEDEV_MINORS];
 static struct mousedev mousedev_mix;
+static LIST_HEAD(mousedev_mix_list);
 
 #define fx(i)  (mousedev->old_x[(mousedev->pkt_count - (i)) & 03])
 #define fy(i)  (mousedev->old_y[(mousedev->pkt_count - (i)) & 03])
@@ -120,32 +124,33 @@
 	int size, tmp;
 	enum { FRACTION_DENOM = 128 };
 
-	if (mousedev->touch) {
-		size = dev->absmax[ABS_X] - dev->absmin[ABS_X];
-		if (size == 0)
-			size = 256 * 2;
+	switch (code) {
+		case ABS_X:
+			fx(0) = value;
+			if (mousedev->touch && mousedev->pkt_count >= 2) {
+				size = dev->absmax[ABS_X] - dev->absmin[ABS_X];
+				if (size == 0)
+					size = 256 * 2;
+				tmp = ((value - fx(2)) * (256 * FRACTION_DENOM)) / size;
+				tmp += mousedev->frac_dx;
+				mousedev->packet.dx = tmp / FRACTION_DENOM;
+				mousedev->frac_dx = tmp - mousedev->packet.dx * FRACTION_DENOM;
+			}
+			break;
 
-		switch (code) {
-			case ABS_X:
-				fx(0) = value;
-				if (mousedev->pkt_count >= 2) {
-					tmp = ((value - fx(2)) * (256 * FRACTION_DENOM)) / size;
-					tmp += mousedev->frac_dx;
-					mousedev->packet.dx = tmp / FRACTION_DENOM;
-					mousedev->frac_dx = tmp - mousedev->packet.dx * FRACTION_DENOM;
-				}
-				break;
-
-			case ABS_Y:
-				fy(0) = value;
-				if (mousedev->pkt_count >= 2) {
-					tmp = -((value - fy(2)) * (256 * FRACTION_DENOM)) / size;
-					tmp += mousedev->frac_dy;
-					mousedev->packet.dy = tmp / FRACTION_DENOM;
-					mousedev->frac_dy = tmp - mousedev->packet.dy * FRACTION_DENOM;
-				}
-				break;
-		}
+		case ABS_Y:
+			fy(0) = value;
+			if (mousedev->touch && mousedev->pkt_count >= 2) {
+				/* use X size to keep the same scale */
+				size = dev->absmax[ABS_X] - dev->absmin[ABS_X];
+				if (size == 0)
+					size = 256 * 2;
+				tmp = -((value - fy(2)) * (256 * FRACTION_DENOM)) / size;
+				tmp += mousedev->frac_dy;
+				mousedev->packet.dy = tmp / FRACTION_DENOM;
+				mousedev->frac_dy = tmp - mousedev->packet.dy * FRACTION_DENOM;
+			}
+			break;
 	}
 }
 
@@ -223,47 +228,47 @@
 
 static void mousedev_notify_readers(struct mousedev *mousedev, struct mousedev_hw_data *packet)
 {
-	struct mousedev_list *list;
+	struct mousedev_client *client;
 	struct mousedev_motion *p;
 	unsigned long flags;
 	int wake_readers = 0;
 
-	list_for_each_entry(list, &mousedev->list, node) {
-		spin_lock_irqsave(&list->packet_lock, flags);
+	list_for_each_entry(client, &mousedev->client_list, node) {
+		spin_lock_irqsave(&client->packet_lock, flags);
 
-		p = &list->packets[list->head];
-		if (list->ready && p->buttons != mousedev->packet.buttons) {
-			unsigned int new_head = (list->head + 1) % PACKET_QUEUE_LEN;
-			if (new_head != list->tail) {
-				p = &list->packets[list->head = new_head];
+		p = &client->packets[client->head];
+		if (client->ready && p->buttons != mousedev->packet.buttons) {
+			unsigned int new_head = (client->head + 1) % PACKET_QUEUE_LEN;
+			if (new_head != client->tail) {
+				p = &client->packets[client->head = new_head];
 				memset(p, 0, sizeof(struct mousedev_motion));
 			}
 		}
 
 		if (packet->abs_event) {
-			p->dx += packet->x - list->pos_x;
-			p->dy += packet->y - list->pos_y;
-			list->pos_x = packet->x;
-			list->pos_y = packet->y;
+			p->dx += packet->x - client->pos_x;
+			p->dy += packet->y - client->pos_y;
+			client->pos_x = packet->x;
+			client->pos_y = packet->y;
 		}
 
-		list->pos_x += packet->dx;
-		list->pos_x = list->pos_x < 0 ? 0 : (list->pos_x >= xres ? xres : list->pos_x);
-		list->pos_y += packet->dy;
-		list->pos_y = list->pos_y < 0 ? 0 : (list->pos_y >= yres ? yres : list->pos_y);
+		client->pos_x += packet->dx;
+		client->pos_x = client->pos_x < 0 ? 0 : (client->pos_x >= xres ? xres : client->pos_x);
+		client->pos_y += packet->dy;
+		client->pos_y = client->pos_y < 0 ? 0 : (client->pos_y >= yres ? yres : client->pos_y);
 
 		p->dx += packet->dx;
 		p->dy += packet->dy;
 		p->dz += packet->dz;
 		p->buttons = mousedev->packet.buttons;
 
-		if (p->dx || p->dy || p->dz || p->buttons != list->last_buttons)
-			list->ready = 1;
+		if (p->dx || p->dy || p->dz || p->buttons != client->last_buttons)
+			client->ready = 1;
 
-		spin_unlock_irqrestore(&list->packet_lock, flags);
+		spin_unlock_irqrestore(&client->packet_lock, flags);
 
-		if (list->ready) {
-			kill_fasync(&list->fasync, SIGIO, POLL_IN);
+		if (client->ready) {
+			kill_fasync(&client->fasync, SIGIO, POLL_IN);
 			wake_readers = 1;
 		}
 	}
@@ -351,9 +356,9 @@
 static int mousedev_fasync(int fd, struct file *file, int on)
 {
 	int retval;
-	struct mousedev_list *list = file->private_data;
+	struct mousedev_client *client = file->private_data;
 
-	retval = fasync_helper(fd, file, on, &list->fasync);
+	retval = fasync_helper(fd, file, on, &client->fasync);
 
 	return retval < 0 ? retval : 0;
 }
@@ -364,50 +369,95 @@
 	kfree(mousedev);
 }
 
-static void mixdev_release(void)
+static int mixdev_add_device(struct mousedev *mousedev)
 {
-	struct input_handle *handle;
+	int error;
 
-	list_for_each_entry(handle, &mousedev_handler.h_list, h_node) {
-		struct mousedev *mousedev = handle->private;
+	if (mousedev_mix.open) {
+		error = input_open_device(&mousedev->handle);
+		if (error)
+			return error;
 
-		if (!mousedev->open) {
-			if (mousedev->exist)
-				input_close_device(&mousedev->handle);
-			else
-				mousedev_free(mousedev);
-		}
-	}
-}
-
-static int mousedev_release(struct inode * inode, struct file * file)
-{
-	struct mousedev_list *list = file->private_data;
-
-	mousedev_fasync(-1, file, 0);
-
-	list_del(&list->node);
-
-	if (!--list->mousedev->open) {
-		if (list->mousedev->minor == MOUSEDEV_MIX)
-			mixdev_release();
-		else if (!mousedev_mix.open) {
-			if (list->mousedev->exist)
-				input_close_device(&list->mousedev->handle);
-			else
-				mousedev_free(list->mousedev);
-		}
+		mousedev->open++;
+		mousedev->mixdev_open++;
 	}
 
-	kfree(list);
+	list_add_tail(&mousedev->mixdev_node, &mousedev_mix_list);
+
 	return 0;
 }
 
-static int mousedev_open(struct inode * inode, struct file * file)
+static void mixdev_remove_device(struct mousedev *mousedev)
 {
-	struct mousedev_list *list;
-	struct input_handle *handle;
+	if (mousedev->mixdev_open) {
+		mousedev->mixdev_open = 0;
+		if (!--mousedev->open && mousedev->exist)
+			input_close_device(&mousedev->handle);
+	}
+
+	list_del_init(&mousedev->mixdev_node);
+}
+
+static void mixdev_open_devices(void)
+{
 	struct mousedev *mousedev;
+
+	list_for_each_entry(mousedev, &mousedev_mix_list, mixdev_node) {
+		if (mousedev->exist && !mousedev->open) {
+			if (input_open_device(&mousedev->handle))
+				continue;
+
+			mousedev->open++;
+			mousedev->mixdev_open++;
+		}
+	}
+}
+
+static void mixdev_close_devices(void)
+{
+	struct mousedev *mousedev, *next;
+
+	list_for_each_entry_safe(mousedev, next, &mousedev_mix_list, mixdev_node) {
+		if (mousedev->mixdev_open) {
+			mousedev->mixdev_open = 0;
+			if (!--mousedev->open) {
+				if (mousedev->exist)
+					input_close_device(&mousedev->handle);
+				else
+					mousedev_free(mousedev);
+			}
+		}
+	}
+}
+
+static int mousedev_release(struct inode *inode, struct file *file)
+{
+	struct mousedev_client *client = file->private_data;
+	struct mousedev *mousedev = client->mousedev;
+
+	mousedev_fasync(-1, file, 0);
+
+	list_del(&client->node);
+	kfree(client);
+
+	if (!--mousedev->open) {
+		if (mousedev->minor == MOUSEDEV_MIX)
+			mixdev_close_devices();
+		else if (mousedev->exist)
+			input_close_device(&mousedev->handle);
+		else
+			mousedev_free(mousedev);
+	}
+
+	return 0;
+}
+
+
+static int mousedev_open(struct inode *inode, struct file *file)
+{
+	struct mousedev_client *client;
+	struct mousedev *mousedev;
+	int error;
 	int i;
 
 #ifdef CONFIG_INPUT_MOUSEDEV_PSAUX
@@ -417,31 +467,37 @@
 #endif
 		i = iminor(inode) - MOUSEDEV_MINOR_BASE;
 
-	if (i >= MOUSEDEV_MINORS || !mousedev_table[i])
+	if (i >= MOUSEDEV_MINORS)
 		return -ENODEV;
 
-	if (!(list = kzalloc(sizeof(struct mousedev_list), GFP_KERNEL)))
+	mousedev = mousedev_table[i];
+	if (!mousedev)
+		return -ENODEV;
+
+	client = kzalloc(sizeof(struct mousedev_client), GFP_KERNEL);
+	if (!client)
 		return -ENOMEM;
 
-	spin_lock_init(&list->packet_lock);
-	list->pos_x = xres / 2;
-	list->pos_y = yres / 2;
-	list->mousedev = mousedev_table[i];
-	list_add_tail(&list->node, &mousedev_table[i]->list);
-	file->private_data = list;
+	spin_lock_init(&client->packet_lock);
+	client->pos_x = xres / 2;
+	client->pos_y = yres / 2;
+	client->mousedev = mousedev;
+	list_add_tail(&client->node, &mousedev->client_list);
 
-	if (!list->mousedev->open++) {
-		if (list->mousedev->minor == MOUSEDEV_MIX) {
-			list_for_each_entry(handle, &mousedev_handler.h_list, h_node) {
-				mousedev = handle->private;
-				if (!mousedev->open && mousedev->exist)
-					input_open_device(handle);
+	if (!mousedev->open++) {
+		if (mousedev->minor == MOUSEDEV_MIX)
+			mixdev_open_devices();
+		else if (mousedev->exist) {
+			error = input_open_device(&mousedev->handle);
+			if (error) {
+				list_del(&client->node);
+				kfree(client);
+				return error;
 			}
-		} else
-			if (!mousedev_mix.open && list->mousedev->exist)
-				input_open_device(&list->mousedev->handle);
+		}
 	}
 
+	file->private_data = client;
 	return 0;
 }
 
@@ -450,13 +506,13 @@
 	return delta > limit ? limit : (delta < -limit ? -limit : delta);
 }
 
-static void mousedev_packet(struct mousedev_list *list, signed char *ps2_data)
+static void mousedev_packet(struct mousedev_client *client, signed char *ps2_data)
 {
 	struct mousedev_motion *p;
 	unsigned long flags;
 
-	spin_lock_irqsave(&list->packet_lock, flags);
-	p = &list->packets[list->tail];
+	spin_lock_irqsave(&client->packet_lock, flags);
+	p = &client->packets[client->tail];
 
 	ps2_data[0] = 0x08 | ((p->dx < 0) << 4) | ((p->dy < 0) << 5) | (p->buttons & 0x07);
 	ps2_data[1] = mousedev_limit_delta(p->dx, 127);
@@ -464,44 +520,44 @@
 	p->dx -= ps2_data[1];
 	p->dy -= ps2_data[2];
 
-	switch (list->mode) {
+	switch (client->mode) {
 		case MOUSEDEV_EMUL_EXPS:
 			ps2_data[3] = mousedev_limit_delta(p->dz, 7);
 			p->dz -= ps2_data[3];
 			ps2_data[3] = (ps2_data[3] & 0x0f) | ((p->buttons & 0x18) << 1);
-			list->bufsiz = 4;
+			client->bufsiz = 4;
 			break;
 
 		case MOUSEDEV_EMUL_IMPS:
 			ps2_data[0] |= ((p->buttons & 0x10) >> 3) | ((p->buttons & 0x08) >> 1);
 			ps2_data[3] = mousedev_limit_delta(p->dz, 127);
 			p->dz -= ps2_data[3];
-			list->bufsiz = 4;
+			client->bufsiz = 4;
 			break;
 
 		case MOUSEDEV_EMUL_PS2:
 		default:
 			ps2_data[0] |= ((p->buttons & 0x10) >> 3) | ((p->buttons & 0x08) >> 1);
 			p->dz = 0;
-			list->bufsiz = 3;
+			client->bufsiz = 3;
 			break;
 	}
 
 	if (!p->dx && !p->dy && !p->dz) {
-		if (list->tail == list->head) {
-			list->ready = 0;
-			list->last_buttons = p->buttons;
+		if (client->tail == client->head) {
+			client->ready = 0;
+			client->last_buttons = p->buttons;
 		} else
-			list->tail = (list->tail + 1) % PACKET_QUEUE_LEN;
+			client->tail = (client->tail + 1) % PACKET_QUEUE_LEN;
 	}
 
-	spin_unlock_irqrestore(&list->packet_lock, flags);
+	spin_unlock_irqrestore(&client->packet_lock, flags);
 }
 
 
-static ssize_t mousedev_write(struct file * file, const char __user * buffer, size_t count, loff_t *ppos)
+static ssize_t mousedev_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
 {
-	struct mousedev_list *list = file->private_data;
+	struct mousedev_client *client = file->private_data;
 	unsigned char c;
 	unsigned int i;
 
@@ -510,95 +566,95 @@
 		if (get_user(c, buffer + i))
 			return -EFAULT;
 
-		if (c == mousedev_imex_seq[list->imexseq]) {
-			if (++list->imexseq == MOUSEDEV_SEQ_LEN) {
-				list->imexseq = 0;
-				list->mode = MOUSEDEV_EMUL_EXPS;
+		if (c == mousedev_imex_seq[client->imexseq]) {
+			if (++client->imexseq == MOUSEDEV_SEQ_LEN) {
+				client->imexseq = 0;
+				client->mode = MOUSEDEV_EMUL_EXPS;
 			}
 		} else
-			list->imexseq = 0;
+			client->imexseq = 0;
 
-		if (c == mousedev_imps_seq[list->impsseq]) {
-			if (++list->impsseq == MOUSEDEV_SEQ_LEN) {
-				list->impsseq = 0;
-				list->mode = MOUSEDEV_EMUL_IMPS;
+		if (c == mousedev_imps_seq[client->impsseq]) {
+			if (++client->impsseq == MOUSEDEV_SEQ_LEN) {
+				client->impsseq = 0;
+				client->mode = MOUSEDEV_EMUL_IMPS;
 			}
 		} else
-			list->impsseq = 0;
+			client->impsseq = 0;
 
-		list->ps2[0] = 0xfa;
+		client->ps2[0] = 0xfa;
 
 		switch (c) {
 
 			case 0xeb: /* Poll */
-				mousedev_packet(list, &list->ps2[1]);
-				list->bufsiz++; /* account for leading ACK */
+				mousedev_packet(client, &client->ps2[1]);
+				client->bufsiz++; /* account for leading ACK */
 				break;
 
 			case 0xf2: /* Get ID */
-				switch (list->mode) {
-					case MOUSEDEV_EMUL_PS2:  list->ps2[1] = 0; break;
-					case MOUSEDEV_EMUL_IMPS: list->ps2[1] = 3; break;
-					case MOUSEDEV_EMUL_EXPS: list->ps2[1] = 4; break;
+				switch (client->mode) {
+					case MOUSEDEV_EMUL_PS2:  client->ps2[1] = 0; break;
+					case MOUSEDEV_EMUL_IMPS: client->ps2[1] = 3; break;
+					case MOUSEDEV_EMUL_EXPS: client->ps2[1] = 4; break;
 				}
-				list->bufsiz = 2;
+				client->bufsiz = 2;
 				break;
 
 			case 0xe9: /* Get info */
-				list->ps2[1] = 0x60; list->ps2[2] = 3; list->ps2[3] = 200;
-				list->bufsiz = 4;
+				client->ps2[1] = 0x60; client->ps2[2] = 3; client->ps2[3] = 200;
+				client->bufsiz = 4;
 				break;
 
 			case 0xff: /* Reset */
-				list->impsseq = list->imexseq = 0;
-				list->mode = MOUSEDEV_EMUL_PS2;
-				list->ps2[1] = 0xaa; list->ps2[2] = 0x00;
-				list->bufsiz = 3;
+				client->impsseq = client->imexseq = 0;
+				client->mode = MOUSEDEV_EMUL_PS2;
+				client->ps2[1] = 0xaa; client->ps2[2] = 0x00;
+				client->bufsiz = 3;
 				break;
 
 			default:
-				list->bufsiz = 1;
+				client->bufsiz = 1;
 				break;
 		}
 
-		list->buffer = list->bufsiz;
+		client->buffer = client->bufsiz;
 	}
 
-	kill_fasync(&list->fasync, SIGIO, POLL_IN);
+	kill_fasync(&client->fasync, SIGIO, POLL_IN);
 
-	wake_up_interruptible(&list->mousedev->wait);
+	wake_up_interruptible(&client->mousedev->wait);
 
 	return count;
 }
 
-static ssize_t mousedev_read(struct file * file, char __user * buffer, size_t count, loff_t *ppos)
+static ssize_t mousedev_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
 {
-	struct mousedev_list *list = file->private_data;
+	struct mousedev_client *client = file->private_data;
 	int retval = 0;
 
-	if (!list->ready && !list->buffer && (file->f_flags & O_NONBLOCK))
+	if (!client->ready && !client->buffer && (file->f_flags & O_NONBLOCK))
 		return -EAGAIN;
 
-	retval = wait_event_interruptible(list->mousedev->wait,
-					  !list->mousedev->exist || list->ready || list->buffer);
+	retval = wait_event_interruptible(client->mousedev->wait,
+					  !client->mousedev->exist || client->ready || client->buffer);
 
 	if (retval)
 		return retval;
 
-	if (!list->mousedev->exist)
+	if (!client->mousedev->exist)
 		return -ENODEV;
 
-	if (!list->buffer && list->ready) {
-		mousedev_packet(list, list->ps2);
-		list->buffer = list->bufsiz;
+	if (!client->buffer && client->ready) {
+		mousedev_packet(client, client->ps2);
+		client->buffer = client->bufsiz;
 	}
 
-	if (count > list->buffer)
-		count = list->buffer;
+	if (count > client->buffer)
+		count = client->buffer;
 
-	list->buffer -= count;
+	client->buffer -= count;
 
-	if (copy_to_user(buffer, list->ps2 + list->bufsiz - list->buffer - count, count))
+	if (copy_to_user(buffer, client->ps2 + client->bufsiz - client->buffer - count, count))
 		return -EFAULT;
 
 	return count;
@@ -607,11 +663,12 @@
 /* No kernel lock - fine */
 static unsigned int mousedev_poll(struct file *file, poll_table *wait)
 {
-	struct mousedev_list *list = file->private_data;
+	struct mousedev_client *client = file->private_data;
+	struct mousedev *mousedev = client->mousedev;
 
-	poll_wait(file, &list->mousedev->wait, wait);
-	return ((list->ready || list->buffer) ? (POLLIN | POLLRDNORM) : 0) |
-		(list->mousedev->exist ? 0 : (POLLHUP | POLLERR));
+	poll_wait(file, &mousedev->wait, wait);
+	return ((client->ready || client->buffer) ? (POLLIN | POLLRDNORM) : 0) |
+		(mousedev->exist ? 0 : (POLLHUP | POLLERR));
 }
 
 static const struct file_operations mousedev_fops = {
@@ -624,23 +681,27 @@
 	.fasync =	mousedev_fasync,
 };
 
-static struct input_handle *mousedev_connect(struct input_handler *handler, struct input_dev *dev,
-					     const struct input_device_id *id)
+static int mousedev_connect(struct input_handler *handler, struct input_dev *dev,
+			    const struct input_device_id *id)
 {
 	struct mousedev *mousedev;
 	struct class_device *cdev;
-	int minor = 0;
+	dev_t devt;
+	int minor;
+	int error;
 
 	for (minor = 0; minor < MOUSEDEV_MINORS && mousedev_table[minor]; minor++);
 	if (minor == MOUSEDEV_MINORS) {
 		printk(KERN_ERR "mousedev: no more free mousedev devices\n");
-		return NULL;
+		return -ENFILE;
 	}
 
-	if (!(mousedev = kzalloc(sizeof(struct mousedev), GFP_KERNEL)))
-		return NULL;
+	mousedev = kzalloc(sizeof(struct mousedev), GFP_KERNEL);
+	if (!mousedev)
+		return -ENOMEM;
 
-	INIT_LIST_HEAD(&mousedev->list);
+	INIT_LIST_HEAD(&mousedev->client_list);
+	INIT_LIST_HEAD(&mousedev->mixdev_node);
 	init_waitqueue_head(&mousedev->wait);
 
 	mousedev->minor = minor;
@@ -651,42 +712,66 @@
 	mousedev->handle.private = mousedev;
 	sprintf(mousedev->name, "mouse%d", minor);
 
-	if (mousedev_mix.open)
-		input_open_device(&mousedev->handle);
-
 	mousedev_table[minor] = mousedev;
 
-	cdev = class_device_create(&input_class, &dev->cdev,
-			MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + minor),
-			dev->cdev.dev, mousedev->name);
+	devt = MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + minor),
+
+	cdev = class_device_create(&input_class, &dev->cdev, devt,
+				   dev->cdev.dev, mousedev->name);
+	if (IS_ERR(cdev)) {
+		error = PTR_ERR(cdev);
+		goto err_free_mousedev;
+	}
 
 	/* temporary symlink to keep userspace happy */
-	sysfs_create_link(&input_class.subsys.kset.kobj, &cdev->kobj,
-			  mousedev->name);
+	error = sysfs_create_link(&input_class.subsys.kobj,
+				  &cdev->kobj, mousedev->name);
+	if (error)
+		goto err_cdev_destroy;
 
-	return &mousedev->handle;
+	error = input_register_handle(&mousedev->handle);
+	if (error)
+		goto err_remove_link;
+
+	error = mixdev_add_device(mousedev);
+	if (error)
+		goto err_unregister_handle;
+
+	return 0;
+
+ err_unregister_handle:
+	input_unregister_handle(&mousedev->handle);
+ err_remove_link:
+	sysfs_remove_link(&input_class.subsys.kobj, mousedev->name);
+ err_cdev_destroy:
+	class_device_destroy(&input_class, devt);
+ err_free_mousedev:
+	mousedev_table[minor] = NULL;
+	kfree(mousedev);
+	return error;
 }
 
 static void mousedev_disconnect(struct input_handle *handle)
 {
 	struct mousedev *mousedev = handle->private;
-	struct mousedev_list *list;
+	struct mousedev_client *client;
 
-	sysfs_remove_link(&input_class.subsys.kset.kobj, mousedev->name);
+	input_unregister_handle(handle);
+
+	sysfs_remove_link(&input_class.subsys.kobj, mousedev->name);
 	class_device_destroy(&input_class,
 			MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + mousedev->minor));
 	mousedev->exist = 0;
 
+	mixdev_remove_device(mousedev);
+
 	if (mousedev->open) {
 		input_close_device(handle);
 		wake_up_interruptible(&mousedev->wait);
-		list_for_each_entry(list, &mousedev->list, node)
-			kill_fasync(&list->fasync, SIGIO, POLL_HUP);
-	} else {
-		if (mousedev_mix.open)
-			input_close_device(handle);
+		list_for_each_entry(client, &mousedev->client_list, node)
+			kill_fasync(&client->fasync, SIGIO, POLL_HUP);
+	} else
 		mousedev_free(mousedev);
-	}
 }
 
 static const struct input_device_id mousedev_ids[] = {
@@ -714,7 +799,7 @@
 		.absbit = { BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE) | BIT(ABS_TOOL_WIDTH) },
 	},	/* A touchpad */
 
-	{ }, 	/* Terminating entry */
+	{ },	/* Terminating entry */
 };
 
 MODULE_DEVICE_TABLE(input, mousedev_ids);
@@ -746,7 +831,7 @@
 		return error;
 
 	memset(&mousedev_mix, 0, sizeof(struct mousedev));
-	INIT_LIST_HEAD(&mousedev_mix.list);
+	INIT_LIST_HEAD(&mousedev_mix.client_list);
 	init_waitqueue_head(&mousedev_mix.wait);
 	mousedev_table[MOUSEDEV_MIX] = &mousedev_mix;
 	mousedev_mix.exist = 1;
diff --git a/drivers/input/power.c b/drivers/input/power.c
deleted file mode 100644
index ee82464..0000000
--- a/drivers/input/power.c
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * $Id: power.c,v 1.10 2001/09/25 09:17:15 vojtech Exp $
- *
- *  Copyright (c) 2001 "Crazy" James Simmons
- *
- *  Input driver Power Management.
- *
- *  Sponsored by Transvirtual Technology.
- */
-
-/*
- * This program is free software; you can redistribute it and/or 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
- *
- * Should you need to contact me, the author, you can do so by
- * e-mail - mail your message to <jsimmons@transvirtual.com>.
- */
-
-#include <linux/module.h>
-#include <linux/input.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/tty.h>
-#include <linux/delay.h>
-#include <linux/pm.h>
-
-static struct input_handler power_handler;
-
-/*
- * Power management can't be done in a interrupt context. So we have to
- * use keventd.
- */
-static int suspend_button_pushed = 0;
-static void suspend_button_task_handler(void *data)
-{
-        udelay(200); /* debounce */
-        suspend_button_pushed = 0;
-}
-
-static DECLARE_WORK(suspend_button_task, suspend_button_task_handler, NULL);
-
-static void power_event(struct input_handle *handle, unsigned int type,
-		        unsigned int code, int down)
-{
-	struct input_dev *dev = handle->dev;
-
-	printk("Entering power_event\n");
-
-	if (type == EV_PWR) {
-		switch (code) {
-			case KEY_SUSPEND:
-				printk("Powering down entire device\n");
-
-				if (!suspend_button_pushed) {
-                			suspend_button_pushed = 1;
-                        		schedule_work(&suspend_button_task);
-                		}
-				break;
-			case KEY_POWER:
-				/* Hum power down the machine. */
-				break;
-			default:
-				return;
-		}
-	}
-
-	if (type == EV_KEY) {
-		switch (code) {
-			case KEY_SUSPEND:
-				printk("Powering down input device\n");
-				/* This is risky. See pm.h for details. */
-				if (dev->state != PM_RESUME)
-					dev->state = PM_RESUME;
-				else
-					dev->state = PM_SUSPEND;
-				pm_send(dev->pm_dev, dev->state, dev);
-				break;
-			case KEY_POWER:
-				/* Turn the input device off completely ? */
-				break;
-			default:
-				return;
-		}
-	}
-	return;
-}
-
-static struct input_handle *power_connect(struct input_handler *handler,
-					  struct input_dev *dev,
-					  const struct input_device_id *id)
-{
-	struct input_handle *handle;
-
-	if (!(handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL)))
-		return NULL;
-
-	handle->dev = dev;
-	handle->handler = handler;
-
-	input_open_device(handle);
-
-	printk(KERN_INFO "power.c: Adding power management to input layer\n");
-	return handle;
-}
-
-static void power_disconnect(struct input_handle *handle)
-{
-	input_close_device(handle);
-	kfree(handle);
-}
-
-static const struct input_device_id power_ids[] = {
-	{
-		.flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT,
-		.evbit = { BIT(EV_KEY) },
-		.keybit = { [LONG(KEY_SUSPEND)] = BIT(KEY_SUSPEND) }
-	},
-	{
-		.flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT,
-		.evbit = { BIT(EV_KEY) },
-		.keybit = { [LONG(KEY_POWER)] = BIT(KEY_POWER) }
-	},
-	{
-		.flags = INPUT_DEVICE_ID_MATCH_EVBIT,
-		.evbit = { BIT(EV_PWR) },
-	},
-	{ }, 	/* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE(input, power_ids);
-
-static struct input_handler power_handler = {
-	.event =	power_event,
-	.connect =	power_connect,
-	.disconnect =	power_disconnect,
-	.name =		"power",
-	.id_table =	power_ids,
-};
-
-static int __init power_init(void)
-{
-	return input_register_handler(&power_handler);
-}
-
-static void __exit power_exit(void)
-{
-	input_unregister_handler(&power_handler);
-}
-
-module_init(power_init);
-module_exit(power_exit);
-
-MODULE_AUTHOR("James Simmons <jsimmons@transvirtual.com>");
-MODULE_DESCRIPTION("Input Power Management driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/input/serio/hil_mlc.c b/drivers/input/serio/hil_mlc.c
index 4fa93ff..93a1a6b 100644
--- a/drivers/input/serio/hil_mlc.c
+++ b/drivers/input/serio/hil_mlc.c
@@ -32,11 +32,11 @@
  *
  *	Driver theory of operation:
  *
- *	Some access methods and an ISR is defined by the sub-driver 
- *	(e.g. hp_sdc_mlc.c).  These methods are expected to provide a 
- *	few bits of logic in addition to raw access to the HIL MLC, 
- *	specifically, the ISR, which is entirely registered by the 
- *	sub-driver and invoked directly, must check for record 
+ *	Some access methods and an ISR is defined by the sub-driver
+ *	(e.g. hp_sdc_mlc.c).  These methods are expected to provide a
+ *	few bits of logic in addition to raw access to the HIL MLC,
+ *	specifically, the ISR, which is entirely registered by the
+ *	sub-driver and invoked directly, must check for record
  *	termination or packet match, at which point a semaphore must
  *	be cleared and then the hil_mlcs_tasklet must be scheduled.
  *
@@ -47,7 +47,7 @@
  *	itself if output is pending.  (This rescheduling should be replaced
  *	at some point with a sub-driver-specific mechanism.)
  *
- *	A timer task prods the tasklet once per second to prevent 
+ *	A timer task prods the tasklet once per second to prevent
  *	hangups when attached devices do not return expected data
  *	and to initiate probes of the loop for new devices.
  */
@@ -83,69 +83,85 @@
 
 /********************** Device info/instance management **********************/
 
-static void hil_mlc_clear_di_map (hil_mlc *mlc, int val) {
+static void hil_mlc_clear_di_map(hil_mlc *mlc, int val)
+{
 	int j;
-	for (j = val; j < 7 ; j++) {
+
+	for (j = val; j < 7 ; j++)
 		mlc->di_map[j] = -1;
-	}
 }
 
-static void hil_mlc_clear_di_scratch (hil_mlc *mlc) {
-	memset(&(mlc->di_scratch), 0, sizeof(mlc->di_scratch));
+static void hil_mlc_clear_di_scratch(hil_mlc *mlc)
+{
+	memset(&mlc->di_scratch, 0, sizeof(mlc->di_scratch));
 }
 
-static void hil_mlc_copy_di_scratch (hil_mlc *mlc, int idx) {
-	memcpy(&(mlc->di[idx]), &(mlc->di_scratch), sizeof(mlc->di_scratch));
+static void hil_mlc_copy_di_scratch(hil_mlc *mlc, int idx)
+{
+	memcpy(&mlc->di[idx], &mlc->di_scratch, sizeof(mlc->di_scratch));
 }
 
-static int hil_mlc_match_di_scratch (hil_mlc *mlc) {
+static int hil_mlc_match_di_scratch(hil_mlc *mlc)
+{
 	int idx;
 
 	for (idx = 0; idx < HIL_MLC_DEVMEM; idx++) {
-		int j, found;
+		int j, found = 0;
 
 		/* In-use slots are not eligible. */
-		found = 0;
-		for (j = 0; j < 7 ; j++) {
-			if (mlc->di_map[j] == idx) found++;
-		}
-		if (found) continue;
-		if (!memcmp(mlc->di + idx, 
-			    &(mlc->di_scratch), 
-			    sizeof(mlc->di_scratch))) break;
+		for (j = 0; j < 7 ; j++)
+			if (mlc->di_map[j] == idx)
+				found++;
+
+		if (found)
+			continue;
+
+		if (!memcmp(mlc->di + idx, &mlc->di_scratch,
+				sizeof(mlc->di_scratch)))
+			break;
 	}
-	return((idx >= HIL_MLC_DEVMEM) ? -1 : idx);
+	return idx >= HIL_MLC_DEVMEM ? -1 : idx;
 }
 
-static int hil_mlc_find_free_di(hil_mlc *mlc) {
+static int hil_mlc_find_free_di(hil_mlc *mlc)
+{
 	int idx;
-	/* TODO: Pick all-zero slots first, failing that, 
-	 * randomize the slot picked among those eligible. 
+
+	/* TODO: Pick all-zero slots first, failing that,
+	 * randomize the slot picked among those eligible.
 	 */
 	for (idx = 0; idx < HIL_MLC_DEVMEM; idx++) {
-		int j, found;
-		found = 0;
-		for (j = 0; j < 7 ; j++) {
-			if (mlc->di_map[j] == idx) found++;
-		}
-		if (!found) break;
+		int j, found = 0;
+
+		for (j = 0; j < 7 ; j++)
+			if (mlc->di_map[j] == idx)
+				found++;
+
+		if (!found)
+			break;
 	}
-	return(idx); /* Note: It is guaranteed at least one above will match */
+
+	return idx; /* Note: It is guaranteed at least one above will match */
 }
 
-static inline void hil_mlc_clean_serio_map(hil_mlc *mlc) {
+static inline void hil_mlc_clean_serio_map(hil_mlc *mlc)
+{
 	int idx;
+
 	for (idx = 0; idx < HIL_MLC_DEVMEM; idx++) {
-		int j, found;
-		found = 0;
-		for (j = 0; j < 7 ; j++) {
-			if (mlc->di_map[j] == idx) found++;
-		}
-		if (!found) mlc->serio_map[idx].di_revmap = -1;
+		int j, found = 0;
+
+		for (j = 0; j < 7 ; j++)
+			if (mlc->di_map[j] == idx)
+				found++;
+
+		if (!found)
+			mlc->serio_map[idx].di_revmap = -1;
 	}
 }
 
-static void hil_mlc_send_polls(hil_mlc *mlc) {
+static void hil_mlc_send_polls(hil_mlc *mlc)
+{
 	int did, i, cnt;
 	struct serio *serio;
 	struct serio_driver *drv;
@@ -157,26 +173,31 @@
 
 	while (mlc->icount < 15 - i) {
 		hil_packet p;
+
 		p = mlc->ipacket[i];
 		if (did != (p & HIL_PKT_ADDR_MASK) >> 8) {
-			if (drv == NULL || drv->interrupt == NULL) goto skip;
+			if (drv && drv->interrupt) {
+				drv->interrupt(serio, 0, 0);
+				drv->interrupt(serio, HIL_ERR_INT >> 16, 0);
+				drv->interrupt(serio, HIL_PKT_CMD >> 8,  0);
+				drv->interrupt(serio, HIL_CMD_POL + cnt, 0);
+			}
 
-			drv->interrupt(serio, 0, 0);
-			drv->interrupt(serio, HIL_ERR_INT >> 16, 0);
-			drv->interrupt(serio, HIL_PKT_CMD >> 8,  0);
-			drv->interrupt(serio, HIL_CMD_POL + cnt, 0);
-		skip:
 			did = (p & HIL_PKT_ADDR_MASK) >> 8;
 			serio = did ? mlc->serio[mlc->di_map[did-1]] : NULL;
 			drv = (serio != NULL) ? serio->drv : NULL;
 			cnt = 0;
 		}
-		cnt++; i++;
-		if (drv == NULL || drv->interrupt == NULL) continue;
-		drv->interrupt(serio, (p >> 24), 0);
-		drv->interrupt(serio, (p >> 16) & 0xff, 0);
-		drv->interrupt(serio, (p >> 8) & ~HIL_PKT_ADDR_MASK, 0);
-		drv->interrupt(serio, p & 0xff, 0);
+
+		cnt++;
+		i++;
+
+		if (drv && drv->interrupt) {
+			drv->interrupt(serio, (p >> 24), 0);
+			drv->interrupt(serio, (p >> 16) & 0xff, 0);
+			drv->interrupt(serio, (p >> 8) & ~HIL_PKT_ADDR_MASK, 0);
+			drv->interrupt(serio, p & 0xff, 0);
+		}
 	}
 }
 
@@ -215,12 +236,16 @@
 #define HILSEN_DOZE	(HILSEN_SAME | HILSEN_SCHED | HILSEN_BREAK)
 #define HILSEN_SLEEP	(HILSEN_SAME | HILSEN_BREAK)
 
-static int hilse_match(hil_mlc *mlc, int unused) {
+static int hilse_match(hil_mlc *mlc, int unused)
+{
 	int rc;
+
 	rc = hil_mlc_match_di_scratch(mlc);
 	if (rc == -1) {
 		rc = hil_mlc_find_free_di(mlc);
-		if (rc == -1) goto err;
+		if (rc == -1)
+			goto err;
+
 #ifdef HIL_MLC_DEBUG
 		printk(KERN_DEBUG PREFIX "new in slot %i\n", rc);
 #endif
@@ -231,6 +256,7 @@
 		serio_rescan(mlc->serio[rc]);
 		return -1;
 	}
+
 	mlc->di_map[mlc->ddi] = rc;
 #ifdef HIL_MLC_DEBUG
 	printk(KERN_DEBUG PREFIX "same in slot %i\n", rc);
@@ -238,152 +264,177 @@
 	mlc->serio_map[rc].di_revmap = mlc->ddi;
 	hil_mlc_clean_serio_map(mlc);
 	return 0;
+
  err:
 	printk(KERN_ERR PREFIX "Residual device slots exhausted, close some serios!\n");
 	return 1;
 }
 
 /* An LCV used to prevent runaway loops, forces 5 second sleep when reset. */
-static int hilse_init_lcv(hil_mlc *mlc, int unused) {
+static int hilse_init_lcv(hil_mlc *mlc, int unused)
+{
 	struct timeval tv;
 
 	do_gettimeofday(&tv);
 
-	if(mlc->lcv == 0) goto restart;  /* First init, no need to dally */
-	if(tv.tv_sec - mlc->lcv_tv.tv_sec < 5) return -1;
- restart:
+	if (mlc->lcv && (tv.tv_sec - mlc->lcv_tv.tv_sec) < 5)
+		return -1;
+
 	mlc->lcv_tv = tv;
 	mlc->lcv = 0;
+
 	return 0;
 }
 
-static int hilse_inc_lcv(hil_mlc *mlc, int lim) {
-	if (mlc->lcv++ >= lim) return -1;
-	return 0;
+static int hilse_inc_lcv(hil_mlc *mlc, int lim)
+{
+	return mlc->lcv++ >= lim ? -1 : 0;
 }
 
 #if 0
-static int hilse_set_lcv(hil_mlc *mlc, int val) {
+static int hilse_set_lcv(hil_mlc *mlc, int val)
+{
 	mlc->lcv = val;
+
 	return 0;
 }
 #endif
 
 /* Management of the discovered device index (zero based, -1 means no devs) */
-static int hilse_set_ddi(hil_mlc *mlc, int val) {
+static int hilse_set_ddi(hil_mlc *mlc, int val)
+{
 	mlc->ddi = val;
 	hil_mlc_clear_di_map(mlc, val + 1);
+
 	return 0;
 }
 
-static int hilse_dec_ddi(hil_mlc *mlc, int unused) {
+static int hilse_dec_ddi(hil_mlc *mlc, int unused)
+{
 	mlc->ddi--;
-	if (mlc->ddi <= -1) { 
+	if (mlc->ddi <= -1) {
 		mlc->ddi = -1;
 		hil_mlc_clear_di_map(mlc, 0);
 		return -1;
 	}
 	hil_mlc_clear_di_map(mlc, mlc->ddi + 1);
+
 	return 0;
 }
 
-static int hilse_inc_ddi(hil_mlc *mlc, int unused) {
-	if (mlc->ddi >= 6) {
-		BUG();
-		return -1;
-	}
+static int hilse_inc_ddi(hil_mlc *mlc, int unused)
+{
+	BUG_ON(mlc->ddi >= 6);
 	mlc->ddi++;
+
 	return 0;
 }
 
-static int hilse_take_idd(hil_mlc *mlc, int unused) {
+static int hilse_take_idd(hil_mlc *mlc, int unused)
+{
 	int i;
 
-	/* Help the state engine: 
-	 * Is this a real IDD response or just an echo? 
+	/* Help the state engine:
+	 * Is this a real IDD response or just an echo?
 	 *
-	 * Real IDD response does not start with a command. 
+	 * Real IDD response does not start with a command.
 	 */
-	if (mlc->ipacket[0] & HIL_PKT_CMD) goto bail;
+	if (mlc->ipacket[0] & HIL_PKT_CMD)
+		goto bail;
+
 	/* Should have the command echoed further down. */
 	for (i = 1; i < 16; i++) {
-		if (((mlc->ipacket[i] & HIL_PKT_ADDR_MASK) == 
+		if (((mlc->ipacket[i] & HIL_PKT_ADDR_MASK) ==
 		     (mlc->ipacket[0] & HIL_PKT_ADDR_MASK)) &&
-		    (mlc->ipacket[i] & HIL_PKT_CMD) && 
+		    (mlc->ipacket[i] & HIL_PKT_CMD) &&
 		    ((mlc->ipacket[i] & HIL_PKT_DATA_MASK) == HIL_CMD_IDD))
 			break;
 	}
-	if (i > 15) goto bail;
+	if (i > 15)
+		goto bail;
+
 	/* And the rest of the packets should still be clear. */
-	while (++i < 16) {
-		if (mlc->ipacket[i]) break;
-	}
-	if (i < 16) goto bail;
-	for (i = 0; i < 16; i++) {
-		mlc->di_scratch.idd[i] = 
+	while (++i < 16)
+		if (mlc->ipacket[i])
+			break;
+
+	if (i < 16)
+		goto bail;
+
+	for (i = 0; i < 16; i++)
+		mlc->di_scratch.idd[i] =
 			mlc->ipacket[i] & HIL_PKT_DATA_MASK;
-	}
+
 	/* Next step is to see if RSC supported */
-	if (mlc->di_scratch.idd[1] & HIL_IDD_HEADER_RSC) 
+	if (mlc->di_scratch.idd[1] & HIL_IDD_HEADER_RSC)
 		return HILSEN_NEXT;
-	if (mlc->di_scratch.idd[1] & HIL_IDD_HEADER_EXD) 
+
+	if (mlc->di_scratch.idd[1] & HIL_IDD_HEADER_EXD)
 		return HILSEN_DOWN | 4;
+
 	return 0;
+
  bail:
 	mlc->ddi--;
+
 	return -1; /* This should send us off to ACF */
 }
 
-static int hilse_take_rsc(hil_mlc *mlc, int unused) {
+static int hilse_take_rsc(hil_mlc *mlc, int unused)
+{
 	int i;
 
-	for (i = 0; i < 16; i++) {
-		mlc->di_scratch.rsc[i] = 
+	for (i = 0; i < 16; i++)
+		mlc->di_scratch.rsc[i] =
 			mlc->ipacket[i] & HIL_PKT_DATA_MASK;
-	}
+
 	/* Next step is to see if EXD supported (IDD has already been read) */
-	if (mlc->di_scratch.idd[1] & HIL_IDD_HEADER_EXD) 
+	if (mlc->di_scratch.idd[1] & HIL_IDD_HEADER_EXD)
 		return HILSEN_NEXT;
+
 	return 0;
 }
 
-static int hilse_take_exd(hil_mlc *mlc, int unused) {
+static int hilse_take_exd(hil_mlc *mlc, int unused)
+{
 	int i;
 
-	for (i = 0; i < 16; i++) {
-		mlc->di_scratch.exd[i] = 
+	for (i = 0; i < 16; i++)
+		mlc->di_scratch.exd[i] =
 			mlc->ipacket[i] & HIL_PKT_DATA_MASK;
-	}
+
 	/* Next step is to see if RNM supported. */
-	if (mlc->di_scratch.exd[0] & HIL_EXD_HEADER_RNM) 
+	if (mlc->di_scratch.exd[0] & HIL_EXD_HEADER_RNM)
 		return HILSEN_NEXT;
+
 	return 0;
 }
 
-static int hilse_take_rnm(hil_mlc *mlc, int unused) {
+static int hilse_take_rnm(hil_mlc *mlc, int unused)
+{
 	int i;
 
-	for (i = 0; i < 16; i++) {
-		mlc->di_scratch.rnm[i] = 
+	for (i = 0; i < 16; i++)
+		mlc->di_scratch.rnm[i] =
 			mlc->ipacket[i] & HIL_PKT_DATA_MASK;
-	}
-	do {
-	  char nam[17];
-	  snprintf(nam, 16, "%s", mlc->di_scratch.rnm);
-	  nam[16] = '\0';
-	  printk(KERN_INFO PREFIX "Device name gotten: %s\n", nam);
-	} while (0);
+
+	printk(KERN_INFO PREFIX "Device name gotten: %16s\n",
+			mlc->di_scratch.rnm);
+
 	return 0;
 }
 
-static int hilse_operate(hil_mlc *mlc, int repoll) { 
+static int hilse_operate(hil_mlc *mlc, int repoll)
+{
 
-	if (mlc->opercnt == 0) hil_mlcs_probe = 0;
+	if (mlc->opercnt == 0)
+		hil_mlcs_probe = 0;
 	mlc->opercnt = 1;
 
 	hil_mlc_send_polls(mlc);
 
-	if (!hil_mlcs_probe) return 0;
+	if (!hil_mlcs_probe)
+		return 0;
 	hil_mlcs_probe = 0;
 	mlc->opercnt = 0;
 	return 1;
@@ -408,7 +459,7 @@
 #define OUT_LAST(pack) \
 { HILSE_OUT_LAST,	{ .packet = pack }, 0, 0, 0, 0 },
 
-struct hilse_node hil_mlc_se[HILSEN_END] = {
+const struct hilse_node hil_mlc_se[HILSEN_END] = {
 
 	/* 0  HILSEN_START */
 	FUNC(hilse_init_lcv, 0,	HILSEN_NEXT,	HILSEN_SLEEP,	0)
@@ -428,7 +479,7 @@
 	EXPECT(HIL_ERR_INT | TEST_PACKET(0xa),
 	       2000,		HILSEN_NEXT,	HILSEN_RESTART,	HILSEN_RESTART)
 	OUT(HIL_CTRL_ONLY | 0)			/* Disable test mode */
-	
+
 	/* 9  HILSEN_DHR */
 	FUNC(hilse_init_lcv, 0,	HILSEN_NEXT,	HILSEN_SLEEP,	0)
 
@@ -439,7 +490,7 @@
 	IN(300000,		HILSEN_DHR2,	HILSEN_DHR2,	HILSEN_NEXT)
 
 	/* 14 HILSEN_IFC */
-  	OUT(HIL_PKT_CMD | HIL_CMD_IFC)
+	OUT(HIL_PKT_CMD | HIL_CMD_IFC)
 	EXPECT(HIL_PKT_CMD | HIL_CMD_IFC | HIL_ERR_INT,
 	       20000,		HILSEN_DISC,	HILSEN_DHR2,	HILSEN_NEXT )
 
@@ -455,7 +506,7 @@
 
 	/* 18 HILSEN_HEAL */
 	OUT_LAST(HIL_CMD_ELB)
-	EXPECT_LAST(HIL_CMD_ELB | HIL_ERR_INT, 
+	EXPECT_LAST(HIL_CMD_ELB | HIL_ERR_INT,
 		    20000,	HILSEN_REPOLL,	HILSEN_DSR,	HILSEN_NEXT)
 	FUNC(hilse_dec_ddi, 0,	HILSEN_HEAL,	HILSEN_NEXT,	0)
 
@@ -503,7 +554,7 @@
 
 	/* 44 HILSEN_PROBE */
 	OUT_LAST(HIL_PKT_CMD | HIL_CMD_EPT)
-	IN(10000, 		HILSEN_DISC,	HILSEN_DSR,	HILSEN_NEXT)
+	IN(10000,		HILSEN_DISC,	HILSEN_DSR,	HILSEN_NEXT)
 	OUT_DISC(HIL_PKT_CMD | HIL_CMD_ELB)
 	IN(10000,		HILSEN_DISC,	HILSEN_DSR,	HILSEN_NEXT)
 	OUT(HIL_PKT_CMD | HIL_CMD_ACF | 1)
@@ -514,7 +565,7 @@
 	/* 52 HILSEN_DSR */
 	FUNC(hilse_set_ddi, -1,	HILSEN_NEXT,	0,		0)
 	OUT(HIL_PKT_CMD | HIL_CMD_DSR)
-	IN(20000, 		HILSEN_DHR,	HILSEN_DHR,	HILSEN_IFC)
+	IN(20000,		HILSEN_DHR,	HILSEN_DHR,	HILSEN_IFC)
 
 	/* 55 HILSEN_REPOLL */
 	OUT(HIL_PKT_CMD | HIL_CMD_RPL)
@@ -523,14 +574,15 @@
 	FUNC(hilse_operate, 1,	HILSEN_OPERATE,	HILSEN_IFC,	HILSEN_PROBE)
 
 	/* 58 HILSEN_IFCACF */
-  	OUT(HIL_PKT_CMD | HIL_CMD_IFC)
+	OUT(HIL_PKT_CMD | HIL_CMD_IFC)
 	EXPECT(HIL_PKT_CMD | HIL_CMD_IFC | HIL_ERR_INT,
 	       20000,		HILSEN_ACF2,	HILSEN_DHR2,	HILSEN_HEAL)
 
 	/* 60 HILSEN_END */
 };
 
-static inline void hilse_setup_input(hil_mlc *mlc, struct hilse_node *node) {
+static inline void hilse_setup_input(hil_mlc *mlc, const struct hilse_node *node)
+{
 
 	switch (node->act) {
 	case HILSE_EXPECT_DISC:
@@ -555,29 +607,27 @@
 	do_gettimeofday(&(mlc->instart));
 	mlc->icount = 15;
 	memset(mlc->ipacket, 0, 16 * sizeof(hil_packet));
-	BUG_ON(down_trylock(&(mlc->isem)));
-
-	return;
+	BUG_ON(down_trylock(&mlc->isem));
 }
 
 #ifdef HIL_MLC_DEBUG
-static int doze = 0;
+static int doze;
 static int seidx; /* For debug */
-static int kick = 1;
 #endif
 
-static int hilse_donode (hil_mlc *mlc) {
-	struct hilse_node *node;
+static int hilse_donode(hil_mlc *mlc)
+{
+	const struct hilse_node *node;
 	int nextidx = 0;
 	int sched_long = 0;
 	unsigned long flags;
 
 #ifdef HIL_MLC_DEBUG
-	if (mlc->seidx && (mlc->seidx != seidx)  && mlc->seidx != 41 && mlc->seidx != 42 && mlc->seidx != 43) {
-	  printk(KERN_DEBUG PREFIX "z%i \n%s {%i}", doze, kick ? "K" : "", mlc->seidx);
+	if (mlc->seidx && mlc->seidx != seidx &&
+	    mlc->seidx != 41 && mlc->seidx != 42 && mlc->seidx != 43) {
+		printk(KERN_DEBUG PREFIX "z%i \n {%i}", doze, mlc->seidx);
 		doze = 0;
 	}
-	kick = 0;
 
 	seidx = mlc->seidx;
 #endif
@@ -588,52 +638,61 @@
 		hil_packet pack;
 
 	case HILSE_FUNC:
-		if (node->object.func == NULL) break;
+		BUG_ON(node->object.func == NULL);
 		rc = node->object.func(mlc, node->arg);
-		nextidx = (rc > 0) ? node->ugly : 
+		nextidx = (rc > 0) ? node->ugly :
 			((rc < 0) ? node->bad : node->good);
-		if (nextidx == HILSEN_FOLLOW) nextidx = rc;
+		if (nextidx == HILSEN_FOLLOW)
+			nextidx = rc;
 		break;
+
 	case HILSE_EXPECT_LAST:
 	case HILSE_EXPECT_DISC:
 	case HILSE_EXPECT:
 	case HILSE_IN:
 		/* Already set up from previous HILSE_OUT_* */
-		write_lock_irqsave(&(mlc->lock), flags);
+		write_lock_irqsave(&mlc->lock, flags);
 		rc = mlc->in(mlc, node->arg);
 		if (rc == 2)  {
 			nextidx = HILSEN_DOZE;
 			sched_long = 1;
-			write_unlock_irqrestore(&(mlc->lock), flags);
+			write_unlock_irqrestore(&mlc->lock, flags);
 			break;
 		}
-		if (rc == 1)		nextidx = node->ugly;
-		else if (rc == 0)	nextidx = node->good;
-		else			nextidx = node->bad;
+		if (rc == 1)
+			nextidx = node->ugly;
+		else if (rc == 0)
+			nextidx = node->good;
+		else
+			nextidx = node->bad;
 		mlc->istarted = 0;
-		write_unlock_irqrestore(&(mlc->lock), flags);
+		write_unlock_irqrestore(&mlc->lock, flags);
 		break;
+
 	case HILSE_OUT_LAST:
-		write_lock_irqsave(&(mlc->lock), flags);
+		write_lock_irqsave(&mlc->lock, flags);
 		pack = node->object.packet;
 		pack |= ((mlc->ddi + 1) << HIL_PKT_ADDR_SHIFT);
 		goto out;
+
 	case HILSE_OUT_DISC:
-		write_lock_irqsave(&(mlc->lock), flags);
+		write_lock_irqsave(&mlc->lock, flags);
 		pack = node->object.packet;
 		pack |= ((mlc->ddi + 2) << HIL_PKT_ADDR_SHIFT);
 		goto out;
+
 	case HILSE_OUT:
-		write_lock_irqsave(&(mlc->lock), flags);
+		write_lock_irqsave(&mlc->lock, flags);
 		pack = node->object.packet;
 	out:
-		if (mlc->istarted) goto out2;
+		if (mlc->istarted)
+			goto out2;
 		/* Prepare to receive input */
 		if ((node + 1)->act & HILSE_IN)
 			hilse_setup_input(mlc, node + 1);
 
 	out2:
-		write_unlock_irqrestore(&(mlc->lock), flags);
+		write_unlock_irqrestore(&mlc->lock, flags);
 
 		if (down_trylock(&mlc->osem)) {
 			nextidx = HILSEN_DOZE;
@@ -641,60 +700,71 @@
 		}
 		up(&mlc->osem);
 
-		write_lock_irqsave(&(mlc->lock), flags);
-		if (!(mlc->ostarted)) {
+		write_lock_irqsave(&mlc->lock, flags);
+		if (!mlc->ostarted) {
 			mlc->ostarted = 1;
 			mlc->opacket = pack;
 			mlc->out(mlc);
 			nextidx = HILSEN_DOZE;
-			write_unlock_irqrestore(&(mlc->lock), flags);
+			write_unlock_irqrestore(&mlc->lock, flags);
 			break;
 		}
 		mlc->ostarted = 0;
 		do_gettimeofday(&(mlc->instart));
-		write_unlock_irqrestore(&(mlc->lock), flags);
+		write_unlock_irqrestore(&mlc->lock, flags);
 		nextidx = HILSEN_NEXT;
 		break;
+
 	case HILSE_CTS:
+		write_lock_irqsave(&mlc->lock, flags);
 		nextidx = mlc->cts(mlc) ? node->bad : node->good;
+		write_unlock_irqrestore(&mlc->lock, flags);
 		break;
+
 	default:
 		BUG();
-		nextidx = 0;
-		break;
 	}
 
 #ifdef HIL_MLC_DEBUG
-	if (nextidx == HILSEN_DOZE) doze++;
+	if (nextidx == HILSEN_DOZE)
+		doze++;
 #endif
 
 	while (nextidx & HILSEN_SCHED) {
 		struct timeval tv;
 
-		if (!sched_long) goto sched;
+		if (!sched_long)
+			goto sched;
 
 		do_gettimeofday(&tv);
-		tv.tv_usec += 1000000 * (tv.tv_sec - mlc->instart.tv_sec);
+		tv.tv_usec += USEC_PER_SEC * (tv.tv_sec - mlc->instart.tv_sec);
 		tv.tv_usec -= mlc->instart.tv_usec;
 		if (tv.tv_usec >= mlc->intimeout) goto sched;
-		tv.tv_usec = (mlc->intimeout - tv.tv_usec) * HZ / 1000000;
+		tv.tv_usec = (mlc->intimeout - tv.tv_usec) * HZ / USEC_PER_SEC;
 		if (!tv.tv_usec) goto sched;
 		mod_timer(&hil_mlcs_kicker, jiffies + tv.tv_usec);
 		break;
 	sched:
 		tasklet_schedule(&hil_mlcs_tasklet);
 		break;
-	} 
-	if (nextidx & HILSEN_DOWN) mlc->seidx += nextidx & HILSEN_MASK;
-	else if (nextidx & HILSEN_UP) mlc->seidx -= nextidx & HILSEN_MASK;
-	else mlc->seidx = nextidx & HILSEN_MASK;
+	}
 
-	if (nextidx & HILSEN_BREAK)	return 1;
+	if (nextidx & HILSEN_DOWN)
+		mlc->seidx += nextidx & HILSEN_MASK;
+	else if (nextidx & HILSEN_UP)
+		mlc->seidx -= nextidx & HILSEN_MASK;
+	else
+		mlc->seidx = nextidx & HILSEN_MASK;
+
+	if (nextidx & HILSEN_BREAK)
+		return 1;
+
 	return 0;
 }
 
 /******************** tasklet context functions **************************/
-static void hil_mlcs_process(unsigned long unused) {
+static void hil_mlcs_process(unsigned long unused)
+{
 	struct list_head *tmp;
 
 	read_lock(&hil_mlcs_lock);
@@ -702,19 +772,20 @@
 		struct hil_mlc *mlc = list_entry(tmp, hil_mlc, list);
 		while (hilse_donode(mlc) == 0) {
 #ifdef HIL_MLC_DEBUG
-		  if (mlc->seidx != 41 && 
-		      mlc->seidx != 42 && 
-		      mlc->seidx != 43) 
-		    printk(KERN_DEBUG PREFIX " + ");
+			if (mlc->seidx != 41 &&
+			    mlc->seidx != 42 &&
+			    mlc->seidx != 43)
+				printk(KERN_DEBUG PREFIX " + ");
 #endif
-		};
+		}
 	}
 	read_unlock(&hil_mlcs_lock);
 }
 
 /************************* Keepalive timer task *********************/
 
-void hil_mlcs_timer (unsigned long data) {
+void hil_mlcs_timer(unsigned long data)
+{
 	hil_mlcs_probe = 1;
 	tasklet_schedule(&hil_mlcs_tasklet);
 	/* Re-insert the periodic task. */
@@ -724,28 +795,25 @@
 
 /******************** user/kernel context functions **********************/
 
-static int hil_mlc_serio_write(struct serio *serio, unsigned char c) {
+static int hil_mlc_serio_write(struct serio *serio, unsigned char c)
+{
 	struct hil_mlc_serio_map *map;
 	struct hil_mlc *mlc;
 	struct serio_driver *drv;
 	uint8_t *idx, *last;
 
 	map = serio->port_data;
-	if (map == NULL) {
-		BUG();
-		return -EIO;
-	}
+	BUG_ON(map == NULL);
+
 	mlc = map->mlc;
-	if (mlc == NULL) {
-		BUG();
-		return -EIO;
-	}
-	mlc->serio_opacket[map->didx] |= 
+	BUG_ON(mlc == NULL);
+
+	mlc->serio_opacket[map->didx] |=
 		((hil_packet)c) << (8 * (3 - mlc->serio_oidx[map->didx]));
 
 	if (mlc->serio_oidx[map->didx] >= 3) {
 		/* for now only commands */
-		if (!(mlc->serio_opacket[map->didx] & HIL_PKT_CMD)) 
+		if (!(mlc->serio_opacket[map->didx] & HIL_PKT_CMD))
 			return -EIO;
 		switch (mlc->serio_opacket[map->didx] & HIL_PKT_DATA_MASK) {
 		case HIL_CMD_IDD:
@@ -771,12 +839,11 @@
 	return -EIO;
  emu:
 	drv = serio->drv;
-	if (drv == NULL) {
-		BUG();
-		return -EIO;
-	}
+	BUG_ON(drv == NULL);
+
 	last = idx + 15;
-	while ((last != idx) && (*last == 0)) last--;
+	while ((last != idx) && (*last == 0))
+		last--;
 
 	while (idx != last) {
 		drv->interrupt(serio, 0, 0);
@@ -789,14 +856,15 @@
 	drv->interrupt(serio, HIL_ERR_INT >> 16, 0);
 	drv->interrupt(serio, HIL_PKT_CMD >> 8, 0);
 	drv->interrupt(serio, *idx, 0);
-	
+
 	mlc->serio_oidx[map->didx] = 0;
 	mlc->serio_opacket[map->didx] = 0;
 
 	return 0;
 }
 
-static int hil_mlc_serio_open(struct serio *serio) {
+static int hil_mlc_serio_open(struct serio *serio)
+{
 	struct hil_mlc_serio_map *map;
 	struct hil_mlc *mlc;
 
@@ -804,67 +872,57 @@
 		return -EBUSY;
 
 	map = serio->port_data;
-	if (map == NULL) {
-		BUG();
-		return -ENODEV;
-	}
+	BUG_ON(map == NULL);
+
 	mlc = map->mlc;
-	if (mlc == NULL) {
-		BUG();
-		return -ENODEV;
-	}
+	BUG_ON(mlc == NULL);
 
 	return 0;
 }
 
-static void hil_mlc_serio_close(struct serio *serio) {
+static void hil_mlc_serio_close(struct serio *serio)
+{
 	struct hil_mlc_serio_map *map;
 	struct hil_mlc *mlc;
 
 	map = serio->port_data;
-	if (map == NULL) {
-		BUG();
-		return;
-	}
+	BUG_ON(map == NULL);
+
 	mlc = map->mlc;
-	if (mlc == NULL) {
-		BUG();
-		return;
-	}
+	BUG_ON(mlc == NULL);
 
 	serio_set_drvdata(serio, NULL);
 	serio->drv = NULL;
 	/* TODO wake up interruptable */
 }
 
-static struct serio_device_id hil_mlc_serio_id = {
+static const struct serio_device_id hil_mlc_serio_id = {
 	.type = SERIO_HIL_MLC,
 	.proto = SERIO_HIL,
 	.extra = SERIO_ANY,
 	.id = SERIO_ANY,
 };
 
-int hil_mlc_register(hil_mlc *mlc) {
+int hil_mlc_register(hil_mlc *mlc)
+{
 	int i;
-        unsigned long flags;
+	unsigned long flags;
 
-	if (mlc == NULL) {
-		return -EINVAL;
-	}
+	BUG_ON(mlc == NULL);
 
 	mlc->istarted = 0;
-        mlc->ostarted = 0;
+	mlc->ostarted = 0;
 
-        rwlock_init(&mlc->lock);
-        init_MUTEX(&(mlc->osem));
+	rwlock_init(&mlc->lock);
+	init_MUTEX(&mlc->osem);
 
-        init_MUTEX(&(mlc->isem));
-        mlc->icount = -1;
-        mlc->imatch = 0;
+	init_MUTEX(&mlc->isem);
+	mlc->icount = -1;
+	mlc->imatch = 0;
 
 	mlc->opercnt = 0;
 
-        init_MUTEX_LOCKED(&(mlc->csem));
+	init_MUTEX_LOCKED(&(mlc->csem));
 
 	hil_mlc_clear_di_scratch(mlc);
 	hil_mlc_clear_di_map(mlc, 0);
@@ -873,6 +931,8 @@
 		hil_mlc_copy_di_scratch(mlc, i);
 		mlc_serio = kzalloc(sizeof(*mlc_serio), GFP_KERNEL);
 		mlc->serio[i] = mlc_serio;
+		snprintf(mlc_serio->name, sizeof(mlc_serio->name)-1, "HIL_SERIO%d", i);
+		snprintf(mlc_serio->phys, sizeof(mlc_serio->phys)-1, "HIL%d", i);
 		mlc_serio->id			= hil_mlc_serio_id;
 		mlc_serio->write		= hil_mlc_serio_write;
 		mlc_serio->open			= hil_mlc_serio_open;
@@ -897,19 +957,18 @@
 	return 0;
 }
 
-int hil_mlc_unregister(hil_mlc *mlc) {
+int hil_mlc_unregister(hil_mlc *mlc)
+{
 	struct list_head *tmp;
-        unsigned long flags;
+	unsigned long flags;
 	int i;
 
-	if (mlc == NULL)
-		return -EINVAL;
+	BUG_ON(mlc == NULL);
 
 	write_lock_irqsave(&hil_mlcs_lock, flags);
-	list_for_each(tmp, &hil_mlcs) {
+	list_for_each(tmp, &hil_mlcs)
 		if (list_entry(tmp, hil_mlc, list) == mlc)
 			goto found;
-	}
 
 	/* not found in list */
 	write_unlock_irqrestore(&hil_mlcs_lock, flags);
@@ -918,7 +977,7 @@
 
  found:
 	list_del(tmp);
-        write_unlock_irqrestore(&hil_mlcs_lock, flags);
+	write_unlock_irqrestore(&hil_mlcs_lock, flags);
 
 	for (i = 0; i < HIL_MLC_DEVMEM; i++) {
 		serio_unregister_port(mlc->serio[i]);
@@ -942,7 +1001,7 @@
 
 	return 0;
 }
-                
+
 static void __exit hil_mlc_exit(void)
 {
 	del_timer(&hil_mlcs_kicker);
@@ -950,6 +1009,6 @@
 	tasklet_disable(&hil_mlcs_tasklet);
 	tasklet_kill(&hil_mlcs_tasklet);
 }
-                        
+
 module_init(hil_mlc_init);
 module_exit(hil_mlc_exit);
diff --git a/drivers/input/serio/hp_sdc.c b/drivers/input/serio/hp_sdc.c
index b57370d..6af19980 100644
--- a/drivers/input/serio/hp_sdc.c
+++ b/drivers/input/serio/hp_sdc.c
@@ -34,27 +34,27 @@
  *
  * Driver theory of operation:
  *
- * hp_sdc_put does all writing to the SDC.  ISR can run on a different 
- * CPU than hp_sdc_put, but only one CPU runs hp_sdc_put at a time 
+ * hp_sdc_put does all writing to the SDC.  ISR can run on a different
+ * CPU than hp_sdc_put, but only one CPU runs hp_sdc_put at a time
  * (it cannot really benefit from SMP anyway.)  A tasket fit this perfectly.
  *
- * All data coming back from the SDC is sent via interrupt and can be read 
- * fully in the ISR, so there are no latency/throughput problems there.  
- * The problem is with output, due to the slow clock speed of the SDC 
- * compared to the CPU.  This should not be too horrible most of the time, 
- * but if used with HIL devices that support the multibyte transfer command, 
- * keeping outbound throughput flowing at the 6500KBps that the HIL is 
+ * All data coming back from the SDC is sent via interrupt and can be read
+ * fully in the ISR, so there are no latency/throughput problems there.
+ * The problem is with output, due to the slow clock speed of the SDC
+ * compared to the CPU.  This should not be too horrible most of the time,
+ * but if used with HIL devices that support the multibyte transfer command,
+ * keeping outbound throughput flowing at the 6500KBps that the HIL is
  * capable of is more than can be done at HZ=100.
  *
- * Busy polling for IBF clear wastes CPU cycles and bus cycles.  hp_sdc.ibf 
- * is set to 0 when the IBF flag in the status register has cleared.  ISR 
- * may do this, and may also access the parts of queued transactions related 
- * to reading data back from the SDC, but otherwise will not touch the 
+ * Busy polling for IBF clear wastes CPU cycles and bus cycles.  hp_sdc.ibf
+ * is set to 0 when the IBF flag in the status register has cleared.  ISR
+ * may do this, and may also access the parts of queued transactions related
+ * to reading data back from the SDC, but otherwise will not touch the
  * hp_sdc state. Whenever a register is written hp_sdc.ibf is set to 1.
  *
  * The i8042 write index and the values in the 4-byte input buffer
  * starting at 0x70 are kept track of in hp_sdc.wi, and .r7[], respectively,
- * to minimize the amount of IO needed to the SDC.  However these values 
+ * to minimize the amount of IO needed to the SDC.  However these values
  * do not need to be locked since they are only ever accessed by hp_sdc_put.
  *
  * A timer task schedules the tasklet once per second just to make
@@ -100,39 +100,46 @@
 EXPORT_SYMBOL(hp_sdc_release_hil_irq);
 EXPORT_SYMBOL(hp_sdc_release_cooked_irq);
 
+EXPORT_SYMBOL(__hp_sdc_enqueue_transaction);
 EXPORT_SYMBOL(hp_sdc_enqueue_transaction);
 EXPORT_SYMBOL(hp_sdc_dequeue_transaction);
 
 static hp_i8042_sdc	hp_sdc;	/* All driver state is kept in here. */
 
 /*************** primitives for use in any context *********************/
-static inline uint8_t hp_sdc_status_in8 (void) {
+static inline uint8_t hp_sdc_status_in8(void)
+{
 	uint8_t status;
 	unsigned long flags;
 
 	write_lock_irqsave(&hp_sdc.ibf_lock, flags);
 	status = sdc_readb(hp_sdc.status_io);
-	if (!(status & HP_SDC_STATUS_IBF)) hp_sdc.ibf = 0;
+	if (!(status & HP_SDC_STATUS_IBF))
+		hp_sdc.ibf = 0;
 	write_unlock_irqrestore(&hp_sdc.ibf_lock, flags);
 
 	return status;
 }
 
-static inline uint8_t hp_sdc_data_in8 (void) {
-	return sdc_readb(hp_sdc.data_io); 
+static inline uint8_t hp_sdc_data_in8(void)
+{
+	return sdc_readb(hp_sdc.data_io);
 }
 
-static inline void hp_sdc_status_out8 (uint8_t val) {
+static inline void hp_sdc_status_out8(uint8_t val)
+{
 	unsigned long flags;
 
 	write_lock_irqsave(&hp_sdc.ibf_lock, flags);
 	hp_sdc.ibf = 1;
-	if ((val & 0xf0) == 0xe0) hp_sdc.wi = 0xff;
+	if ((val & 0xf0) == 0xe0)
+		hp_sdc.wi = 0xff;
 	sdc_writeb(val, hp_sdc.status_io);
 	write_unlock_irqrestore(&hp_sdc.ibf_lock, flags);
 }
 
-static inline void hp_sdc_data_out8 (uint8_t val) {
+static inline void hp_sdc_data_out8(uint8_t val)
+{
 	unsigned long flags;
 
 	write_lock_irqsave(&hp_sdc.ibf_lock, flags);
@@ -141,11 +148,12 @@
 	write_unlock_irqrestore(&hp_sdc.ibf_lock, flags);
 }
 
-/*	Care must be taken to only invoke hp_sdc_spin_ibf when 
- *	absolutely needed, or in rarely invoked subroutines.  
- *	Not only does it waste CPU cycles, it also wastes bus cycles. 
+/*	Care must be taken to only invoke hp_sdc_spin_ibf when
+ *	absolutely needed, or in rarely invoked subroutines.
+ *	Not only does it waste CPU cycles, it also wastes bus cycles.
  */
-static inline void hp_sdc_spin_ibf(void) {
+static inline void hp_sdc_spin_ibf(void)
+{
 	unsigned long flags;
 	rwlock_t *lock;
 
@@ -158,19 +166,21 @@
 	}
 	read_unlock(lock);
 	write_lock(lock);
-	while (sdc_readb(hp_sdc.status_io) & HP_SDC_STATUS_IBF) {};
+	while (sdc_readb(hp_sdc.status_io) & HP_SDC_STATUS_IBF)
+		{ }
 	hp_sdc.ibf = 0;
 	write_unlock_irqrestore(lock, flags);
 }
 
 
 /************************ Interrupt context functions ************************/
-static void hp_sdc_take (int irq, void *dev_id, uint8_t status, uint8_t data) {
+static void hp_sdc_take(int irq, void *dev_id, uint8_t status, uint8_t data)
+{
 	hp_sdc_transaction *curr;
 
 	read_lock(&hp_sdc.rtq_lock);
 	if (hp_sdc.rcurr < 0) {
-	  	read_unlock(&hp_sdc.rtq_lock);
+		read_unlock(&hp_sdc.rtq_lock);
 		return;
 	}
 	curr = hp_sdc.tq[hp_sdc.rcurr];
@@ -183,25 +193,27 @@
 
 	if (hp_sdc.rqty <= 0) {
 		/* All data has been gathered. */
-		if(curr->seq[curr->actidx] & HP_SDC_ACT_SEMAPHORE) {
-			if (curr->act.semaphore) up(curr->act.semaphore);
-		}
-		if(curr->seq[curr->actidx] & HP_SDC_ACT_CALLBACK) {
+		if (curr->seq[curr->actidx] & HP_SDC_ACT_SEMAPHORE)
+			if (curr->act.semaphore)
+				up(curr->act.semaphore);
+
+		if (curr->seq[curr->actidx] & HP_SDC_ACT_CALLBACK)
 			if (curr->act.irqhook)
 				curr->act.irqhook(irq, dev_id, status, data);
-		}
+
 		curr->actidx = curr->idx;
 		curr->idx++;
 		/* Return control of this transaction */
 		write_lock(&hp_sdc.rtq_lock);
-		hp_sdc.rcurr = -1; 
+		hp_sdc.rcurr = -1;
 		hp_sdc.rqty = 0;
 		write_unlock(&hp_sdc.rtq_lock);
 		tasklet_schedule(&hp_sdc.task);
 	}
 }
 
-static irqreturn_t hp_sdc_isr(int irq, void *dev_id) {
+static irqreturn_t hp_sdc_isr(int irq, void *dev_id)
+{
 	uint8_t status, data;
 
 	status = hp_sdc_status_in8();
@@ -209,67 +221,74 @@
 	data =   hp_sdc_data_in8();
 
 	/* For now we are ignoring these until we get the SDC to behave. */
-	if (((status & 0xf1) == 0x51) && data == 0x82) {
-	  return IRQ_HANDLED;
-	}
+	if (((status & 0xf1) == 0x51) && data == 0x82)
+		return IRQ_HANDLED;
 
-	switch(status & HP_SDC_STATUS_IRQMASK) {
-	      case 0: /* This case is not documented. */
+	switch (status & HP_SDC_STATUS_IRQMASK) {
+	case 0: /* This case is not documented. */
 		break;
-	      case HP_SDC_STATUS_USERTIMER:
-	      case HP_SDC_STATUS_PERIODIC:
-	      case HP_SDC_STATUS_TIMER:
+
+	case HP_SDC_STATUS_USERTIMER:
+	case HP_SDC_STATUS_PERIODIC:
+	case HP_SDC_STATUS_TIMER:
 		read_lock(&hp_sdc.hook_lock);
-	      	if (hp_sdc.timer != NULL)
+		if (hp_sdc.timer != NULL)
 			hp_sdc.timer(irq, dev_id, status, data);
 		read_unlock(&hp_sdc.hook_lock);
 		break;
-	      case HP_SDC_STATUS_REG:
+
+	case HP_SDC_STATUS_REG:
 		hp_sdc_take(irq, dev_id, status, data);
 		break;
-	      case HP_SDC_STATUS_HILCMD:
-	      case HP_SDC_STATUS_HILDATA:
+
+	case HP_SDC_STATUS_HILCMD:
+	case HP_SDC_STATUS_HILDATA:
 		read_lock(&hp_sdc.hook_lock);
 		if (hp_sdc.hil != NULL)
 			hp_sdc.hil(irq, dev_id, status, data);
 		read_unlock(&hp_sdc.hook_lock);
 		break;
-	      case HP_SDC_STATUS_PUP:
+
+	case HP_SDC_STATUS_PUP:
 		read_lock(&hp_sdc.hook_lock);
 		if (hp_sdc.pup != NULL)
 			hp_sdc.pup(irq, dev_id, status, data);
-		else printk(KERN_INFO PREFIX "HP SDC reports successful PUP.\n");
+		else
+			printk(KERN_INFO PREFIX "HP SDC reports successful PUP.\n");
 		read_unlock(&hp_sdc.hook_lock);
 		break;
-	      default:
+
+	default:
 		read_lock(&hp_sdc.hook_lock);
 		if (hp_sdc.cooked != NULL)
 			hp_sdc.cooked(irq, dev_id, status, data);
 		read_unlock(&hp_sdc.hook_lock);
 		break;
 	}
+
 	return IRQ_HANDLED;
 }
 
 
-static irqreturn_t hp_sdc_nmisr(int irq, void *dev_id) {
+static irqreturn_t hp_sdc_nmisr(int irq, void *dev_id)
+{
 	int status;
-	
+
 	status = hp_sdc_status_in8();
 	printk(KERN_WARNING PREFIX "NMI !\n");
 
-#if 0	
+#if 0
 	if (status & HP_SDC_NMISTATUS_FHS) {
 		read_lock(&hp_sdc.hook_lock);
-	      	if (hp_sdc.timer != NULL)
+		if (hp_sdc.timer != NULL)
 			hp_sdc.timer(irq, dev_id, status, 0);
 		read_unlock(&hp_sdc.hook_lock);
-	}
-	else {
+	} else {
 		/* TODO: pass this on to the HIL handler, or do SAK here? */
 		printk(KERN_WARNING PREFIX "HIL NMI\n");
 	}
 #endif
+
 	return IRQ_HANDLED;
 }
 
@@ -278,13 +297,17 @@
 
 unsigned long hp_sdc_put(void);
 
-static void hp_sdc_tasklet(unsigned long foo) {
-
+static void hp_sdc_tasklet(unsigned long foo)
+{
 	write_lock_irq(&hp_sdc.rtq_lock);
+
 	if (hp_sdc.rcurr >= 0) {
 		struct timeval tv;
+
 		do_gettimeofday(&tv);
-		if (tv.tv_sec > hp_sdc.rtv.tv_sec) tv.tv_usec += 1000000;
+		if (tv.tv_sec > hp_sdc.rtv.tv_sec)
+			tv.tv_usec += USEC_PER_SEC;
+
 		if (tv.tv_usec - hp_sdc.rtv.tv_usec > HP_SDC_MAX_REG_DELAY) {
 			hp_sdc_transaction *curr;
 			uint8_t tmp;
@@ -300,27 +323,29 @@
 			hp_sdc.rqty = 0;
 			tmp = curr->seq[curr->actidx];
 			curr->seq[curr->actidx] |= HP_SDC_ACT_DEAD;
-			if(tmp & HP_SDC_ACT_SEMAPHORE) {
-				if (curr->act.semaphore) 
+			if (tmp & HP_SDC_ACT_SEMAPHORE)
+				if (curr->act.semaphore)
 					up(curr->act.semaphore);
-			}
-			if(tmp & HP_SDC_ACT_CALLBACK) {
+
+			if (tmp & HP_SDC_ACT_CALLBACK) {
 				/* Note this means that irqhooks may be called
 				 * in tasklet/bh context.
 				 */
-				if (curr->act.irqhook) 
+				if (curr->act.irqhook)
 					curr->act.irqhook(0, NULL, 0, 0);
 			}
+
 			curr->actidx = curr->idx;
 			curr->idx++;
-			hp_sdc.rcurr = -1; 
+			hp_sdc.rcurr = -1;
 		}
 	}
 	write_unlock_irq(&hp_sdc.rtq_lock);
 	hp_sdc_put();
 }
 
-unsigned long hp_sdc_put(void) {
+unsigned long hp_sdc_put(void)
+{
 	hp_sdc_transaction *curr;
 	uint8_t act;
 	int idx, curridx;
@@ -333,19 +358,24 @@
 	   requires output, so we skip to the administrativa. */
 	if (hp_sdc.ibf) {
 		hp_sdc_status_in8();
-		if (hp_sdc.ibf) goto finish;
+		if (hp_sdc.ibf)
+			goto finish;
 	}
 
  anew:
 	/* See if we are in the middle of a sequence. */
-	if (hp_sdc.wcurr < 0) hp_sdc.wcurr = 0;
+	if (hp_sdc.wcurr < 0)
+		hp_sdc.wcurr = 0;
 	read_lock_irq(&hp_sdc.rtq_lock);
-	if (hp_sdc.rcurr == hp_sdc.wcurr) hp_sdc.wcurr++;
+	if (hp_sdc.rcurr == hp_sdc.wcurr)
+		hp_sdc.wcurr++;
 	read_unlock_irq(&hp_sdc.rtq_lock);
-	if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN) hp_sdc.wcurr = 0;
+	if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN)
+		hp_sdc.wcurr = 0;
 	curridx = hp_sdc.wcurr;
 
-	if (hp_sdc.tq[curridx] != NULL) goto start;
+	if (hp_sdc.tq[curridx] != NULL)
+		goto start;
 
 	while (++curridx != hp_sdc.wcurr) {
 		if (curridx >= HP_SDC_QUEUE_LEN) {
@@ -358,7 +388,8 @@
 			continue;
 		}
 		read_unlock_irq(&hp_sdc.rtq_lock);
-		if (hp_sdc.tq[curridx] != NULL) break; /* Found one. */
+		if (hp_sdc.tq[curridx] != NULL)
+			break; /* Found one. */
 	}
 	if (curridx == hp_sdc.wcurr) { /* There's nothing queued to do. */
 		curridx = -1;
@@ -374,7 +405,8 @@
 		goto finish;
 	}
 
-	if (hp_sdc.wcurr == -1) goto done;
+	if (hp_sdc.wcurr == -1)
+		goto done;
 
 	curr = hp_sdc.tq[curridx];
 	idx = curr->actidx;
@@ -383,20 +415,23 @@
 		hp_sdc.tq[curridx] = NULL;
 		/* Interleave outbound data between the transactions. */
 		hp_sdc.wcurr++;
-		if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN) hp_sdc.wcurr = 0;
-		goto finish;	
+		if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN)
+			hp_sdc.wcurr = 0;
+		goto finish;
 	}
 
 	act = curr->seq[idx];
 	idx++;
 
 	if (curr->idx >= curr->endidx) {
-		if (act & HP_SDC_ACT_DEALLOC) kfree(curr);
+		if (act & HP_SDC_ACT_DEALLOC)
+			kfree(curr);
 		hp_sdc.tq[curridx] = NULL;
 		/* Interleave outbound data between the transactions. */
 		hp_sdc.wcurr++;
-		if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN) hp_sdc.wcurr = 0;
-		goto finish;	
+		if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN)
+			hp_sdc.wcurr = 0;
+		goto finish;
 	}
 
 	while (act & HP_SDC_ACT_PRECMD) {
@@ -409,9 +444,10 @@
 		curr->idx++;
 		/* act finished? */
 		if ((act & HP_SDC_ACT_DURING) == HP_SDC_ACT_PRECMD)
-		  goto actdone;
+			goto actdone;
 		/* skip quantity field if data-out sequence follows. */
-		if (act & HP_SDC_ACT_DATAOUT) curr->idx++;
+		if (act & HP_SDC_ACT_DATAOUT)
+			curr->idx++;
 		goto finish;
 	}
 	if (act & HP_SDC_ACT_DATAOUT) {
@@ -423,15 +459,15 @@
 			hp_sdc_data_out8(curr->seq[curr->idx]);
 			curr->idx++;
 			/* act finished? */
-			if ((curr->idx - idx >= qty) && 
-			    ((act & HP_SDC_ACT_DURING) == HP_SDC_ACT_DATAOUT))
+			if (curr->idx - idx >= qty &&
+			    (act & HP_SDC_ACT_DURING) == HP_SDC_ACT_DATAOUT)
 				goto actdone;
 			goto finish;
 		}
 		idx += qty;
 		act &= ~HP_SDC_ACT_DATAOUT;
-	}
-	else while (act & HP_SDC_ACT_DATAREG) {
+	} else
+	    while (act & HP_SDC_ACT_DATAREG) {
 		int mask;
 		uint8_t w7[4];
 
@@ -445,26 +481,30 @@
 			act &= ~HP_SDC_ACT_DATAREG;
 			break;
 		}
-		
+
 		w7[0] = (mask & 1) ? curr->seq[++idx] : hp_sdc.r7[0];
 		w7[1] = (mask & 2) ? curr->seq[++idx] : hp_sdc.r7[1];
 		w7[2] = (mask & 4) ? curr->seq[++idx] : hp_sdc.r7[2];
 		w7[3] = (mask & 8) ? curr->seq[++idx] : hp_sdc.r7[3];
-		
+
 		if (hp_sdc.wi > 0x73 || hp_sdc.wi < 0x70 ||
-		        w7[hp_sdc.wi-0x70] == hp_sdc.r7[hp_sdc.wi-0x70]) {
+		    w7[hp_sdc.wi - 0x70] == hp_sdc.r7[hp_sdc.wi - 0x70]) {
 			int i = 0;
 
-			/* Need to point the write index register */	
-			while ((i < 4) && w7[i] == hp_sdc.r7[i]) i++;
+			/* Need to point the write index register */
+			while (i < 4 && w7[i] == hp_sdc.r7[i])
+				i++;
+
 			if (i < 4) {
 				hp_sdc_status_out8(HP_SDC_CMD_SET_D0 + i);
 				hp_sdc.wi = 0x70 + i;
 				goto finish;
 			}
+
 			idx++;
 			if ((act & HP_SDC_ACT_DURING) == HP_SDC_ACT_DATAREG)
 				goto actdone;
+
 			curr->idx = idx;
 			act &= ~HP_SDC_ACT_DATAREG;
 			break;
@@ -476,12 +516,13 @@
 		{
 			int i = 0;
 
-			while ((i < 4) && w7[i] == hp_sdc.r7[i]) i++;
+			while ((i < 4) && w7[i] == hp_sdc.r7[i])
+				i++;
 			if (i >= 4) {
 				curr->idx = idx + 1;
-				if ((act & HP_SDC_ACT_DURING) == 
+				if ((act & HP_SDC_ACT_DURING) ==
 				    HP_SDC_ACT_DATAREG)
-				        goto actdone;
+					goto actdone;
 			}
 		}
 		goto finish;
@@ -497,7 +538,7 @@
 
 
 	if (act & HP_SDC_ACT_POSTCMD) {
-	  	uint8_t postcmd;
+		uint8_t postcmd;
 
 		/* curr->idx should == idx at this point. */
 		postcmd = curr->seq[idx];
@@ -505,12 +546,12 @@
 		if (act & HP_SDC_ACT_DATAIN) {
 
 			/* Start a new read */
-	  		hp_sdc.rqty = curr->seq[curr->idx];
+			hp_sdc.rqty = curr->seq[curr->idx];
 			do_gettimeofday(&hp_sdc.rtv);
 			curr->idx++;
 			/* Still need to lock here in case of spurious irq. */
 			write_lock_irq(&hp_sdc.rtq_lock);
-			hp_sdc.rcurr = curridx; 
+			hp_sdc.rcurr = curridx;
 			write_unlock_irq(&hp_sdc.rtq_lock);
 			hp_sdc_status_out8(postcmd);
 			goto finish;
@@ -519,75 +560,86 @@
 		goto actdone;
 	}
 
-actdone:
-	if (act & HP_SDC_ACT_SEMAPHORE) {
+ actdone:
+	if (act & HP_SDC_ACT_SEMAPHORE)
 		up(curr->act.semaphore);
-	}
-	else if (act & HP_SDC_ACT_CALLBACK) {
+	else if (act & HP_SDC_ACT_CALLBACK)
 		curr->act.irqhook(0,NULL,0,0);
-	}
+
 	if (curr->idx >= curr->endidx) { /* This transaction is over. */
-		if (act & HP_SDC_ACT_DEALLOC) kfree(curr);
+		if (act & HP_SDC_ACT_DEALLOC)
+			kfree(curr);
 		hp_sdc.tq[curridx] = NULL;
-	}
-	else {
+	} else {
 		curr->actidx = idx + 1;
 		curr->idx = idx + 2;
 	}
 	/* Interleave outbound data between the transactions. */
 	hp_sdc.wcurr++;
-	if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN) hp_sdc.wcurr = 0;
+	if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN)
+		hp_sdc.wcurr = 0;
 
  finish:
-	/* If by some quirk IBF has cleared and our ISR has run to 
+	/* If by some quirk IBF has cleared and our ISR has run to
 	   see that that has happened, do it all again. */
-	if (!hp_sdc.ibf && limit++ < 20) goto anew;
+	if (!hp_sdc.ibf && limit++ < 20)
+		goto anew;
 
  done:
-	if (hp_sdc.wcurr >= 0) tasklet_schedule(&hp_sdc.task);
+	if (hp_sdc.wcurr >= 0)
+		tasklet_schedule(&hp_sdc.task);
 	write_unlock(&hp_sdc.lock);
+
 	return 0;
 }
 
 /******* Functions called in either user or kernel context ****/
-int hp_sdc_enqueue_transaction(hp_sdc_transaction *this) {
-	unsigned long flags;
+int __hp_sdc_enqueue_transaction(hp_sdc_transaction *this)
+{
 	int i;
 
 	if (this == NULL) {
-		tasklet_schedule(&hp_sdc.task);
+		BUG();
 		return -EINVAL;
-	};
-
-	write_lock_irqsave(&hp_sdc.lock, flags);
+	}
 
 	/* Can't have same transaction on queue twice */
-	for (i=0; i < HP_SDC_QUEUE_LEN; i++)
-		if (hp_sdc.tq[i] == this) goto fail;
+	for (i = 0; i < HP_SDC_QUEUE_LEN; i++)
+		if (hp_sdc.tq[i] == this)
+			goto fail;
 
 	this->actidx = 0;
 	this->idx = 1;
 
 	/* Search for empty slot */
-	for (i=0; i < HP_SDC_QUEUE_LEN; i++) {
+	for (i = 0; i < HP_SDC_QUEUE_LEN; i++)
 		if (hp_sdc.tq[i] == NULL) {
 			hp_sdc.tq[i] = this;
-			write_unlock_irqrestore(&hp_sdc.lock, flags);
 			tasklet_schedule(&hp_sdc.task);
 			return 0;
 		}
-	}
-	write_unlock_irqrestore(&hp_sdc.lock, flags);
+
 	printk(KERN_WARNING PREFIX "No free slot to add transaction.\n");
 	return -EBUSY;
 
  fail:
-	write_unlock_irqrestore(&hp_sdc.lock,flags);
 	printk(KERN_WARNING PREFIX "Transaction add failed: transaction already queued?\n");
 	return -EINVAL;
 }
 
-int hp_sdc_dequeue_transaction(hp_sdc_transaction *this) {
+int hp_sdc_enqueue_transaction(hp_sdc_transaction *this) {
+	unsigned long flags;
+	int ret;
+
+	write_lock_irqsave(&hp_sdc.lock, flags);
+	ret = __hp_sdc_enqueue_transaction(this);
+	write_unlock_irqrestore(&hp_sdc.lock,flags);
+
+	return ret;
+}
+
+int hp_sdc_dequeue_transaction(hp_sdc_transaction *this)
+{
 	unsigned long flags;
 	int i;
 
@@ -595,8 +647,9 @@
 
 	/* TODO: don't remove it if it's not done. */
 
-	for (i=0; i < HP_SDC_QUEUE_LEN; i++)
-		if (hp_sdc.tq[i] == this) hp_sdc.tq[i] = NULL;
+	for (i = 0; i < HP_SDC_QUEUE_LEN; i++)
+		if (hp_sdc.tq[i] == this)
+			hp_sdc.tq[i] = NULL;
 
 	write_unlock_irqrestore(&hp_sdc.lock, flags);
 	return 0;
@@ -605,11 +658,11 @@
 
 
 /********************** User context functions **************************/
-int hp_sdc_request_timer_irq(hp_sdc_irqhook *callback) {
-
-	if (callback == NULL || hp_sdc.dev == NULL) {
+int hp_sdc_request_timer_irq(hp_sdc_irqhook *callback)
+{
+	if (callback == NULL || hp_sdc.dev == NULL)
 		return -EINVAL;
-	}
+
 	write_lock_irq(&hp_sdc.hook_lock);
 	if (hp_sdc.timer != NULL) {
 		write_unlock_irq(&hp_sdc.hook_lock);
@@ -629,11 +682,11 @@
 	return 0;
 }
 
-int hp_sdc_request_hil_irq(hp_sdc_irqhook *callback) {
-
-	if (callback == NULL || hp_sdc.dev == NULL) {
+int hp_sdc_request_hil_irq(hp_sdc_irqhook *callback)
+{
+	if (callback == NULL || hp_sdc.dev == NULL)
 		return -EINVAL;
-	}
+
 	write_lock_irq(&hp_sdc.hook_lock);
 	if (hp_sdc.hil != NULL) {
 		write_unlock_irq(&hp_sdc.hook_lock);
@@ -650,11 +703,11 @@
 	return 0;
 }
 
-int hp_sdc_request_cooked_irq(hp_sdc_irqhook *callback) {
-
-	if (callback == NULL || hp_sdc.dev == NULL) {
+int hp_sdc_request_cooked_irq(hp_sdc_irqhook *callback)
+{
+	if (callback == NULL || hp_sdc.dev == NULL)
 		return -EINVAL;
-	}
+
 	write_lock_irq(&hp_sdc.hook_lock);
 	if (hp_sdc.cooked != NULL) {
 		write_unlock_irq(&hp_sdc.hook_lock);
@@ -672,9 +725,8 @@
 	return 0;
 }
 
-int hp_sdc_release_timer_irq(hp_sdc_irqhook *callback) {
-
-
+int hp_sdc_release_timer_irq(hp_sdc_irqhook *callback)
+{
 	write_lock_irq(&hp_sdc.hook_lock);
 	if ((callback != hp_sdc.timer) ||
 	    (hp_sdc.timer == NULL)) {
@@ -694,8 +746,8 @@
 	return 0;
 }
 
-int hp_sdc_release_hil_irq(hp_sdc_irqhook *callback) {
-
+int hp_sdc_release_hil_irq(hp_sdc_irqhook *callback)
+{
 	write_lock_irq(&hp_sdc.hook_lock);
 	if ((callback != hp_sdc.hil) ||
 	    (hp_sdc.hil == NULL)) {
@@ -715,8 +767,8 @@
 	return 0;
 }
 
-int hp_sdc_release_cooked_irq(hp_sdc_irqhook *callback) {
-
+int hp_sdc_release_cooked_irq(hp_sdc_irqhook *callback)
+{
 	write_lock_irq(&hp_sdc.hook_lock);
 	if ((callback != hp_sdc.cooked) ||
 	    (hp_sdc.cooked == NULL)) {
@@ -738,7 +790,8 @@
 
 /************************* Keepalive timer task *********************/
 
-void hp_sdc_kicker (unsigned long data) {
+void hp_sdc_kicker (unsigned long data)
+{
 	tasklet_schedule(&hp_sdc.task);
 	/* Re-insert the periodic task. */
 	mod_timer(&hp_sdc.kicker, jiffies + HZ);
@@ -748,12 +801,12 @@
 
 #if defined(__hppa__)
 
-static struct parisc_device_id hp_sdc_tbl[] = {
+static const struct parisc_device_id hp_sdc_tbl[] = {
 	{
-		.hw_type =	HPHW_FIO, 
+		.hw_type =	HPHW_FIO,
 		.hversion_rev =	HVERSION_REV_ANY_ID,
 		.hversion =	HVERSION_ANY_ID,
-		.sversion =	0x73, 
+		.sversion =	0x73,
 	 },
 	{ 0, }
 };
@@ -772,16 +825,15 @@
 
 static int __init hp_sdc_init(void)
 {
-	int i;
 	char *errstr;
 	hp_sdc_transaction t_sync;
 	uint8_t ts_sync[6];
 	struct semaphore s_sync;
 
-  	rwlock_init(&hp_sdc.lock);
-  	rwlock_init(&hp_sdc.ibf_lock);
-  	rwlock_init(&hp_sdc.rtq_lock);
-  	rwlock_init(&hp_sdc.hook_lock);
+	rwlock_init(&hp_sdc.lock);
+	rwlock_init(&hp_sdc.ibf_lock);
+	rwlock_init(&hp_sdc.rtq_lock);
+	rwlock_init(&hp_sdc.hook_lock);
 
 	hp_sdc.timer		= NULL;
 	hp_sdc.hil		= NULL;
@@ -796,7 +848,8 @@
 	hp_sdc.r7[3]		= 0xff;
 	hp_sdc.ibf		= 1;
 
-	for (i = 0; i < HP_SDC_QUEUE_LEN; i++) hp_sdc.tq[i] = NULL;
+	memset(&hp_sdc.tq, 0, sizeof(hp_sdc.tq));
+
 	hp_sdc.wcurr		= -1;
         hp_sdc.rcurr		= -1;
 	hp_sdc.rqty		= 0;
@@ -804,27 +857,32 @@
 	hp_sdc.dev_err = -ENODEV;
 
 	errstr = "IO not found for";
-	if (!hp_sdc.base_io) goto err0;
+	if (!hp_sdc.base_io)
+		goto err0;
 
 	errstr = "IRQ not found for";
-	if (!hp_sdc.irq) goto err0;
+	if (!hp_sdc.irq)
+		goto err0;
 
 	hp_sdc.dev_err = -EBUSY;
 
 #if defined(__hppa__)
 	errstr = "IO not available for";
-        if (request_region(hp_sdc.data_io, 2, hp_sdc_driver.name)) goto err0;
-#endif	
+        if (request_region(hp_sdc.data_io, 2, hp_sdc_driver.name))
+		goto err0;
+#endif
 
 	errstr = "IRQ not available for";
-        if(request_irq(hp_sdc.irq, &hp_sdc_isr, 0, "HP SDC",
-		       (void *) hp_sdc.base_io)) goto err1;
+	if (request_irq(hp_sdc.irq, &hp_sdc_isr, IRQF_SHARED|IRQF_SAMPLE_RANDOM,
+			"HP SDC", &hp_sdc))
+		goto err1;
 
 	errstr = "NMI not available for";
-	if (request_irq(hp_sdc.nmi, &hp_sdc_nmisr, 0, "HP SDC NMI", 
-			(void *) hp_sdc.base_io)) goto err2;
+	if (request_irq(hp_sdc.nmi, &hp_sdc_nmisr, IRQF_SHARED,
+			"HP SDC NMI", &hp_sdc))
+		goto err2;
 
-	printk(KERN_INFO PREFIX "HP SDC at 0x%p, IRQ %d (NMI IRQ %d)\n", 
+	printk(KERN_INFO PREFIX "HP SDC at 0x%p, IRQ %d (NMI IRQ %d)\n",
 	       (void *)hp_sdc.base_io, hp_sdc.irq, hp_sdc.nmi);
 
 	hp_sdc_status_in8();
@@ -854,13 +912,14 @@
 	hp_sdc.dev_err = 0;
 	return 0;
  err2:
-	free_irq(hp_sdc.irq, NULL);
+	free_irq(hp_sdc.irq, &hp_sdc);
  err1:
 	release_region(hp_sdc.data_io, 2);
  err0:
-	printk(KERN_WARNING PREFIX ": %s SDC IO=0x%p IRQ=0x%x NMI=0x%x\n", 
+	printk(KERN_WARNING PREFIX ": %s SDC IO=0x%p IRQ=0x%x NMI=0x%x\n",
 		errstr, (void *)hp_sdc.base_io, hp_sdc.irq, hp_sdc.nmi);
 	hp_sdc.dev = NULL;
+
 	return hp_sdc.dev_err;
 }
 
@@ -868,8 +927,10 @@
 
 static int __init hp_sdc_init_hppa(struct parisc_device *d)
 {
-	if (!d) return 1;
-	if (hp_sdc.dev != NULL) return 1;	/* We only expect one SDC */
+	if (!d)
+		return 1;
+	if (hp_sdc.dev != NULL)
+		return 1;	/* We only expect one SDC */
 
 	hp_sdc.dev		= d;
 	hp_sdc.irq		= d->irq;
@@ -898,18 +959,16 @@
 	/* Wait until we know this has been processed by the i8042 */
 	hp_sdc_spin_ibf();
 
-	free_irq(hp_sdc.nmi, NULL);
-	free_irq(hp_sdc.irq, NULL);
+	free_irq(hp_sdc.nmi, &hp_sdc);
+	free_irq(hp_sdc.irq, &hp_sdc);
 	write_unlock_irq(&hp_sdc.lock);
 
 	del_timer(&hp_sdc.kicker);
 
 	tasklet_kill(&hp_sdc.task);
 
-/*        release_region(hp_sdc.data_io, 2); */
-
 #if defined(__hppa__)
-	if (unregister_parisc_driver(&hp_sdc_driver)) 
+	if (unregister_parisc_driver(&hp_sdc_driver))
 		printk(KERN_WARNING PREFIX "Error unregistering HP SDC");
 #endif
 }
@@ -923,7 +982,7 @@
 	mm_segment_t fs;
 	unsigned char i;
 #endif
-	
+
 	hp_sdc.dev = NULL;
 	hp_sdc.dev_err = 0;
 #if defined(__hppa__)
@@ -960,8 +1019,8 @@
 	tq_init.seq		= tq_init_seq;
 	tq_init.act.semaphore	= &tq_init_sem;
 
-	tq_init_seq[0] = 
-	  HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN | HP_SDC_ACT_SEMAPHORE;
+	tq_init_seq[0] =
+		HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN | HP_SDC_ACT_SEMAPHORE;
 	tq_init_seq[1] = HP_SDC_CMD_READ_KCC;
 	tq_init_seq[2] = 1;
 	tq_init_seq[3] = 0;
@@ -979,13 +1038,13 @@
 	}
 	hp_sdc.r11 = tq_init_seq[4];
 	if (hp_sdc.r11 & HP_SDC_CFG_NEW) {
-		char *str;
+		const char *str;
 		printk(KERN_INFO PREFIX "New style SDC\n");
 		tq_init_seq[1] = HP_SDC_CMD_READ_XTD;
 		tq_init.actidx		= 0;
 		tq_init.idx		= 1;
 		down(&tq_init_sem);
-		hp_sdc_enqueue_transaction(&tq_init);		
+		hp_sdc_enqueue_transaction(&tq_init);
 		down(&tq_init_sem);
 		up(&tq_init_sem);
 		if ((tq_init_seq[0] & HP_SDC_ACT_DEAD) == HP_SDC_ACT_DEAD) {
@@ -995,15 +1054,13 @@
 		hp_sdc.r7e = tq_init_seq[4];
 		HP_SDC_XTD_REV_STRINGS(hp_sdc.r7e & HP_SDC_XTD_REV, str)
 		printk(KERN_INFO PREFIX "Revision: %s\n", str);
-		if (hp_sdc.r7e & HP_SDC_XTD_BEEPER) {
+		if (hp_sdc.r7e & HP_SDC_XTD_BEEPER)
 			printk(KERN_INFO PREFIX "TI SN76494 beeper present\n");
-		}
-		if (hp_sdc.r7e & HP_SDC_XTD_BBRTC) {
+		if (hp_sdc.r7e & HP_SDC_XTD_BBRTC)
 			printk(KERN_INFO PREFIX "OKI MSM-58321 BBRTC present\n");
-		}
 		printk(KERN_INFO PREFIX "Spunking the self test register to force PUP "
 		       "on next firmware reset.\n");
-		tq_init_seq[0] = HP_SDC_ACT_PRECMD | 
+		tq_init_seq[0] = HP_SDC_ACT_PRECMD |
 			HP_SDC_ACT_DATAOUT | HP_SDC_ACT_SEMAPHORE;
 		tq_init_seq[1] = HP_SDC_CMD_SET_STR;
 		tq_init_seq[2] = 1;
@@ -1012,14 +1069,12 @@
 		tq_init.idx		= 1;
 		tq_init.endidx		= 4;
 		down(&tq_init_sem);
-		hp_sdc_enqueue_transaction(&tq_init);		
+		hp_sdc_enqueue_transaction(&tq_init);
 		down(&tq_init_sem);
 		up(&tq_init_sem);
-	}
-	else {
-		printk(KERN_INFO PREFIX "Old style SDC (1820-%s).\n", 
+	} else
+		printk(KERN_INFO PREFIX "Old style SDC (1820-%s).\n",
 		       (hp_sdc.r11 & HP_SDC_CFG_REV) ? "3300" : "2564/3087");
-	}
 
         return 0;
 }
@@ -1027,13 +1082,13 @@
 module_init(hp_sdc_register);
 module_exit(hp_sdc_exit);
 
-/* Timing notes:  These measurements taken on my 64MHz 7100-LC (715/64) 
+/* Timing notes:  These measurements taken on my 64MHz 7100-LC (715/64)
  *                                              cycles cycles-adj    time
  * between two consecutive mfctl(16)'s:              4        n/a    63ns
  * hp_sdc_spin_ibf when idle:                      119        115   1.7us
  * gsc_writeb status register:                      83         79   1.2us
  * IBF to clear after sending SET_IM:             6204       6006    93us
- * IBF to clear after sending LOAD_RT:            4467       4352    68us  
+ * IBF to clear after sending LOAD_RT:            4467       4352    68us
  * IBF to clear after sending two LOAD_RTs:      18974      18859   295us
  * READ_T1, read status/data, IRQ, call handler: 35564        n/a   556us
  * cmd to ~IBF READ_T1 2nd time right after:   5158403        n/a    81ms
diff --git a/drivers/input/serio/hp_sdc_mlc.c b/drivers/input/serio/hp_sdc_mlc.c
index aa4a8a4..c45ea74 100644
--- a/drivers/input/serio/hp_sdc_mlc.c
+++ b/drivers/input/serio/hp_sdc_mlc.c
@@ -58,12 +58,13 @@
 } hp_sdc_mlc_priv;
 
 /************************* Interrupt context ******************************/
-static void hp_sdc_mlc_isr (int irq, void *dev_id, 
-			    uint8_t status, uint8_t data) {
-  	int idx;
+static void hp_sdc_mlc_isr (int irq, void *dev_id,
+			    uint8_t status, uint8_t data)
+{
+	int idx;
 	hil_mlc *mlc = &hp_sdc_mlc;
 
-	write_lock(&(mlc->lock));
+	write_lock(&mlc->lock);
 	if (mlc->icount < 0) {
 		printk(KERN_WARNING PREFIX "HIL Overflow!\n");
 		up(&mlc->isem);
@@ -73,239 +74,232 @@
 	if ((status & HP_SDC_STATUS_IRQMASK) == HP_SDC_STATUS_HILDATA) {
 		mlc->ipacket[idx] |= data | HIL_ERR_INT;
 		mlc->icount--;
-		if (hp_sdc_mlc_priv.got5x) goto check;
-		if (!idx) goto check;
-		if ((mlc->ipacket[idx-1] & HIL_PKT_ADDR_MASK) !=
+		if (hp_sdc_mlc_priv.got5x || !idx)
+			goto check;
+		if ((mlc->ipacket[idx - 1] & HIL_PKT_ADDR_MASK) !=
 		    (mlc->ipacket[idx] & HIL_PKT_ADDR_MASK)) {
 			mlc->ipacket[idx] &= ~HIL_PKT_ADDR_MASK;
-			mlc->ipacket[idx] |= (mlc->ipacket[idx-1] 
-						    & HIL_PKT_ADDR_MASK);
+			mlc->ipacket[idx] |= (mlc->ipacket[idx - 1]
+						& HIL_PKT_ADDR_MASK);
 		}
 		goto check;
 	}
 	/* We know status is 5X */
-	if (data & HP_SDC_HIL_ISERR) goto err;
-	mlc->ipacket[idx] = 
+	if (data & HP_SDC_HIL_ISERR)
+		goto err;
+	mlc->ipacket[idx] =
 		(data & HP_SDC_HIL_R1MASK) << HIL_PKT_ADDR_SHIFT;
 	hp_sdc_mlc_priv.got5x = 1;
 	goto out;
 
  check:
 	hp_sdc_mlc_priv.got5x = 0;
-	if (mlc->imatch == 0) goto done;
-	if ((mlc->imatch == (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_POL)) 
-	    && (mlc->ipacket[idx] == (mlc->imatch | idx))) goto done;
-	if (mlc->ipacket[idx] == mlc->imatch) goto done;
+	if (mlc->imatch == 0)
+		goto done;
+	if ((mlc->imatch == (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_POL))
+	    && (mlc->ipacket[idx] == (mlc->imatch | idx)))
+		goto done;
+	if (mlc->ipacket[idx] == mlc->imatch)
+		goto done;
 	goto out;
 
- err:				
+ err:
 	printk(KERN_DEBUG PREFIX "err code %x\n", data);
+
 	switch (data) {
 	case HP_SDC_HIL_RC_DONE:
 		printk(KERN_WARNING PREFIX "Bastard SDC reconfigured loop!\n");
 		break;
+
 	case HP_SDC_HIL_ERR:
-		mlc->ipacket[idx] |= HIL_ERR_INT | HIL_ERR_PERR | 
-		  HIL_ERR_FERR | HIL_ERR_FOF;
+		mlc->ipacket[idx] |= HIL_ERR_INT | HIL_ERR_PERR |
+					HIL_ERR_FERR | HIL_ERR_FOF;
 		break;
+
 	case HP_SDC_HIL_TO:
 		mlc->ipacket[idx] |= HIL_ERR_INT | HIL_ERR_LERR;
 		break;
+
 	case HP_SDC_HIL_RC:
 		printk(KERN_WARNING PREFIX "Bastard SDC decided to reconfigure loop!\n");
 		break;
+
 	default:
 		printk(KERN_WARNING PREFIX "Unkown HIL Error status (%x)!\n", data);
 		break;
 	}
+
 	/* No more data will be coming due to an error. */
  done:
 	tasklet_schedule(mlc->tasklet);
-	up(&(mlc->isem));
+	up(&mlc->isem);
  out:
-	write_unlock(&(mlc->lock));
+	write_unlock(&mlc->lock);
 }
 
 
 /******************** Tasklet or userspace context functions ****************/
 
-static int hp_sdc_mlc_in (hil_mlc *mlc, suseconds_t timeout) {
-	unsigned long flags;
+static int hp_sdc_mlc_in(hil_mlc *mlc, suseconds_t timeout)
+{
 	struct hp_sdc_mlc_priv_s *priv;
 	int rc = 2;
 
 	priv = mlc->priv;
 
-	write_lock_irqsave(&(mlc->lock), flags);
-
 	/* Try to down the semaphore */
-	if (down_trylock(&(mlc->isem))) {
+	if (down_trylock(&mlc->isem)) {
 		struct timeval tv;
 		if (priv->emtestmode) {
-			mlc->ipacket[0] = 
-				HIL_ERR_INT | (mlc->opacket & 
-					       (HIL_PKT_CMD | 
-						HIL_PKT_ADDR_MASK | 
+			mlc->ipacket[0] =
+				HIL_ERR_INT | (mlc->opacket &
+					       (HIL_PKT_CMD |
+						HIL_PKT_ADDR_MASK |
 						HIL_PKT_DATA_MASK));
 			mlc->icount = 14;
 			/* printk(KERN_DEBUG PREFIX ">[%x]\n", mlc->ipacket[0]); */
 			goto wasup;
 		}
 		do_gettimeofday(&tv);
-		tv.tv_usec += 1000000 * (tv.tv_sec - mlc->instart.tv_sec);
+		tv.tv_usec += USEC_PER_SEC * (tv.tv_sec - mlc->instart.tv_sec);
 		if (tv.tv_usec - mlc->instart.tv_usec > mlc->intimeout) {
-		  /*		  printk("!%i %i", 
-				  tv.tv_usec - mlc->instart.tv_usec, 
-				  mlc->intimeout);
-		  */
+			/*	printk("!%i %i",
+				tv.tv_usec - mlc->instart.tv_usec,
+				mlc->intimeout);
+			 */
 			rc = 1;
-			up(&(mlc->isem));
+			up(&mlc->isem);
 		}
 		goto done;
 	}
  wasup:
-	up(&(mlc->isem));
+	up(&mlc->isem);
 	rc = 0;
-	goto done;
  done:
-	write_unlock_irqrestore(&(mlc->lock), flags);
 	return rc;
 }
 
-static int hp_sdc_mlc_cts (hil_mlc *mlc) {
+static int hp_sdc_mlc_cts(hil_mlc *mlc)
+{
 	struct hp_sdc_mlc_priv_s *priv;
-	unsigned long flags;
 
-	priv = mlc->priv;	
-
-	write_lock_irqsave(&(mlc->lock), flags);
+	priv = mlc->priv;
 
 	/* Try to down the semaphores -- they should be up. */
-	if (down_trylock(&(mlc->isem))) {
-		BUG();
-		goto busy;
-	}
-	if (down_trylock(&(mlc->osem))) {
-	 	BUG();
-		up(&(mlc->isem));
-		goto busy;
-	}
-	up(&(mlc->isem));
-	up(&(mlc->osem));
+	BUG_ON(down_trylock(&mlc->isem));
+	BUG_ON(down_trylock(&mlc->osem));
 
-	if (down_trylock(&(mlc->csem))) {
-		if (priv->trans.act.semaphore != &(mlc->csem)) goto poll;
-		goto busy;
+	up(&mlc->isem);
+	up(&mlc->osem);
+
+	if (down_trylock(&mlc->csem)) {
+		if (priv->trans.act.semaphore != &mlc->csem)
+			goto poll;
+		else
+			goto busy;
 	}
-	if (!(priv->tseq[4] & HP_SDC_USE_LOOP)) goto done;
+
+	if (!(priv->tseq[4] & HP_SDC_USE_LOOP))
+		goto done;
 
  poll:
-	priv->trans.act.semaphore = &(mlc->csem);
+	priv->trans.act.semaphore = &mlc->csem;
 	priv->trans.actidx = 0;
 	priv->trans.idx = 1;
 	priv->trans.endidx = 5;
-	priv->tseq[0] = 
+	priv->tseq[0] =
 		HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN | HP_SDC_ACT_SEMAPHORE;
 	priv->tseq[1] = HP_SDC_CMD_READ_USE;
 	priv->tseq[2] = 1;
 	priv->tseq[3] = 0;
 	priv->tseq[4] = 0;
-	hp_sdc_enqueue_transaction(&(priv->trans));
+	__hp_sdc_enqueue_transaction(&priv->trans);
  busy:
-	write_unlock_irqrestore(&(mlc->lock), flags);
 	return 1;
  done:
-	priv->trans.act.semaphore = &(mlc->osem);
-	up(&(mlc->csem));
-	write_unlock_irqrestore(&(mlc->lock), flags);
+	priv->trans.act.semaphore = &mlc->osem;
+	up(&mlc->csem);
 	return 0;
 }
 
-static void hp_sdc_mlc_out (hil_mlc *mlc) {
+static void hp_sdc_mlc_out(hil_mlc *mlc)
+{
 	struct hp_sdc_mlc_priv_s *priv;
-	unsigned long flags;
 
 	priv = mlc->priv;
 
-	write_lock_irqsave(&(mlc->lock), flags);
-	
 	/* Try to down the semaphore -- it should be up. */
-	if (down_trylock(&(mlc->osem))) {
-	 	BUG();
-		goto done;
-	}
+	BUG_ON(down_trylock(&mlc->osem));
 
-	if (mlc->opacket & HIL_DO_ALTER_CTRL) goto do_control;
+	if (mlc->opacket & HIL_DO_ALTER_CTRL)
+		goto do_control;
 
  do_data:
 	if (priv->emtestmode) {
-		up(&(mlc->osem));
-		goto done;
+		up(&mlc->osem);
+		return;
 	}
 	/* Shouldn't be sending commands when loop may be busy */
-	if (down_trylock(&(mlc->csem))) {
-	 	BUG();
-		goto done;
-	}
-	up(&(mlc->csem));
+	BUG_ON(down_trylock(&mlc->csem));
+	up(&mlc->csem);
 
 	priv->trans.actidx = 0;
 	priv->trans.idx = 1;
-	priv->trans.act.semaphore = &(mlc->osem);
+	priv->trans.act.semaphore = &mlc->osem;
 	priv->trans.endidx = 6;
-	priv->tseq[0] = 
+	priv->tseq[0] =
 		HP_SDC_ACT_DATAREG | HP_SDC_ACT_POSTCMD | HP_SDC_ACT_SEMAPHORE;
 	priv->tseq[1] = 0x7;
-	priv->tseq[2] = 
-		(mlc->opacket & 
+	priv->tseq[2] =
+		(mlc->opacket &
 		 (HIL_PKT_ADDR_MASK | HIL_PKT_CMD))
 		   >> HIL_PKT_ADDR_SHIFT;
-	priv->tseq[3] = 
-		(mlc->opacket & HIL_PKT_DATA_MASK) 
+	priv->tseq[3] =
+		(mlc->opacket & HIL_PKT_DATA_MASK)
 		  >> HIL_PKT_DATA_SHIFT;
 	priv->tseq[4] = 0;  /* No timeout */
-	if (priv->tseq[3] == HIL_CMD_DHR) priv->tseq[4] = 1;
+	if (priv->tseq[3] == HIL_CMD_DHR)
+		priv->tseq[4] = 1;
 	priv->tseq[5] = HP_SDC_CMD_DO_HIL;
 	goto enqueue;
 
  do_control:
 	priv->emtestmode = mlc->opacket & HIL_CTRL_TEST;
-	
+
 	/* we cannot emulate this, it should not be used. */
 	BUG_ON((mlc->opacket & (HIL_CTRL_APE | HIL_CTRL_IPF)) == HIL_CTRL_APE);
-	
-	if ((mlc->opacket & HIL_CTRL_ONLY) == HIL_CTRL_ONLY) goto control_only;
-	if (mlc->opacket & HIL_CTRL_APE) { 
-		BUG(); /* Should not send command/data after engaging APE */
-		goto done;
-	}
-	/* Disengaging APE this way would not be valid either since 
+
+	if ((mlc->opacket & HIL_CTRL_ONLY) == HIL_CTRL_ONLY)
+		goto control_only;
+
+	/* Should not send command/data after engaging APE */
+	BUG_ON(mlc->opacket & HIL_CTRL_APE);
+
+	/* Disengaging APE this way would not be valid either since
 	 * the loop must be allowed to idle.
 	 *
-	 * So, it works out that we really never actually send control 
-	 * and data when using SDC, we just send the data. 
+	 * So, it works out that we really never actually send control
+	 * and data when using SDC, we just send the data.
 	 */
 	goto do_data;
 
  control_only:
 	priv->trans.actidx = 0;
 	priv->trans.idx = 1;
-	priv->trans.act.semaphore = &(mlc->osem);
+	priv->trans.act.semaphore = &mlc->osem;
 	priv->trans.endidx = 4;
-	priv->tseq[0] = 
+	priv->tseq[0] =
 	  HP_SDC_ACT_PRECMD | HP_SDC_ACT_DATAOUT | HP_SDC_ACT_SEMAPHORE;
 	priv->tseq[1] = HP_SDC_CMD_SET_LPC;
 	priv->tseq[2] = 1;
-	//	priv->tseq[3] = (mlc->ddc + 1) | HP_SDC_LPS_ACSUCC;
+	/* priv->tseq[3] = (mlc->ddc + 1) | HP_SDC_LPS_ACSUCC; */
 	priv->tseq[3] = 0;
 	if (mlc->opacket & HIL_CTRL_APE) {
 		priv->tseq[3] |= HP_SDC_LPC_APE_IPF;
-		down_trylock(&(mlc->csem));
-	} 
+		down_trylock(&mlc->csem);
+	}
  enqueue:
-	hp_sdc_enqueue_transaction(&(priv->trans));
- done:
-	write_unlock_irqrestore(&(mlc->lock), flags);
+	hp_sdc_enqueue_transaction(&priv->trans);
 }
 
 static int __init hp_sdc_mlc_init(void)
@@ -316,18 +310,18 @@
 
 	hp_sdc_mlc_priv.emtestmode = 0;
 	hp_sdc_mlc_priv.trans.seq = hp_sdc_mlc_priv.tseq;
-	hp_sdc_mlc_priv.trans.act.semaphore = &(mlc->osem);
+	hp_sdc_mlc_priv.trans.act.semaphore = &mlc->osem;
 	hp_sdc_mlc_priv.got5x = 0;
 
-	mlc->cts		= &hp_sdc_mlc_cts;
-	mlc->in			= &hp_sdc_mlc_in;
-	mlc->out		= &hp_sdc_mlc_out;
+	mlc->cts = &hp_sdc_mlc_cts;
+	mlc->in	= &hp_sdc_mlc_in;
+	mlc->out = &hp_sdc_mlc_out;
+	mlc->priv = &hp_sdc_mlc_priv;
 
 	if (hil_mlc_register(mlc)) {
 		printk(KERN_WARNING PREFIX "Failed to register MLC structure with hil_mlc\n");
 		goto err0;
 	}
-	mlc->priv		= &hp_sdc_mlc_priv;
 
 	if (hp_sdc_request_hil_irq(&hp_sdc_mlc_isr)) {
 		printk(KERN_WARNING PREFIX "Request for raw HIL ISR hook denied\n");
@@ -335,10 +329,9 @@
 	}
 	return 0;
  err1:
-	if (hil_mlc_unregister(mlc)) {
+	if (hil_mlc_unregister(mlc))
 		printk(KERN_ERR PREFIX "Failed to unregister MLC structure with hil_mlc.\n"
 			"This is bad.  Could cause an oops.\n");
-	}
  err0:
 	return -EBUSY;
 }
@@ -346,14 +339,14 @@
 static void __exit hp_sdc_mlc_exit(void)
 {
 	hil_mlc *mlc = &hp_sdc_mlc;
-	if (hp_sdc_release_hil_irq(&hp_sdc_mlc_isr)) {
+
+	if (hp_sdc_release_hil_irq(&hp_sdc_mlc_isr))
 		printk(KERN_ERR PREFIX "Failed to release the raw HIL ISR hook.\n"
 			"This is bad.  Could cause an oops.\n");
-	}
-	if (hil_mlc_unregister(mlc)) {
+
+	if (hil_mlc_unregister(mlc))
 		printk(KERN_ERR PREFIX "Failed to unregister MLC structure with hil_mlc.\n"
 			"This is bad.  Could cause an oops.\n");
-	}
 }
 
 module_init(hp_sdc_mlc_init);
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h
index d36bd54..6858bc5 100644
--- a/drivers/input/serio/i8042-x86ia64io.h
+++ b/drivers/input/serio/i8042-x86ia64io.h
@@ -160,6 +160,28 @@
 		},
 	},
 	{
+		/*
+		 * No data is coming from the touchscreen unless KBC
+		 * is in legacy mode.
+		 */
+		.ident = "Panasonic CF-29",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Matsushita"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "CF-29"),
+		},
+	},
+	{
+		/*
+		 * Errors on MUX ports are reported without raising AUXDATA
+		 * causing "spurious NAK" messages.
+		 */
+		.ident = "HP Pavilion DV4017EA",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Pavilion dv4000 (EA032EA#ABF)"),
+		},
+	},
+	{
 		.ident = "Toshiba P10",
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
@@ -280,6 +302,8 @@
 };
 
 static struct pnp_device_id pnp_aux_devids[] = {
+	{ .id = "FJC6000", .driver_data = 0 },
+	{ .id = "FJC6001", .driver_data = 0 },
 	{ .id = "PNP0f03", .driver_data = 0 },
 	{ .id = "PNP0f0b", .driver_data = 0 },
 	{ .id = "PNP0f0e", .driver_data = 0 },
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c
index db9cca3..7c17377 100644
--- a/drivers/input/serio/i8042.c
+++ b/drivers/input/serio/i8042.c
@@ -768,6 +768,13 @@
 	i8042_flush();
 
 /*
+ * Disable both KBD and AUX interfaces so they don't get in the way
+ */
+
+	i8042_ctr |= I8042_CTR_KBDDIS | I8042_CTR_AUXDIS;
+	i8042_ctr &= ~(I8042_CTR_KBDINT | I8042_CTR_AUXINT);
+
+/*
  * Disable MUX mode if present.
  */
 
diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c
index 0a26e06..693e3b2 100644
--- a/drivers/input/touchscreen/ads7846.c
+++ b/drivers/input/touchscreen/ads7846.c
@@ -39,7 +39,8 @@
 /*
  * This code has been heavily tested on a Nokia 770, and lightly
  * tested on other ads7846 devices (OSK/Mistral, Lubbock).
- * Support for ads7843 and ads7845 has only been stubbed in.
+ * Support for ads7843 tested on Atmel at91sam926x-EK.
+ * Support for ads7845 has only been stubbed in.
  *
  * IRQ handling needs a workaround because of a shortcoming in handling
  * edge triggered IRQs on some platforms like the OMAP1/2. These
@@ -246,18 +247,16 @@
 
 	/* REVISIT:  take a few more samples, and compare ... */
 
-	/* maybe off internal vREF */
-	if (use_internal) {
-		req->ref_off = REF_OFF;
-		req->xfer[4].tx_buf = &req->ref_off;
-		req->xfer[4].len = 1;
-		spi_message_add_tail(&req->xfer[4], &req->msg);
+	/* converter in low power mode & enable PENIRQ */
+	req->ref_off = PWRDOWN;
+	req->xfer[4].tx_buf = &req->ref_off;
+	req->xfer[4].len = 1;
+	spi_message_add_tail(&req->xfer[4], &req->msg);
 
-		req->xfer[5].rx_buf = &req->scratch;
-		req->xfer[5].len = 2;
-		CS_CHANGE(req->xfer[5]);
-		spi_message_add_tail(&req->xfer[5], &req->msg);
-	}
+	req->xfer[5].rx_buf = &req->scratch;
+	req->xfer[5].len = 2;
+	CS_CHANGE(req->xfer[5]);
+	spi_message_add_tail(&req->xfer[5], &req->msg);
 
 	ts->irq_disabled = 1;
 	disable_irq(spi->irq);
@@ -536,6 +535,9 @@
 	} else
 		Rt = 0;
 
+	if (ts->model == 7843)
+		Rt = ts->pressure_max / 2;
+
 	/* Sample found inconsistent by debouncing or pressure is beyond
 	 * the maximum. Don't report it to user space, repeat at least
 	 * once more the measurement
@@ -897,7 +899,7 @@
 
 	input_dev->name = "ADS784x Touchscreen";
 	input_dev->phys = ts->phys;
-	input_dev->cdev.dev = &spi->dev;
+	input_dev->dev.parent = &spi->dev;
 
 	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
 	input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
diff --git a/drivers/input/touchscreen/corgi_ts.c b/drivers/input/touchscreen/corgi_ts.c
index e294558..e6a31d1 100644
--- a/drivers/input/touchscreen/corgi_ts.c
+++ b/drivers/input/touchscreen/corgi_ts.c
@@ -300,8 +300,7 @@
 	input_dev->id.vendor = 0x0001;
 	input_dev->id.product = 0x0002;
 	input_dev->id.version = 0x0100;
-	input_dev->cdev.dev = &pdev->dev;
-	input_dev->private = corgi_ts;
+	input_dev->dev.parent = &pdev->dev;
 
 	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
 	input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
diff --git a/drivers/input/touchscreen/elo.c b/drivers/input/touchscreen/elo.c
index 9d61cd1..557d781 100644
--- a/drivers/input/touchscreen/elo.c
+++ b/drivers/input/touchscreen/elo.c
@@ -312,14 +312,13 @@
 	init_completion(&elo->cmd_done);
 	snprintf(elo->phys, sizeof(elo->phys), "%s/input0", serio->phys);
 
-	input_dev->private = elo;
 	input_dev->name = "Elo Serial TouchScreen";
 	input_dev->phys = elo->phys;
 	input_dev->id.bustype = BUS_RS232;
 	input_dev->id.vendor = SERIO_ELO;
 	input_dev->id.product = elo->id;
 	input_dev->id.version = 0x0100;
-	input_dev->cdev.dev = &serio->dev;
+	input_dev->dev.parent = &serio->dev;
 
 	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
 	input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
diff --git a/drivers/input/touchscreen/gunze.c b/drivers/input/touchscreen/gunze.c
index 9157eb1..39d6026 100644
--- a/drivers/input/touchscreen/gunze.c
+++ b/drivers/input/touchscreen/gunze.c
@@ -130,13 +130,13 @@
 	gunze->dev = input_dev;
 	snprintf(gunze->phys, sizeof(serio->phys), "%s/input0", serio->phys);
 
-	input_dev->private = gunze;
 	input_dev->name = "Gunze AHL-51S TouchScreen";
 	input_dev->phys = gunze->phys;
 	input_dev->id.bustype = BUS_RS232;
 	input_dev->id.vendor = SERIO_GUNZE;
 	input_dev->id.product = 0x0051;
 	input_dev->id.version = 0x0100;
+	input_dev->dev.parent = &serio->dev;
 	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
 	input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
 	input_set_abs_params(input_dev, ABS_X, 24, 1000, 0, 0);
diff --git a/drivers/input/touchscreen/h3600_ts_input.c b/drivers/input/touchscreen/h3600_ts_input.c
index c4116d4..09ed780 100644
--- a/drivers/input/touchscreen/h3600_ts_input.c
+++ b/drivers/input/touchscreen/h3600_ts_input.c
@@ -147,7 +147,7 @@
 unsigned int h3600_flite_power(struct input_dev *dev, enum flite_pwr pwr)
 {
 	unsigned char brightness = (pwr == FLITE_PWR_OFF) ? 0 : flite_brightness;
-	struct h3600_dev *ts = dev->private;
+	struct h3600_dev *ts = input_get_drvdata(dev);
 
 	/* Must be in this order */
 	ts->serio->write(ts->serio, 1);
@@ -260,7 +260,7 @@
 			 unsigned int code, int value)
 {
 #if 0
-	struct h3600_dev *ts = dev->private;
+	struct h3600_dev *ts = input_get_drvdata(dev);
 
 	switch (type) {
 		case EV_LED: {
@@ -367,8 +367,9 @@
 	input_dev->id.vendor = SERIO_H3600;
 	input_dev->id.product = 0x0666;  /* FIXME !!! We can ask the hardware */
 	input_dev->id.version = 0x0100;
-	input_dev->cdev.dev = &serio->dev;
-	input_dev->private = ts;
+	input_dev->dev.parent = &serio->dev;
+
+	input_set_drvdata(input_dev, ts);
 
 	input_dev->event = h3600ts_event;
 
diff --git a/drivers/input/touchscreen/mtouch.c b/drivers/input/touchscreen/mtouch.c
index c3c2d73..4ec3b1f 100644
--- a/drivers/input/touchscreen/mtouch.c
+++ b/drivers/input/touchscreen/mtouch.c
@@ -144,13 +144,13 @@
 	mtouch->dev = input_dev;
 	snprintf(mtouch->phys, sizeof(mtouch->phys), "%s/input0", serio->phys);
 
-	input_dev->private = mtouch;
 	input_dev->name = "MicroTouch Serial TouchScreen";
 	input_dev->phys = mtouch->phys;
 	input_dev->id.bustype = BUS_RS232;
 	input_dev->id.vendor = SERIO_MICROTOUCH;
 	input_dev->id.product = 0;
 	input_dev->id.version = 0x0100;
+	input_dev->dev.parent = &serio->dev;
 	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
 	input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
 	input_set_abs_params(mtouch->dev, ABS_X, MTOUCH_MIN_XC, MTOUCH_MAX_XC, 0, 0);
diff --git a/drivers/input/touchscreen/penmount.c b/drivers/input/touchscreen/penmount.c
index bd27679..f2c0d3c 100644
--- a/drivers/input/touchscreen/penmount.c
+++ b/drivers/input/touchscreen/penmount.c
@@ -105,14 +105,13 @@
 	pm->dev = input_dev;
 	snprintf(pm->phys, sizeof(pm->phys), "%s/input0", serio->phys);
 
-	input_dev->private = pm;
 	input_dev->name = "Penmount Serial TouchScreen";
 	input_dev->phys = pm->phys;
 	input_dev->id.bustype = BUS_RS232;
 	input_dev->id.vendor = SERIO_PENMOUNT;
 	input_dev->id.product = 0;
 	input_dev->id.version = 0x0100;
-	input_dev->cdev.dev = &serio->dev;
+	input_dev->dev.parent = &serio->dev;
 
         input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
         input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
diff --git a/drivers/input/touchscreen/touchright.c b/drivers/input/touchscreen/touchright.c
index 35ba46c..3def7bb 100644
--- a/drivers/input/touchscreen/touchright.c
+++ b/drivers/input/touchscreen/touchright.c
@@ -118,13 +118,13 @@
 	tr->dev = input_dev;
 	snprintf(tr->phys, sizeof(tr->phys), "%s/input0", serio->phys);
 
-	input_dev->private = tr;
 	input_dev->name = "Touchright Serial TouchScreen";
 	input_dev->phys = tr->phys;
 	input_dev->id.bustype = BUS_RS232;
 	input_dev->id.vendor = SERIO_TOUCHRIGHT;
 	input_dev->id.product = 0;
 	input_dev->id.version = 0x0100;
+	input_dev->dev.parent = &serio->dev;
 	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
 	input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
 	input_set_abs_params(tr->dev, ABS_X, TR_MIN_XC, TR_MAX_XC, 0, 0);
diff --git a/drivers/input/touchscreen/touchwin.c b/drivers/input/touchscreen/touchwin.c
index 4dc073d..ac4bdcf 100644
--- a/drivers/input/touchscreen/touchwin.c
+++ b/drivers/input/touchscreen/touchwin.c
@@ -125,13 +125,13 @@
 	tw->dev = input_dev;
 	snprintf(tw->phys, sizeof(tw->phys), "%s/input0", serio->phys);
 
-	input_dev->private = tw;
 	input_dev->name = "Touchwindow Serial TouchScreen";
 	input_dev->phys = tw->phys;
 	input_dev->id.bustype = BUS_RS232;
 	input_dev->id.vendor = SERIO_TOUCHWIN;
 	input_dev->id.product = 0;
 	input_dev->id.version = 0x0100;
+	input_dev->dev.parent = &serio->dev;
 	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
 	input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
 	input_set_abs_params(tw->dev, ABS_X, TW_MIN_XC, TW_MAX_XC, 0, 0);
diff --git a/drivers/input/touchscreen/ucb1400_ts.c b/drivers/input/touchscreen/ucb1400_ts.c
index e8606c4..6582816 100644
--- a/drivers/input/touchscreen/ucb1400_ts.c
+++ b/drivers/input/touchscreen/ucb1400_ts.c
@@ -97,6 +97,8 @@
 };
 
 static int adcsync;
+static int ts_delay = 55; /* us */
+static int ts_delay_pressure;	/* us */
 
 static inline u16 ucb1400_reg_read(struct ucb1400 *ucb, u16 reg)
 {
@@ -159,6 +161,7 @@
 			UCB_TS_CR_TSMX_POW | UCB_TS_CR_TSPX_POW |
 			UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND |
 			UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
+	udelay(ts_delay_pressure);
 	return ucb1400_adc_read(ucb, UCB_ADC_INP_TSPY);
 }
 
@@ -180,7 +183,7 @@
 			UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |
 			UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA);
 
-	udelay(55);
+	udelay(ts_delay);
 
 	return ucb1400_adc_read(ucb, UCB_ADC_INP_TSPY);
 }
@@ -203,7 +206,7 @@
 			UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |
 			UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA);
 
-	udelay(55);
+	udelay(ts_delay);
 
 	return ucb1400_adc_read(ucb, UCB_ADC_INP_TSPX);
 }
@@ -369,7 +372,7 @@
 
 static int ucb1400_ts_open(struct input_dev *idev)
 {
-	struct ucb1400 *ucb = idev->private;
+	struct ucb1400 *ucb = input_get_drvdata(idev);
 	int ret = 0;
 
 	BUG_ON(ucb->ts_task);
@@ -385,7 +388,7 @@
 
 static void ucb1400_ts_close(struct input_dev *idev)
 {
-	struct ucb1400 *ucb = idev->private;
+	struct ucb1400 *ucb = input_get_drvdata(idev);
 
 	if (ucb->ts_task)
 		kthread_stop(ucb->ts_task);
@@ -507,8 +510,9 @@
 	}
 	printk(KERN_DEBUG "UCB1400: found IRQ %d\n", ucb->irq);
 
-	idev->private		= ucb;
-	idev->cdev.dev		= dev;
+	input_set_drvdata(idev, ucb);
+
+	idev->dev.parent	= dev;
 	idev->name		= "UCB1400 touchscreen interface";
 	idev->id.vendor		= ucb1400_reg_read(ucb, AC97_VENDOR_ID1);
 	idev->id.product	= id;
@@ -571,7 +575,15 @@
 	driver_unregister(&ucb1400_ts_driver);
 }
 
-module_param(adcsync, int, 0444);
+module_param(adcsync, bool, 0444);
+MODULE_PARM_DESC(adcsync, "Synchronize touch readings with ADCSYNC pin.");
+
+module_param(ts_delay, int, 0444);
+MODULE_PARM_DESC(ts_delay, "Delay between panel setup and position read. Default = 55us.");
+
+module_param(ts_delay_pressure, int, 0444);
+MODULE_PARM_DESC(ts_delay_pressure,
+		  "delay between panel setup and pressure read.  Default = 0us.");
 
 module_init(ucb1400_ts_init);
 module_exit(ucb1400_ts_exit);
diff --git a/drivers/input/tsdev.c b/drivers/input/tsdev.c
index 0300dca..5e5b5c9 100644
--- a/drivers/input/tsdev.c
+++ b/drivers/input/tsdev.c
@@ -111,13 +111,13 @@
 	int minor;
 	char name[8];
 	wait_queue_head_t wait;
-	struct list_head list;
+	struct list_head client_list;
 	struct input_handle handle;
 	int x, y, pressure;
 	struct ts_calibration cal;
 };
 
-struct tsdev_list {
+struct tsdev_client {
 	struct fasync_struct *fasync;
 	struct list_head node;
 	struct tsdev *tsdev;
@@ -139,38 +139,49 @@
 
 static int tsdev_fasync(int fd, struct file *file, int on)
 {
-	struct tsdev_list *list = file->private_data;
+	struct tsdev_client *client = file->private_data;
 	int retval;
 
-	retval = fasync_helper(fd, file, on, &list->fasync);
+	retval = fasync_helper(fd, file, on, &client->fasync);
 	return retval < 0 ? retval : 0;
 }
 
 static int tsdev_open(struct inode *inode, struct file *file)
 {
 	int i = iminor(inode) - TSDEV_MINOR_BASE;
-	struct tsdev_list *list;
+	struct tsdev_client *client;
+	struct tsdev *tsdev;
+	int error;
 
 	printk(KERN_WARNING "tsdev (compaq touchscreen emulation) is scheduled "
 		"for removal.\nSee Documentation/feature-removal-schedule.txt "
 		"for details.\n");
 
-	if (i >= TSDEV_MINORS || !tsdev_table[i & TSDEV_MINOR_MASK])
+	if (i >= TSDEV_MINORS)
 		return -ENODEV;
 
-	if (!(list = kzalloc(sizeof(struct tsdev_list), GFP_KERNEL)))
+	tsdev = tsdev_table[i & TSDEV_MINOR_MASK];
+	if (!tsdev || !tsdev->exist)
+		return -ENODEV;
+
+	client = kzalloc(sizeof(struct tsdev_client), GFP_KERNEL);
+	if (!client)
 		return -ENOMEM;
 
-	list->raw = (i >= TSDEV_MINORS/2) ? 1 : 0;
+	client->tsdev = tsdev;
+	client->raw = (i >= TSDEV_MINORS / 2) ? 1 : 0;
+	list_add_tail(&client->node, &tsdev->client_list);
 
-	i &= TSDEV_MINOR_MASK;
-	list->tsdev = tsdev_table[i];
-	list_add_tail(&list->node, &tsdev_table[i]->list);
-	file->private_data = list;
+	if (!tsdev->open++ && tsdev->exist) {
+		error = input_open_device(&tsdev->handle);
+		if (error) {
+			list_del(&client->node);
+			kfree(client);
+			return error;
+		}
+	}
 
-	if (!list->tsdev->open++)
-		if (list->tsdev->exist)
-			input_open_device(&list->tsdev->handle);
+	file->private_data = client;
 	return 0;
 }
 
@@ -182,45 +193,48 @@
 
 static int tsdev_release(struct inode *inode, struct file *file)
 {
-	struct tsdev_list *list = file->private_data;
+	struct tsdev_client *client = file->private_data;
+	struct tsdev *tsdev = client->tsdev;
 
 	tsdev_fasync(-1, file, 0);
-	list_del(&list->node);
 
-	if (!--list->tsdev->open) {
-		if (list->tsdev->exist)
-			input_close_device(&list->tsdev->handle);
+	list_del(&client->node);
+	kfree(client);
+
+	if (!--tsdev->open) {
+		if (tsdev->exist)
+			input_close_device(&tsdev->handle);
 		else
-			tsdev_free(list->tsdev);
+			tsdev_free(tsdev);
 	}
-	kfree(list);
+
 	return 0;
 }
 
 static ssize_t tsdev_read(struct file *file, char __user *buffer, size_t count,
-			  loff_t * ppos)
+			  loff_t *ppos)
 {
-	struct tsdev_list *list = file->private_data;
+	struct tsdev_client *client = file->private_data;
+	struct tsdev *tsdev = client->tsdev;
 	int retval = 0;
 
-	if (list->head == list->tail && list->tsdev->exist && (file->f_flags & O_NONBLOCK))
+	if (client->head == client->tail && tsdev->exist && (file->f_flags & O_NONBLOCK))
 		return -EAGAIN;
 
-	retval = wait_event_interruptible(list->tsdev->wait,
-			list->head != list->tail || !list->tsdev->exist);
-
+	retval = wait_event_interruptible(tsdev->wait,
+			client->head != client->tail || !tsdev->exist);
 	if (retval)
 		return retval;
 
-	if (!list->tsdev->exist)
+	if (!tsdev->exist)
 		return -ENODEV;
 
-	while (list->head != list->tail &&
+	while (client->head != client->tail &&
 	       retval + sizeof (struct ts_event) <= count) {
-		if (copy_to_user (buffer + retval, list->event + list->tail,
+		if (copy_to_user (buffer + retval, client->event + client->tail,
 				  sizeof (struct ts_event)))
 			return -EFAULT;
-		list->tail = (list->tail + 1) & (TSDEV_BUFFER_SIZE - 1);
+		client->tail = (client->tail + 1) & (TSDEV_BUFFER_SIZE - 1);
 		retval += sizeof (struct ts_event);
 	}
 
@@ -228,32 +242,33 @@
 }
 
 /* No kernel lock - fine */
-static unsigned int tsdev_poll(struct file *file, poll_table * wait)
+static unsigned int tsdev_poll(struct file *file, poll_table *wait)
 {
-	struct tsdev_list *list = file->private_data;
+	struct tsdev_client *client = file->private_data;
+	struct tsdev *tsdev = client->tsdev;
 
-	poll_wait(file, &list->tsdev->wait, wait);
-	return ((list->head == list->tail) ? 0 : (POLLIN | POLLRDNORM)) |
-		(list->tsdev->exist ? 0 : (POLLHUP | POLLERR));
+	poll_wait(file, &tsdev->wait, wait);
+	return ((client->head == client->tail) ? 0 : (POLLIN | POLLRDNORM)) |
+		(tsdev->exist ? 0 : (POLLHUP | POLLERR));
 }
 
 static int tsdev_ioctl(struct inode *inode, struct file *file,
 		       unsigned int cmd, unsigned long arg)
 {
-	struct tsdev_list *list = file->private_data;
-	struct tsdev *tsdev = list->tsdev;
+	struct tsdev_client *client = file->private_data;
+	struct tsdev *tsdev = client->tsdev;
 	int retval = 0;
 
 	switch (cmd) {
 	case TS_GET_CAL:
-		if (copy_to_user ((void __user *)arg, &tsdev->cal,
-				  sizeof (struct ts_calibration)))
+		if (copy_to_user((void __user *)arg, &tsdev->cal,
+				 sizeof (struct ts_calibration)))
 			retval = -EFAULT;
 		break;
 
 	case TS_SET_CAL:
-		if (copy_from_user (&tsdev->cal, (void __user *)arg,
-				    sizeof (struct ts_calibration)))
+		if (copy_from_user(&tsdev->cal, (void __user *)arg,
+				   sizeof (struct ts_calibration)))
 			retval = -EFAULT;
 		break;
 
@@ -279,7 +294,7 @@
 			unsigned int code, int value)
 {
 	struct tsdev *tsdev = handle->private;
-	struct tsdev_list *list;
+	struct tsdev_client *client;
 	struct timeval time;
 
 	switch (type) {
@@ -343,18 +358,18 @@
 	if (type != EV_SYN || code != SYN_REPORT)
 		return;
 
-	list_for_each_entry(list, &tsdev->list, node) {
+	list_for_each_entry(client, &tsdev->client_list, node) {
 		int x, y, tmp;
 
 		do_gettimeofday(&time);
-		list->event[list->head].millisecs = time.tv_usec / 100;
-		list->event[list->head].pressure = tsdev->pressure;
+		client->event[client->head].millisecs = time.tv_usec / 100;
+		client->event[client->head].pressure = tsdev->pressure;
 
 		x = tsdev->x;
 		y = tsdev->y;
 
 		/* Calibration */
-		if (!list->raw) {
+		if (!client->raw) {
 			x = ((x * tsdev->cal.xscale) >> 8) + tsdev->cal.xtrans;
 			y = ((y * tsdev->cal.yscale) >> 8) + tsdev->cal.ytrans;
 			if (tsdev->cal.xyswap) {
@@ -362,33 +377,35 @@
 			}
 		}
 
-		list->event[list->head].x = x;
-		list->event[list->head].y = y;
-		list->head = (list->head + 1) & (TSDEV_BUFFER_SIZE - 1);
-		kill_fasync(&list->fasync, SIGIO, POLL_IN);
+		client->event[client->head].x = x;
+		client->event[client->head].y = y;
+		client->head = (client->head + 1) & (TSDEV_BUFFER_SIZE - 1);
+		kill_fasync(&client->fasync, SIGIO, POLL_IN);
 	}
 	wake_up_interruptible(&tsdev->wait);
 }
 
-static struct input_handle *tsdev_connect(struct input_handler *handler,
-					  struct input_dev *dev,
-					  const struct input_device_id *id)
+static int tsdev_connect(struct input_handler *handler, struct input_dev *dev,
+			 const struct input_device_id *id)
 {
 	struct tsdev *tsdev;
 	struct class_device *cdev;
+	dev_t devt;
 	int minor, delta;
+	int error;
 
 	for (minor = 0; minor < TSDEV_MINORS / 2 && tsdev_table[minor]; minor++);
 	if (minor >= TSDEV_MINORS / 2) {
 		printk(KERN_ERR
 		       "tsdev: You have way too many touchscreens\n");
-		return NULL;
+		return -ENFILE;
 	}
 
-	if (!(tsdev = kzalloc(sizeof(struct tsdev), GFP_KERNEL)))
-		return NULL;
+	tsdev = kzalloc(sizeof(struct tsdev), GFP_KERNEL);
+	if (!tsdev)
+		return -ENOMEM;
 
-	INIT_LIST_HEAD(&tsdev->list);
+	INIT_LIST_HEAD(&tsdev->client_list);
 	init_waitqueue_head(&tsdev->wait);
 
 	sprintf(tsdev->name, "ts%d", minor);
@@ -415,23 +432,45 @@
 
 	tsdev_table[minor] = tsdev;
 
-	cdev = class_device_create(&input_class, &dev->cdev,
-			MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + minor),
-			dev->cdev.dev, tsdev->name);
+	devt = MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + minor),
+
+	cdev = class_device_create(&input_class, &dev->cdev, devt,
+				   dev->cdev.dev, tsdev->name);
+	if (IS_ERR(cdev)) {
+		error = PTR_ERR(cdev);
+		goto err_free_tsdev;
+	}
 
 	/* temporary symlink to keep userspace happy */
-	sysfs_create_link(&input_class.subsys.kset.kobj, &cdev->kobj,
-			  tsdev->name);
+	error = sysfs_create_link(&input_class.subsys.kobj,
+				  &cdev->kobj, tsdev->name);
+	if (error)
+		goto err_cdev_destroy;
 
-	return &tsdev->handle;
+	error = input_register_handle(&tsdev->handle);
+	if (error)
+		goto err_remove_link;
+
+	return 0;
+
+ err_remove_link:
+	sysfs_remove_link(&input_class.subsys.kobj, tsdev->name);
+ err_cdev_destroy:
+	class_device_destroy(&input_class, devt);
+ err_free_tsdev:
+	tsdev_table[minor] = NULL;
+	kfree(tsdev);
+	return error;
 }
 
 static void tsdev_disconnect(struct input_handle *handle)
 {
 	struct tsdev *tsdev = handle->private;
-	struct tsdev_list *list;
+	struct tsdev_client *client;
 
-	sysfs_remove_link(&input_class.subsys.kset.kobj, tsdev->name);
+	input_unregister_handle(handle);
+
+	sysfs_remove_link(&input_class.subsys.kobj, tsdev->name);
 	class_device_destroy(&input_class,
 			MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + tsdev->minor));
 	tsdev->exist = 0;
@@ -439,8 +478,8 @@
 	if (tsdev->open) {
 		input_close_device(handle);
 		wake_up_interruptible(&tsdev->wait);
-		list_for_each_entry(list, &tsdev->list, node)
-			kill_fasync(&list->fasync, SIGIO, POLL_HUP);
+		list_for_each_entry(client, &tsdev->client_list, node)
+			kill_fasync(&client->fasync, SIGIO, POLL_HUP);
 	} else
 		tsdev_free(tsdev);
 }
diff --git a/drivers/isdn/hisax/netjet.c b/drivers/isdn/hisax/netjet.c
index 38f648f..02c6fba 100644
--- a/drivers/isdn/hisax/netjet.c
+++ b/drivers/isdn/hisax/netjet.c
@@ -19,7 +19,6 @@
 #include "isac.h"
 #include "hscx.h"
 #include "isdnl1.h"
-#include <linux/pci.h>
 #include <linux/interrupt.h>
 #include <linux/ppp_defs.h>
 #include <asm/io.h>
diff --git a/drivers/isdn/hysdn/hysdn_proclog.c b/drivers/isdn/hysdn/hysdn_proclog.c
index f7e83a8..4c7deda 100644
--- a/drivers/isdn/hysdn/hysdn_proclog.c
+++ b/drivers/isdn/hysdn/hysdn_proclog.c
@@ -13,7 +13,6 @@
 #include <linux/module.h>
 #include <linux/poll.h>
 #include <linux/proc_fs.h>
-#include <linux/pci.h>
 #include <linux/smp_lock.h>
 
 #include "hysdn_defs.h"
diff --git a/drivers/macintosh/therm_windtunnel.c b/drivers/macintosh/therm_windtunnel.c
index 35233de..3d0354e 100644
--- a/drivers/macintosh/therm_windtunnel.c
+++ b/drivers/macintosh/therm_windtunnel.c
@@ -459,7 +459,8 @@
 static int
 therm_of_remove( struct of_device *dev )
 {
-	return i2c_del_driver( &g4fan_driver );
+	i2c_del_driver( &g4fan_driver );
+	return 0;
 }
 
 static struct of_device_id therm_of_match[] = {{
diff --git a/drivers/macintosh/via-cuda.c b/drivers/macintosh/via-cuda.c
index 76d2177..741a93a 100644
--- a/drivers/macintosh/via-cuda.c
+++ b/drivers/macintosh/via-cuda.c
@@ -82,6 +82,7 @@
 static unsigned char *reply_ptr;
 static int reading_reply;
 static int data_index;
+static int cuda_irq;
 #ifdef CONFIG_PPC
 static struct device_node *vias;
 #endif
@@ -160,10 +161,8 @@
     /* Clear and enable interrupts, but only on PPC. On 68K it's done  */
     /* for us by the main VIA driver in arch/m68k/mac/via.c        */
 
-#ifndef CONFIG_MAC
     out_8(&via[IFR], 0x7f);	/* clear interrupts by writing 1s */
     out_8(&via[IER], IER_SET|SR_INT); /* enable interrupt from SR */
-#endif
 
     /* enable autopoll */
     cuda_request(&req, NULL, 3, CUDA_PACKET, CUDA_AUTOPOLL, 1);
@@ -181,24 +180,22 @@
 
 static int __init via_cuda_start(void)
 {
-    unsigned int irq;
-
     if (via == NULL)
 	return -ENODEV;
 
 #ifdef CONFIG_MAC
-    irq = IRQ_MAC_ADB;
+    cuda_irq = IRQ_MAC_ADB;
 #else /* CONFIG_MAC */
-    irq = irq_of_parse_and_map(vias, 0);
-    if (irq == NO_IRQ) {
+    cuda_irq = irq_of_parse_and_map(vias, 0);
+    if (cuda_irq == NO_IRQ) {
 	printk(KERN_ERR "via-cuda: can't map interrupts for %s\n",
 	       vias->full_name);
 	return -ENODEV;
     }
-#endif /* CONFIG_MAP */
+#endif /* CONFIG_MAC */
 
-    if (request_irq(irq, cuda_interrupt, 0, "ADB", cuda_interrupt)) {
-	printk(KERN_ERR "via-cuda: can't request irq %d\n", irq);
+    if (request_irq(cuda_irq, cuda_interrupt, 0, "ADB", cuda_interrupt)) {
+	printk(KERN_ERR "via-cuda: can't request irq %d\n", cuda_irq);
 	return -EAGAIN;
     }
 
@@ -238,6 +235,7 @@
 	printk(KERN_ERR "cuda_init_via() failed\n");
 	return -ENODEV;
     }
+    out_8(&via[IER], IER_SET|SR_INT); /* enable interrupt from SR */
 
     return via_cuda_start();
 #endif
@@ -263,15 +261,17 @@
     out_8(&via[B], in_8(&via[B]) | TACK | TIP);			/* negate them */
     out_8(&via[ACR] ,(in_8(&via[ACR]) & ~SR_CTRL) | SR_EXT);	/* SR data in */
     (void)in_8(&via[SR]);						/* clear any left-over data */
-#ifndef CONFIG_MAC
+#ifdef CONFIG_PPC
     out_8(&via[IER], 0x7f);					/* disable interrupts from VIA */
     (void)in_8(&via[IER]);
+#else
+    out_8(&via[IER], SR_INT);					/* disable SR interrupt from VIA */
 #endif
 
     /* delay 4ms and then clear any pending interrupt */
     mdelay(4);
     (void)in_8(&via[SR]);
-    out_8(&via[IFR], in_8(&via[IFR]) & 0x7f);
+    out_8(&via[IFR], SR_INT);
 
     /* sync with the CUDA - assert TACK without TIP */
     out_8(&via[B], in_8(&via[B]) & ~TACK);
@@ -282,7 +282,7 @@
     /* wait for the interrupt and then clear it */
     WAIT_FOR(in_8(&via[IFR]) & SR_INT, "CUDA response to sync (2)");
     (void)in_8(&via[SR]);
-    out_8(&via[IFR], in_8(&via[IFR]) & 0x7f);
+    out_8(&via[IFR], SR_INT);
 
     /* finish the sync by negating TACK */
     out_8(&via[B], in_8(&via[B]) | TACK);
@@ -291,7 +291,7 @@
     WAIT_FOR(in_8(&via[B]) & TREQ, "CUDA response to sync (3)");
     WAIT_FOR(in_8(&via[IFR]) & SR_INT, "CUDA response to sync (4)");
     (void)in_8(&via[SR]);
-    out_8(&via[IFR], in_8(&via[IFR]) & 0x7f);
+    out_8(&via[IFR], SR_INT);
     out_8(&via[B], in_8(&via[B]) | TIP);	/* should be unnecessary */
 
     return 0;
@@ -428,16 +428,12 @@
 void
 cuda_poll(void)
 {
-    unsigned long flags;
-
     /* cuda_interrupt only takes a normal lock, we disable
      * interrupts here to avoid re-entering and thus deadlocking.
-     * An option would be to disable only the IRQ source with
-     * disable_irq(), would that work on m68k ? --BenH
      */
-    local_irq_save(flags);
+    disable_irq(cuda_irq);
     cuda_interrupt(0, NULL);
-    local_irq_restore(flags);
+    enable_irq(cuda_irq);
 }
 
 static irqreturn_t
@@ -448,15 +444,25 @@
     unsigned char ibuf[16];
     int ibuf_len = 0;
     int complete = 0;
-    unsigned char virq;
     
     spin_lock(&cuda_lock);
 
-    virq = in_8(&via[IFR]) & 0x7f;
-    out_8(&via[IFR], virq);   
-    if ((virq & SR_INT) == 0) {
-        spin_unlock(&cuda_lock);
-	return IRQ_NONE;
+    /* On powermacs, this handler is registered for the VIA IRQ. But it uses
+     * just the shift register IRQ -- other VIA interrupt sources are disabled.
+     * On m68k macs, the VIA IRQ sources are dispatched individually. Unless
+     * we are polling, the shift register IRQ flag has already been cleared.
+     */
+
+#ifdef CONFIG_MAC
+    if (!arg)
+#endif
+    {
+        if ((in_8(&via[IFR]) & SR_INT) == 0) {
+            spin_unlock(&cuda_lock);
+            return IRQ_NONE;
+        } else {
+            out_8(&via[IFR], SR_INT);
+        }
     }
     
     status = (~in_8(&via[B]) & (TIP|TREQ)) | (in_8(&via[ACR]) & SR_OUT);
diff --git a/drivers/macintosh/via-macii.c b/drivers/macintosh/via-macii.c
index 1b3bad6..01b8eca 100644
--- a/drivers/macintosh/via-macii.c
+++ b/drivers/macintosh/via-macii.c
@@ -12,6 +12,15 @@
  * 1999-08-02 (jmt) - Initial rewrite for Unified ADB.
  * 2000-03-29 Tony Mantler <tonym@mac.linux-m68k.org>
  * 				- Big overhaul, should actually work now.
+ * 2006-12-31 Finn Thain <fthain@telegraphics.com.au> - Another overhaul.
+ *
+ * Suggested reading:
+ *   Inside Macintosh, ch. 5 ADB Manager
+ *   Guide to the Macinstosh Family Hardware, ch. 8 Apple Desktop Bus
+ *   Rockwell R6522 VIA datasheet
+ *
+ * Apple's "ADB Analyzer" bus sniffer is invaluable:
+ *   ftp://ftp.apple.com/developer/Tool_Chest/Devices_-_Hardware/Apple_Desktop_Bus/
  */
  
 #include <stdarg.h>
@@ -26,7 +35,6 @@
 #include <asm/macints.h>
 #include <asm/machw.h>
 #include <asm/mac_via.h>
-#include <asm/io.h>
 #include <asm/system.h>
 
 static volatile unsigned char *via;
@@ -51,9 +59,7 @@
 #define ANH		(15*RS)		/* A-side data, no handshake */
 
 /* Bits in B data register: all active low */
-#define TREQ		0x08		/* Transfer request (input) */
-#define TACK		0x10		/* Transfer acknowledge (output) */
-#define TIP		0x20		/* Transfer in progress (output) */
+#define CTLR_IRQ	0x08		/* Controller rcv status (input) */
 #define ST_MASK		0x30		/* mask for selecting ADB state bits */
 
 /* Bits in ACR */
@@ -65,8 +71,6 @@
 #define IER_SET		0x80		/* set bits in IER */
 #define IER_CLR		0		/* clear bits in IER */
 #define SR_INT		0x04		/* Shift register full/empty */
-#define SR_DATA		0x08		/* Shift register data */
-#define SR_CLOCK	0x10		/* Shift register clock */
 
 /* ADB transaction states according to GMHW */
 #define ST_CMD		0x00		/* ADB state: command byte */
@@ -77,7 +81,6 @@
 static int  macii_init_via(void);
 static void macii_start(void);
 static irqreturn_t macii_interrupt(int irq, void *arg);
-static void macii_retransmit(int);
 static void macii_queue_poll(void);
 
 static int macii_probe(void);
@@ -103,29 +106,37 @@
 	sending,
 	reading,
 	read_done,
-	awaiting_reply
 } macii_state;
 
-static int need_poll;
-static int command_byte;
-static int last_reply;
-static int last_active;
+static struct adb_request *current_req; /* first request struct in the queue */
+static struct adb_request *last_req;     /* last request struct in the queue */
+static unsigned char reply_buf[16];        /* storage for autopolled replies */
+static unsigned char *reply_ptr;      /* next byte in req->data or reply_buf */
+static int reading_reply;        /* store reply in reply_buf else req->reply */
+static int data_index;      /* index of the next byte to send from req->data */
+static int reply_len; /* number of bytes received in reply_buf or req->reply */
+static int status;          /* VIA's ADB status bits captured upon interrupt */
+static int last_status;              /* status bits as at previous interrupt */
+static int srq_asserted;     /* have to poll for the device that asserted it */
+static int command_byte;         /* the most recent command byte transmitted */
+static int autopoll_devs;      /* bits set are device addresses to be polled */
 
-static struct adb_request *current_req;
-static struct adb_request *last_req;
-static struct adb_request *retry_req;
-static unsigned char reply_buf[16];
-static unsigned char *reply_ptr;
-static int reply_len;
-static int reading_reply;
-static int data_index;
-static int first_byte;
-static int prefix_len;
-static int status = ST_IDLE|TREQ;
-static int last_status;
-static int driver_running;
-
-/* debug level 10 required for ADB logging (should be && debug_adb, ideally) */
+/* Sanity check for request queue. Doesn't check for cycles. */
+static int request_is_queued(struct adb_request *req) {
+	struct adb_request *cur;
+	unsigned long flags;
+	local_irq_save(flags);
+	cur = current_req;
+	while (cur) {
+		if (cur == req) {
+			local_irq_restore(flags);
+			return 1;
+		}
+		cur = cur->next;
+	}
+	local_irq_restore(flags);
+	return 0;
+}
 
 /* Check for MacII style ADB */
 static int macii_probe(void)
@@ -147,15 +158,16 @@
 	local_irq_save(flags);
 	
 	err = macii_init_via();
-	if (err) return err;
+	if (err) goto out;
 
 	err = request_irq(IRQ_MAC_ADB, macii_interrupt, IRQ_FLG_LOCK, "ADB",
 			  macii_interrupt);
-	if (err) return err;
+	if (err) goto out;
 
 	macii_state = idle;
+out:
 	local_irq_restore(flags);
-	return 0;
+	return err;
 }
 
 /* initialize the hardware */	
@@ -163,12 +175,12 @@
 {
 	unsigned char x;
 
-	/* Set the lines up. We want TREQ as input TACK|TIP as output */
-	via[DIRB] = (via[DIRB] | TACK | TIP) & ~TREQ;
+	/* We want CTLR_IRQ as input and ST_EVEN | ST_ODD as output lines. */
+	via[DIRB] = (via[DIRB] | ST_EVEN | ST_ODD) & ~CTLR_IRQ;
 
 	/* Set up state: idle */
 	via[B] |= ST_IDLE;
-	last_status = via[B] & (ST_MASK|TREQ);
+	last_status = via[B] & (ST_MASK|CTLR_IRQ);
 
 	/* Shift register on input */
 	via[ACR] = (via[ACR] & ~SR_CTRL) | SR_EXT;
@@ -179,81 +191,72 @@
 	return 0;
 }
 
-/* Send an ADB poll (Talk Register 0 command, tagged on the front of the request queue) */
+/* Send an ADB poll (Talk Register 0 command prepended to the request queue) */
 static void macii_queue_poll(void)
 {
-	static int device = 0;
-	static int in_poll=0;
+	/* No point polling the active device as it will never assert SRQ, so
+	 * poll the next device in the autopoll list. This could leave us
+	 * stuck in a polling loop if an unprobed device is asserting SRQ.
+	 * In theory, that could only happen if a device was plugged in after
+	 * probing started. Unplugging it again will break the cycle.
+	 * (Simply polling the next higher device often ends up polling almost
+	 * every device (after wrapping around), which takes too long.)
+	 */
+	int device_mask;
+	int next_device;
 	static struct adb_request req;
-	unsigned long flags;
-	
-	if (in_poll) printk("macii_queue_poll: double poll!\n");
 
-	in_poll++;
-	if (++device > 15) device = 1;
+	if (!autopoll_devs) return;
 
-	adb_request(&req, NULL, ADBREQ_REPLY|ADBREQ_NOSEND, 1,
-		    ADB_READREG(device, 0));
+	device_mask = (1 << (((command_byte & 0xF0) >> 4) + 1)) - 1;
+	if (autopoll_devs & ~device_mask)
+		next_device = ffs(autopoll_devs & ~device_mask) - 1;
+	else
+		next_device = ffs(autopoll_devs) - 1;
 
-	local_irq_save(flags);
+	BUG_ON(request_is_queued(&req));
 
+	adb_request(&req, NULL, ADBREQ_NOSEND, 1,
+	            ADB_READREG(next_device, 0));
+
+	req.sent = 0;
+	req.complete = 0;
+	req.reply_len = 0;
 	req.next = current_req;
-	current_req = &req;
-
-	local_irq_restore(flags);
-	macii_start();
-	in_poll--;
-}
-
-/* Send an ADB retransmit (Talk, appended to the request queue) */
-static void macii_retransmit(int device)
-{
-	static int in_retransmit = 0;
-	static struct adb_request rt;
-	unsigned long flags;
-	
-	if (in_retransmit) printk("macii_retransmit: double retransmit!\n");
-
-	in_retransmit++;
-
-	adb_request(&rt, NULL, ADBREQ_REPLY|ADBREQ_NOSEND, 1,
-		    ADB_READREG(device, 0));
-
-	local_irq_save(flags);
 
 	if (current_req != NULL) {
-		last_req->next = &rt;
-		last_req = &rt;
+		current_req = &req;
 	} else {
-		current_req = &rt;
-		last_req = &rt;
+		current_req = &req;
+		last_req = &req;
 	}
-
-	if (macii_state == idle) macii_start();
-
-	local_irq_restore(flags);
-	in_retransmit--;
 }
 
 /* Send an ADB request; if sync, poll out the reply 'till it's done */
 static int macii_send_request(struct adb_request *req, int sync)
 {
-	int i;
-
-	i = macii_write(req);
-	if (i) return i;
-
-	if (sync) {
-		while (!req->complete) macii_poll();
-	}
-	return 0;
-}
-
-/* Send an ADB request */
-static int macii_write(struct adb_request *req)
-{
+	int err;
 	unsigned long flags;
 
+	BUG_ON(request_is_queued(req));
+
+	local_irq_save(flags);
+	err = macii_write(req);
+	local_irq_restore(flags);
+
+	if (!err && sync) {
+		while (!req->complete) {
+			macii_poll();
+		}
+		BUG_ON(request_is_queued(req));
+	}
+
+	return err;
+}
+
+/* Send an ADB request (append to request queue) */
+static int macii_write(struct adb_request *req)
+{
 	if (req->nbytes < 2 || req->data[0] != ADB_PACKET || req->nbytes > 15) {
 		req->complete = 1;
 		return -EINVAL;
@@ -264,8 +267,6 @@
 	req->complete = 0;
 	req->reply_len = 0;
 
-	local_irq_save(flags);
-
 	if (current_req != NULL) {
 		last_req->next = req;
 		last_req = req;
@@ -274,28 +275,52 @@
 		last_req = req;
 		if (macii_state == idle) macii_start();
 	}
-
-	local_irq_restore(flags);
 	return 0;
 }
 
 /* Start auto-polling */
 static int macii_autopoll(int devs)
 {
-	/* Just ping a random default address */
-	if (!(current_req || retry_req))
-		macii_retransmit( (last_active < 16 && last_active > 0) ? last_active : 3);
-	return 0;
+	static struct adb_request req;
+	unsigned long flags;
+	int err = 0;
+
+	/* bit 1 == device 1, and so on. */
+	autopoll_devs = devs & 0xFFFE;
+
+	if (!autopoll_devs) return 0;
+
+	local_irq_save(flags);
+
+	if (current_req == NULL) {
+		/* Send a Talk Reg 0. The controller will repeatedly transmit
+		 * this as long as it is idle.
+		 */
+		adb_request(&req, NULL, ADBREQ_NOSEND, 1,
+		            ADB_READREG(ffs(autopoll_devs) - 1, 0));
+		err = macii_write(&req);
+	}
+
+	local_irq_restore(flags);
+	return err;
+}
+
+static inline int need_autopoll(void) {
+	/* Was the last command Talk Reg 0
+	 * and is the target on the autopoll list?
+	 */
+	if ((command_byte & 0x0F) == 0x0C &&
+	    ((1 << ((command_byte & 0xF0) >> 4)) & autopoll_devs))
+		return 0;
+	return 1;
 }
 
 /* Prod the chip without interrupts */
 static void macii_poll(void)
 {
-	unsigned long flags;
-
-	local_irq_save(flags);
-	if (via[IFR] & SR_INT) macii_interrupt(0, NULL);
-	local_irq_restore(flags);
+	disable_irq(IRQ_MAC_ADB);
+	macii_interrupt(0, NULL);
+	enable_irq(IRQ_MAC_ADB);
 }
 
 /* Reset the bus */
@@ -303,73 +328,34 @@
 {
 	static struct adb_request req;
 	
+	if (request_is_queued(&req))
+		return 0;
+
 	/* Command = 0, Address = ignored */
 	adb_request(&req, NULL, 0, 1, ADB_BUSRESET);
 
+	/* Don't want any more requests during the Global Reset low time. */
+	udelay(3000);
+
 	return 0;
 }
 
 /* Start sending ADB packet */
 static void macii_start(void)
 {
-	unsigned long flags;
 	struct adb_request *req;
 
 	req = current_req;
-	if (!req) return;
-	
-	/* assert macii_state == idle */
-	if (macii_state != idle) {
-		printk("macii_start: called while driver busy (%p %x %x)!\n",
-			req, macii_state, (uint) via1[B] & (ST_MASK|TREQ));
-		return;
-	}
 
-	local_irq_save(flags);
-	
-	/* 
-	 * IRQ signaled ?? (means ADB controller wants to send, or might 
-	 * be end of packet if we were reading)
-	 */
-#if 0 /* FIXME: This is broke broke broke, for some reason */
-	if ((via[B] & TREQ) == 0) {
-		printk("macii_start: weird poll stuff. huh?\n");
-		/*
-		 *	FIXME - we need to restart this on a timer
-		 *	or a collision at boot hangs us.
-		 *	Never set macii_state to idle here, or macii_start 
-		 *	won't be called again from send_request!
-		 *	(need to re-check other cases ...)
-		 */
-		/*
-		 * if the interrupt handler set the need_poll
-		 * flag, it's hopefully a SRQ poll or re-Talk
-		 * so we try to send here anyway
-		 */
-		if (!need_poll) {
-			if (console_loglevel == 10)
-				printk("macii_start: device busy - retry %p state %d status %x!\n", 
-					req, macii_state,
-					(uint) via[B] & (ST_MASK|TREQ));
-			retry_req = req;
-			/* set ADB status here ? */
-			local_irq_restore(flags);
-			return;
-		} else {
-			need_poll = 0;
-		}
-	}
-#endif
-	/*
-	 * Another retry pending? (sanity check)
-	 */
-	if (retry_req) {
-		retry_req = NULL;
-	}
+	BUG_ON(req == NULL);
 
-	/* Now send it. Be careful though, that first byte of the request */
-	/* is actually ADB_PACKET; the real data begins at index 1!	  */
-	
+	BUG_ON(macii_state != idle);
+
+	/* Now send it. Be careful though, that first byte of the request
+	 * is actually ADB_PACKET; the real data begins at index 1!
+	 * And req->nbytes is the number of bytes of real data plus one.
+	 */
+
 	/* store command byte */
 	command_byte = req->data[1];
 	/* Output mode */
@@ -381,115 +367,97 @@
 
 	macii_state = sending;
 	data_index = 2;
-
-	local_irq_restore(flags);
 }
 
 /*
- * The notorious ADB interrupt handler - does all of the protocol handling, 
- * except for starting new send operations. Relies heavily on the ADB 
- * controller sending and receiving data, thereby generating SR interrupts
- * for us. This means there has to be always activity on the ADB bus, otherwise
- * the whole process dies and has to be re-kicked by sending TALK requests ...
- * CUDA-based Macs seem to solve this with the autopoll option, for MacII-type
- * ADB the problem isn't solved yet (retransmit of the latest active TALK seems
- * a good choice; either on timeout or on a timer interrupt).
+ * The notorious ADB interrupt handler - does all of the protocol handling.
+ * Relies on the ADB controller sending and receiving data, thereby
+ * generating shift register interrupts (SR_INT) for us. This means there has
+ * to be activity on the ADB bus. The chip will poll to achieve this.
  *
  * The basic ADB state machine was left unchanged from the original MacII code
  * by Alan Cox, which was based on the CUDA driver for PowerMac. 
- * The syntax of the ADB status lines seems to be totally different on MacII, 
- * though. MacII uses the states Command -> Even -> Odd -> Even ->...-> Idle for
- * sending, and Idle -> Even -> Odd -> Even ->...-> Idle for receiving. Start 
- * and end of a receive packet are signaled by asserting /IRQ on the interrupt
- * line. Timeouts are signaled by a sequence of 4 0xFF, with /IRQ asserted on 
- * every other byte. SRQ is probably signaled by 3 or more 0xFF tacked on the 
- * end of a packet. (Thanks to Guido Koerber for eavesdropping on the ADB 
- * protocol with a logic analyzer!!)
- *
- * Note: As of 21/10/97, the MacII ADB part works including timeout detection
- * and retransmit (Talk to the last active device).
+ * The syntax of the ADB status lines is totally different on MacII,
+ * though. MacII uses the states Command -> Even -> Odd -> Even ->...-> Idle
+ * for sending and Idle -> Even -> Odd -> Even ->...-> Idle for receiving.
+ * Start and end of a receive packet are signalled by asserting /IRQ on the
+ * interrupt line (/IRQ means the CTLR_IRQ bit in port B; not to be confused
+ * with the VIA shift register interrupt. /IRQ never actually interrupts the
+ * processor, it's just an ordinary input.)
  */
 static irqreturn_t macii_interrupt(int irq, void *arg)
 {
-	int x, adbdir;
-	unsigned long flags;
+	int x;
+	static int entered;
 	struct adb_request *req;
 
-	last_status = status;
-
-	/* prevent races due to SCSI enabling ints */
-	local_irq_save(flags);
-
-	if (driver_running) {
-		local_irq_restore(flags);
-		return IRQ_NONE;
+	if (!arg) {
+		/* Clear the SR IRQ flag when polling. */
+		if (via[IFR] & SR_INT)
+			via[IFR] = SR_INT;
+		else
+			return IRQ_NONE;
 	}
 
-	driver_running = 1;
-	
-	status = via[B] & (ST_MASK|TREQ);
-	adbdir = via[ACR] & SR_OUT;
+	BUG_ON(entered++);
+
+	last_status = status;
+	status = via[B] & (ST_MASK|CTLR_IRQ);
 
 	switch (macii_state) {
 		case idle:
+			if (reading_reply) {
+				reply_ptr = current_req->reply;
+			} else {
+				BUG_ON(current_req != NULL);
+				reply_ptr = reply_buf;
+			}
+
 			x = via[SR];
-			first_byte = x;
+
+			if ((status & CTLR_IRQ) && (x == 0xFF)) {
+				/* Bus timeout without SRQ sequence:
+				 *     data is "FF" while CTLR_IRQ is "H"
+				 */
+				reply_len = 0;
+				srq_asserted = 0;
+				macii_state = read_done;
+			} else {
+				macii_state = reading;
+				*reply_ptr = x;
+				reply_len = 1;
+			}
+
 			/* set ADB state = even for first data byte */
 			via[B] = (via[B] & ~ST_MASK) | ST_EVEN;
-
-			reply_buf[0] = first_byte; /* was command_byte?? */
-			reply_ptr = reply_buf + 1;
-			reply_len = 1;
-			prefix_len = 1;
-			reading_reply = 0;
-			
-			macii_state = reading;
-			break;
-
-		case awaiting_reply:
-			/* handshake etc. for II ?? */
-			x = via[SR];
-			first_byte = x;
-			/* set ADB state = even for first data byte */
-			via[B] = (via[B] & ~ST_MASK) | ST_EVEN;
-
-			current_req->reply[0] = first_byte;
-			reply_ptr = current_req->reply + 1;
-			reply_len = 1;
-			prefix_len = 1;
-			reading_reply = 1;
-
-			macii_state = reading;			
 			break;
 
 		case sending:
 			req = current_req;
 			if (data_index >= req->nbytes) {
-				/* print an error message if a listen command has no data */
-				if (((command_byte & 0x0C) == 0x08)
-				 /* && (console_loglevel == 10) */
-				    && (data_index == 2))
-					printk("MacII ADB: listen command with no data: %x!\n", 
-						command_byte);
-				/* reset to shift in */
-				via[ACR] &= ~SR_OUT;
-				x = via[SR];
-				/* set ADB state idle - might get SRQ */
-				via[B] = (via[B] & ~ST_MASK) | ST_IDLE;
-
 				req->sent = 1;
+				macii_state = idle;
 
 				if (req->reply_expected) {
-					macii_state = awaiting_reply;
+					reading_reply = 1;
 				} else {
 					req->complete = 1;
 					current_req = req->next;
 					if (req->done) (*req->done)(req);
-					macii_state = idle;
-					if (current_req || retry_req)
+
+					if (current_req)
 						macii_start();
 					else
-						macii_retransmit((command_byte & 0xF0) >> 4);
+						if (need_autopoll())
+							macii_autopoll(autopoll_devs);
+				}
+
+				if (macii_state == idle) {
+					/* reset to shift in */
+					via[ACR] &= ~SR_OUT;
+					x = via[SR];
+					/* set ADB state idle - might get SRQ */
+					via[B] = (via[B] & ~ST_MASK) | ST_IDLE;
 				}
 			} else {
 				via[SR] = req->data[data_index++];
@@ -505,147 +473,79 @@
 			break;
 
 		case reading:
+			x = via[SR];
+			BUG_ON((status & ST_MASK) == ST_CMD ||
+			       (status & ST_MASK) == ST_IDLE);
 
-			/* timeout / SRQ handling for II hw */
-			if( (first_byte == 0xFF && (reply_len-prefix_len)==2 
-			     && memcmp(reply_ptr-2,"\xFF\xFF",2)==0) || 
-			    ((reply_len-prefix_len)==3 
-			     && memcmp(reply_ptr-3,"\xFF\xFF\xFF",3)==0))
-			{
-				/*
-				 * possible timeout (in fact, most probably a 
-				 * timeout, since SRQ can't be signaled without
-				 * transfer on the bus).
-				 * The last three bytes seen were FF, together 
-				 * with the starting byte (in case we started
-				 * on 'idle' or 'awaiting_reply') this probably
-				 * makes four. So this is mostl likely #5!
-				 * The timeout signal is a pattern 1 0 1 0 0..
-				 * on /INT, meaning we missed it :-(
-				 */
-				x = via[SR];
-				if (x != 0xFF) printk("MacII ADB: mistaken timeout/SRQ!\n");
+			/* Bus timeout with SRQ sequence:
+			 *     data is "XX FF"      while CTLR_IRQ is "L L"
+			 * End of packet without SRQ sequence:
+			 *     data is "XX...YY 00" while CTLR_IRQ is "L...H L"
+			 * End of packet SRQ sequence:
+			 *     data is "XX...YY 00" while CTLR_IRQ is "L...L L"
+			 * (where XX is the first response byte and
+			 * YY is the last byte of valid response data.)
+			 */
 
-				if ((status & TREQ) == (last_status & TREQ)) {
-					/* Not a timeout. Unsolicited SRQ? weird. */
-					/* Terminate the SRQ packet and poll */
-					need_poll = 1;
+			srq_asserted = 0;
+			if (!(status & CTLR_IRQ)) {
+				if (x == 0xFF) {
+					if (!(last_status & CTLR_IRQ)) {
+						macii_state = read_done;
+						reply_len = 0;
+						srq_asserted = 1;
+					}
+				} else if (x == 0x00) {
+					macii_state = read_done;
+					if (!(last_status & CTLR_IRQ))
+						srq_asserted = 1;
 				}
-				/* There's no packet to get, so reply is blank */
-				via[B] ^= ST_MASK;
-				reply_ptr -= (reply_len-prefix_len);
-				reply_len = prefix_len;
-				macii_state = read_done;
-				break;
-			} /* end timeout / SRQ handling for II hw. */
+			}
 
-			if((reply_len-prefix_len)>3
-				&& memcmp(reply_ptr-3,"\xFF\xFF\xFF",3)==0)
-			{
-				/* SRQ tacked on data packet */
-				/* Terminate the packet (SRQ never ends) */
-				x = via[SR];
-				macii_state = read_done;
-				reply_len -= 3;
-				reply_ptr -= 3;
-				need_poll = 1;
-				/* need to continue; next byte not seen else */
-			} else {
-				/* Sanity check */
-				if (reply_len > 15) reply_len = 0;
-				/* read byte */
-				x = via[SR];
-				*reply_ptr = x;
+			if (macii_state == reading) {
+				BUG_ON(reply_len > 15);
 				reply_ptr++;
+				*reply_ptr = x;
 				reply_len++;
 			}
-			/* The usual handshake ... */
 
-			/*
-			 * NetBSD hints that the next to last byte 
-			 * is sent with IRQ !! 
-			 * Guido found out it's the last one (0x0),
-			 * but IRQ should be asserted already.
-			 * Problem with timeout detection: First
-			 * transition to /IRQ might be second 
-			 * byte of timeout packet! 
-			 * Timeouts are signaled by 4x FF.
-			 */
-			if (((status & TREQ) == 0) && (x == 0x00)) { /* != 0xFF */
-				/* invert state bits, toggle ODD/EVEN */
-				via[B] ^= ST_MASK;
-
-				/* adjust packet length */
-				reply_len--;
-				reply_ptr--;
-				macii_state = read_done;
-			} else {
-				/* not caught: ST_CMD */
-				/* required for re-entry 'reading'! */
-				if ((status & ST_MASK) == ST_IDLE) {
-					/* (in)sanity check - set even */
-					via[B] = (via[B] & ~ST_MASK) | ST_EVEN;
-				} else {
-					/* invert state bits */
-					via[B] ^= ST_MASK;
-				}
-			}
+			/* invert state bits, toggle ODD/EVEN */
+			via[B] ^= ST_MASK;
 			break;
 
 		case read_done:
 			x = via[SR];
+
 			if (reading_reply) {
+				reading_reply = 0;
 				req = current_req;
-				req->reply_len = reply_ptr - req->reply;
+				req->reply_len = reply_len;
 				req->complete = 1;
 				current_req = req->next;
 				if (req->done) (*req->done)(req);
-			} else {
-				adb_input(reply_buf, reply_ptr - reply_buf, 0);
-			}
+			} else if (reply_len && autopoll_devs)
+				adb_input(reply_buf, reply_len, 0);
 
-			/*
-			 * remember this device ID; it's the latest we got a 
-			 * reply from!
-			 */
-			last_reply = command_byte;
-			last_active = (command_byte & 0xF0) >> 4;
+			macii_state = idle;
 
 			/* SRQ seen before, initiate poll now */
-			if (need_poll) {
-				macii_state = idle;
+			if (srq_asserted)
 				macii_queue_poll();
-				need_poll = 0;
-				break;
-			}
-			
-			/* set ADB state to idle */
-			via[B] = (via[B] & ~ST_MASK) | ST_IDLE;
-			
-			/* /IRQ seen, so the ADB controller has data for us */
-			if ((via[B] & TREQ) != 0) {
-				macii_state = reading;
 
-				reply_buf[0] = command_byte;
-				reply_ptr = reply_buf + 1;
-				reply_len = 1;
-				prefix_len = 1;
-				reading_reply = 0;
-			} else {
-				/* no IRQ, send next packet or wait */
-				macii_state = idle;
-				if (current_req)
-					macii_start();
-				else
-					macii_retransmit(last_active);
-			}
+			if (current_req)
+				macii_start();
+			else
+				if (need_autopoll())
+					macii_autopoll(autopoll_devs);
+
+			if (macii_state == idle)
+				via[B] = (via[B] & ~ST_MASK) | ST_IDLE;
 			break;
 
 		default:
 		break;
 	}
-	/* reset mutex and interrupts */
-	driver_running = 0;
-	local_irq_restore(flags);
+
+	entered--;
 	return IRQ_HANDLED;
 }
diff --git a/drivers/macintosh/via-pmu68k.c b/drivers/macintosh/via-pmu68k.c
index 356c721..dfdf11c 100644
--- a/drivers/macintosh/via-pmu68k.c
+++ b/drivers/macintosh/via-pmu68k.c
@@ -111,7 +111,6 @@
 static int pmu_autopoll(int devs);
 void pmu_poll(void);
 static int pmu_reset_bus(void);
-static int pmu_queue_request(struct adb_request *req);
 
 static void pmu_start(void);
 static void send_byte(int x);
@@ -475,7 +474,7 @@
 	return pmu_queue_request(req);
 }
 
-static int 
+int
 pmu_queue_request(struct adb_request *req)
 {
 	unsigned long flags;
diff --git a/drivers/media/dvb/b2c2/flexcop-i2c.c b/drivers/media/dvb/b2c2/flexcop-i2c.c
index 5347a40..02a0ea6 100644
--- a/drivers/media/dvb/b2c2/flexcop-i2c.c
+++ b/drivers/media/dvb/b2c2/flexcop-i2c.c
@@ -183,7 +183,8 @@
 	mutex_init(&fc->i2c_mutex);
 
 	memset(&fc->i2c_adap, 0, sizeof(struct i2c_adapter));
-	strncpy(fc->i2c_adap.name, "B2C2 FlexCop device",I2C_NAME_SIZE);
+	strncpy(fc->i2c_adap.name, "B2C2 FlexCop device",
+		sizeof(fc->i2c_adap.name));
 
 	i2c_set_adapdata(&fc->i2c_adap,fc);
 
diff --git a/drivers/media/dvb/cinergyT2/cinergyT2.c b/drivers/media/dvb/cinergyT2/cinergyT2.c
index a6cbbdd..34d7abc 100644
--- a/drivers/media/dvb/cinergyT2/cinergyT2.c
+++ b/drivers/media/dvb/cinergyT2/cinergyT2.c
@@ -26,11 +26,11 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/usb.h>
-#include <linux/pci.h>
 #include <linux/input.h>
 #include <linux/dvb/frontend.h>
 #include <linux/mutex.h>
 #include <linux/mm.h>
+#include <asm/io.h>
 
 #include "dmxdev.h"
 #include "dvb_demux.h"
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c b/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c
index 70df31b..088b6de 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c
@@ -19,7 +19,7 @@
 		return -EINVAL;
 	}
 
-	strncpy(d->i2c_adap.name,d->desc->name,I2C_NAME_SIZE);
+	strncpy(d->i2c_adap.name, d->desc->name, sizeof(d->i2c_adap.name));
 #ifdef I2C_ADAP_CLASS_TV_DIGITAL
 	d->i2c_adap.class = I2C_ADAP_CLASS_TV_DIGITAL,
 #else
diff --git a/drivers/media/dvb/frontends/dibx000_common.c b/drivers/media/dvb/frontends/dibx000_common.c
index a18c8f4..315e09e 100644
--- a/drivers/media/dvb/frontends/dibx000_common.c
+++ b/drivers/media/dvb/frontends/dibx000_common.c
@@ -105,9 +105,9 @@
 }
 EXPORT_SYMBOL(dibx000_get_i2c_adapter);
 
-static int i2c_adapter_init(struct i2c_adapter *i2c_adap, struct i2c_algorithm *algo, const char name[I2C_NAME_SIZE], struct dibx000_i2c_master *mst)
+static int i2c_adapter_init(struct i2c_adapter *i2c_adap, struct i2c_algorithm *algo, const char *name, struct dibx000_i2c_master *mst)
 {
-	strncpy(i2c_adap->name, name, I2C_NAME_SIZE);
+	strncpy(i2c_adap->name, name, sizeof(i2c_adap->name));
 	i2c_adap->class     = I2C_CLASS_TV_DIGITAL,
 	i2c_adap->algo      = algo;
 	i2c_adap->algo_data = NULL;
diff --git a/drivers/media/video/adv7170.c b/drivers/media/video/adv7170.c
index 2aa9ce9..823cd6c 100644
--- a/drivers/media/video/adv7170.c
+++ b/drivers/media/video/adv7170.c
@@ -37,7 +37,6 @@
 #include <linux/major.h>
 #include <linux/slab.h>
 #include <linux/mm.h>
-#include <linux/pci.h>
 #include <linux/signal.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
diff --git a/drivers/media/video/adv7175.c b/drivers/media/video/adv7175.c
index a3246a2..05c7820 100644
--- a/drivers/media/video/adv7175.c
+++ b/drivers/media/video/adv7175.c
@@ -33,7 +33,6 @@
 #include <linux/major.h>
 #include <linux/slab.h>
 #include <linux/mm.h>
-#include <linux/pci.h>
 #include <linux/signal.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
diff --git a/drivers/media/video/bt819.c b/drivers/media/video/bt819.c
index 6867386..59a4360 100644
--- a/drivers/media/video/bt819.c
+++ b/drivers/media/video/bt819.c
@@ -37,7 +37,6 @@
 #include <linux/major.h>
 #include <linux/slab.h>
 #include <linux/mm.h>
-#include <linux/pci.h>
 #include <linux/signal.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
diff --git a/drivers/media/video/bt856.c b/drivers/media/video/bt856.c
index 42e2299..853b1a3 100644
--- a/drivers/media/video/bt856.c
+++ b/drivers/media/video/bt856.c
@@ -37,7 +37,6 @@
 #include <linux/major.h>
 #include <linux/slab.h>
 #include <linux/mm.h>
-#include <linux/pci.h>
 #include <linux/signal.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
diff --git a/drivers/media/video/bt866.c b/drivers/media/video/bt866.c
index 772fd52..2e4cf1e 100644
--- a/drivers/media/video/bt866.c
+++ b/drivers/media/video/bt866.c
@@ -37,7 +37,6 @@
 #include <linux/major.h>
 #include <linux/slab.h>
 #include <linux/mm.h>
-#include <linux/pci.h>
 #include <linux/signal.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
diff --git a/drivers/media/video/cx2341x.c b/drivers/media/video/cx2341x.c
index 88dbddd..d73c86a 100644
--- a/drivers/media/video/cx2341x.c
+++ b/drivers/media/video/cx2341x.c
@@ -26,7 +26,6 @@
 #include <linux/init.h>
 #include <linux/types.h>
 #include <linux/videodev2.h>
-#include <linux/i2c.h>
 
 #include <media/tuner.h>
 #include <media/cx2341x.h>
diff --git a/drivers/media/video/cx88/cx88-tvaudio.c b/drivers/media/video/cx88/cx88-tvaudio.c
index 97ef421..e627062 100644
--- a/drivers/media/video/cx88/cx88-tvaudio.c
+++ b/drivers/media/video/cx88/cx88-tvaudio.c
@@ -43,7 +43,6 @@
 #include <linux/slab.h>
 #include <linux/mm.h>
 #include <linux/poll.h>
-#include <linux/pci.h>
 #include <linux/signal.h>
 #include <linux/ioport.h>
 #include <linux/types.h>
diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c
index ed882eb..418ea8b 100644
--- a/drivers/media/video/em28xx/em28xx-cards.c
+++ b/drivers/media/video/em28xx/em28xx-cards.c
@@ -23,7 +23,6 @@
 
 #include <linux/init.h>
 #include <linux/module.h>
-#include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/i2c.h>
 #include <linux/usb.h>
diff --git a/drivers/media/video/ovcamchip/ovcamchip_priv.h b/drivers/media/video/ovcamchip/ovcamchip_priv.h
index 1231335..50c7763 100644
--- a/drivers/media/video/ovcamchip/ovcamchip_priv.h
+++ b/drivers/media/video/ovcamchip/ovcamchip_priv.h
@@ -15,6 +15,7 @@
 #ifndef __LINUX_OVCAMCHIP_PRIV_H
 #define __LINUX_OVCAMCHIP_PRIV_H
 
+#include <linux/i2c.h>
 #include <media/ovcamchip.h>
 
 #ifdef DEBUG
diff --git a/drivers/media/video/saa7111.c b/drivers/media/video/saa7111.c
index 44dc747..74839f9 100644
--- a/drivers/media/video/saa7111.c
+++ b/drivers/media/video/saa7111.c
@@ -36,7 +36,6 @@
 #include <linux/major.h>
 #include <linux/slab.h>
 #include <linux/mm.h>
-#include <linux/pci.h>
 #include <linux/signal.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
diff --git a/drivers/media/video/saa7114.c b/drivers/media/video/saa7114.c
index 2ce3321..87c3144 100644
--- a/drivers/media/video/saa7114.c
+++ b/drivers/media/video/saa7114.c
@@ -39,7 +39,6 @@
 #include <linux/slab.h>
 
 #include <linux/mm.h>
-#include <linux/pci.h>
 #include <linux/signal.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
diff --git a/drivers/media/video/saa711x.c b/drivers/media/video/saa711x.c
index 269d711..80bf911 100644
--- a/drivers/media/video/saa711x.c
+++ b/drivers/media/video/saa711x.c
@@ -30,7 +30,6 @@
 #include <linux/major.h>
 #include <linux/slab.h>
 #include <linux/mm.h>
-#include <linux/pci.h>
 #include <linux/signal.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
diff --git a/drivers/media/video/saa7185.c b/drivers/media/video/saa7185.c
index e0fdb1a..339592e 100644
--- a/drivers/media/video/saa7185.c
+++ b/drivers/media/video/saa7185.c
@@ -33,7 +33,6 @@
 #include <linux/major.h>
 #include <linux/slab.h>
 #include <linux/mm.h>
-#include <linux/pci.h>
 #include <linux/signal.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
diff --git a/drivers/media/video/usbvision/usbvision-cards.c b/drivers/media/video/usbvision/usbvision-cards.c
index 13f69fe..51ab265 100644
--- a/drivers/media/video/usbvision/usbvision-cards.c
+++ b/drivers/media/video/usbvision/usbvision-cards.c
@@ -24,7 +24,6 @@
 
 
 #include <linux/list.h>
-#include <linux/i2c.h>
 #include <media/v4l2-dev.h>
 #include <media/tuner.h>
 #include "usbvision.h"
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c
index 083acfd..97471af 100644
--- a/drivers/message/fusion/mptbase.c
+++ b/drivers/message/fusion/mptbase.c
@@ -1531,6 +1531,7 @@
 	MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
 	u32 device_state = pdev->current_state;
 	int recovery_state;
+	int err;
 
 	printk(MYIOC_s_INFO_FMT
 	"pci-resume: pdev=0x%p, slot=%s, Previous operating state [D%d]\n",
@@ -1538,7 +1539,9 @@
 
 	pci_set_power_state(pdev, 0);
 	pci_restore_state(pdev);
-	pci_enable_device(pdev);
+	err = pci_enable_device(pdev);
+	if (err)
+		return err;
 
 	/* enable interrupts */
 	CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM);
@@ -4739,12 +4742,8 @@
 }
 
 /**
- * mpt_inactive_raid_list_free
- *
- * This clears this link list.
- *
- * @ioc - pointer to per adapter structure
- *
+ * mpt_inactive_raid_list_free - This clears this link list.
+ * @ioc : pointer to per adapter structure
  **/
 static void
 mpt_inactive_raid_list_free(MPT_ADAPTER *ioc)
@@ -4764,15 +4763,11 @@
 }
 
 /**
- * mpt_inactive_raid_volumes
+ * mpt_inactive_raid_volumes - sets up link list of phy_disk_nums for devices belonging in an inactive volume
  *
- * This sets up link list of phy_disk_nums for devices belonging in an inactive volume
- *
- * @ioc - pointer to per adapter structure
- * @channel - volume channel
- * @id - volume target id
- *
- *
+ * @ioc : pointer to per adapter structure
+ * @channel : volume channel
+ * @id : volume target id
  **/
 static void
 mpt_inactive_raid_volumes(MPT_ADAPTER *ioc, u8 channel, u8 id)
@@ -6663,7 +6658,7 @@
 /**
  *	mpt_iocstatus_info_config - IOCSTATUS information for config pages
  *	@ioc: Pointer to MPT_ADAPTER structure
- *	ioc_status: U32 IOCStatus word from IOC
+ *	@ioc_status: U32 IOCStatus word from IOC
  *	@mf: Pointer to MPT request frame
  *
  *	Refer to lsi/mpi.h.
diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h
index e3a3927..d25d3be 100644
--- a/drivers/message/fusion/mptbase.h
+++ b/drivers/message/fusion/mptbase.h
@@ -994,6 +994,7 @@
 	int			  scandv_wait_done;
 	long			  last_queue_full;
 	u16			  tm_iocstatus;
+	u16			  spi_pending;
 	struct list_head	  target_reset_list;
 } MPT_SCSI_HOST;
 
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c
index 2a3e9e66..fa0f776 100644
--- a/drivers/message/fusion/mptscsih.c
+++ b/drivers/message/fusion/mptscsih.c
@@ -819,10 +819,7 @@
 			sc->resid=0;
 		case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR:	/* 0x0040 */
 		case MPI_IOCSTATUS_SUCCESS:			/* 0x0000 */
-			if (scsi_status == MPI_SCSI_STATUS_BUSY)
-				sc->result = (DID_BUS_BUSY << 16) | scsi_status;
-			else
-				sc->result = (DID_OK << 16) | scsi_status;
+			sc->result = (DID_OK << 16) | scsi_status;
 			if (scsi_state == 0) {
 				;
 			} else if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) {
@@ -1188,20 +1185,7 @@
 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;
-
-	hd = (MPT_SCSI_HOST *)host->hostdata;
-	if(!hd)
-		return 0;
-
-	return 0;
+	return mpt_resume(pdev);
 }
 
 #endif
@@ -1537,21 +1521,23 @@
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /**
  *	mptscsih_TMHandler - Generic handler for SCSI Task Management.
- *	Fall through to mpt_HardResetHandler if: not operational, too many
- *	failed TM requests or handshake failure.
- *
- *	@ioc: Pointer to MPT_ADAPTER structure
+ *	@hd: Pointer to MPT SCSI HOST structure
  *	@type: Task Management type
+ *	@channel: channel number for task management
  *	@id: Logical Target ID for reset (if appropriate)
  *	@lun: Logical Unit for reset (if appropriate)
  *	@ctx2abort: Context for the task to be aborted (if appropriate)
+ *	@timeout: timeout for task management control
+ *
+ *	Fall through to mpt_HardResetHandler if: not operational, too many
+ *	failed TM requests or handshake failure.
  *
  *	Remark: Currently invoked from a non-interrupt thread (_bh).
  *
  *	Remark: With old EH code, at most 1 SCSI TaskMgmt function per IOC
  *	will be active.
  *
- *	Returns 0 for SUCCESS, or FAILED.
+ *	Returns 0 for SUCCESS, or %FAILED.
  **/
 int
 mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout)
@@ -1650,9 +1636,11 @@
  *	mptscsih_IssueTaskMgmt - Generic send Task Management function.
  *	@hd: Pointer to MPT_SCSI_HOST structure
  *	@type: Task Management type
+ *	@channel: channel number for task management
  *	@id: Logical Target ID for reset (if appropriate)
  *	@lun: Logical Unit for reset (if appropriate)
  *	@ctx2abort: Context for the task to be aborted (if appropriate)
+ *	@timeout: timeout for task management control
  *
  *	Remark: _HardResetHandler can be invoked from an interrupt thread (timer)
  *	or a non-interrupt thread.  In the former, must not call schedule().
@@ -2022,6 +2010,7 @@
 /**
  *	mptscsih_tm_wait_for_completion - wait for completion of TM task
  *	@hd: Pointer to MPT host structure.
+ *	@timeout: timeout value
  *
  *	Returns {SUCCESS,FAILED}.
  */
diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c
index 85f21b5..d75f7ff 100644
--- a/drivers/message/fusion/mptspi.c
+++ b/drivers/message/fusion/mptspi.c
@@ -96,14 +96,13 @@
 static int	mptspiInternalCtx = -1; /* Used only for internal commands */
 
 /**
- * 	mptspi_setTargetNegoParms  - Update the target negotiation
- *	parameters based on the the Inquiry data, adapter capabilities,
- *	and NVRAM settings
- *
+ * 	mptspi_setTargetNegoParms  - Update the target negotiation parameters
  *	@hd: Pointer to a SCSI Host Structure
- *	@vtarget: per target private data
+ *	@target: per target private data
  *	@sdev: SCSI device
  *
+ * 	Update the target negotiation parameters based on the the Inquiry
+ *	data, adapter capabilities, and NVRAM settings.
  **/
 static void
 mptspi_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *target,
@@ -234,7 +233,7 @@
 /**
  * 	mptspi_writeIOCPage4  - write IOC Page 4
  *	@hd: Pointer to a SCSI Host Structure
- *	@channel:
+ *	@channel: channel number
  *	@id: write IOC Page4 for this ID & Bus
  *
  *	Return: -EAGAIN if unable to obtain a Message Frame
@@ -446,7 +445,7 @@
 	return 0;
 }
 
-void
+static void
 mptspi_target_destroy(struct scsi_target *starget)
 {
 	if (starget->hostdata)
@@ -677,7 +676,9 @@
 		return;
 	}
 
+	hd->spi_pending |= (1 << sdev->id);
 	spi_dv_device(sdev);
+	hd->spi_pending &= ~(1 << sdev->id);
 
 	if (sdev->channel == 1 &&
 	    mptscsih_quiesce_raid(hd, 0, vtarget->channel, vtarget->id) < 0)
@@ -1203,11 +1204,27 @@
 		container_of(work, struct work_queue_wrapper, work);
 	struct _MPT_SCSI_HOST *hd = wqw->hd;
 	struct scsi_device *sdev;
+	struct scsi_target *starget;
+	struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1;
+	u32 nego;
 
 	kfree(wqw);
 
-	shost_for_each_device(sdev, hd->ioc->sh)
-		mptspi_dv_device(hd, sdev);
+	if (hd->spi_pending) {
+		shost_for_each_device(sdev, hd->ioc->sh) {
+			if  (hd->spi_pending & (1 << sdev->id))
+				continue;
+			starget = scsi_target(sdev);
+			nego = mptspi_getRP(starget);
+			pg1.RequestedParameters = cpu_to_le32(nego);
+			pg1.Reserved = 0;
+			pg1.Configuration = 0;
+			mptspi_write_spi_device_pg1(starget, &pg1);
+		}
+	} else {
+		shost_for_each_device(sdev, hd->ioc->sh)
+			mptspi_dv_device(hd, sdev);
+	}
 }
 
 static void
@@ -1453,6 +1470,7 @@
 	init_waitqueue_head(&hd->scandv_waitq);
 	hd->scandv_wait_done = 0;
 	hd->last_queue_full = 0;
+	hd->spi_pending = 0;
 
 	/* Some versions of the firmware don't support page 0; without
 	 * that we can't get the parameters */
diff --git a/drivers/misc/hdpuftrs/hdpu_cpustate.c b/drivers/misc/hdpuftrs/hdpu_cpustate.c
index ca86f11..276ba3c 100644
--- a/drivers/misc/hdpuftrs/hdpu_cpustate.c
+++ b/drivers/misc/hdpuftrs/hdpu_cpustate.c
@@ -18,7 +18,6 @@
 #include <linux/kernel.h>
 #include <linux/spinlock.h>
 #include <linux/miscdevice.h>
-#include <linux/pci.h>
 #include <linux/proc_fs.h>
 #include <linux/platform_device.h>
 #include <asm/uaccess.h>
diff --git a/drivers/misc/hdpuftrs/hdpu_nexus.c b/drivers/misc/hdpuftrs/hdpu_nexus.c
index 6a51e99..60c8b26 100644
--- a/drivers/misc/hdpuftrs/hdpu_nexus.c
+++ b/drivers/misc/hdpuftrs/hdpu_nexus.c
@@ -18,7 +18,6 @@
 #include <linux/kernel.h>
 #include <linux/proc_fs.h>
 #include <linux/hdpu_features.h>
-#include <linux/pci.h>
 
 #include <linux/platform_device.h>
 
diff --git a/drivers/misc/tifm_7xx1.c b/drivers/misc/tifm_7xx1.c
index bc60e2f..1ba6c08 100644
--- a/drivers/misc/tifm_7xx1.c
+++ b/drivers/misc/tifm_7xx1.c
@@ -11,10 +11,20 @@
 
 #include <linux/tifm.h>
 #include <linux/dma-mapping.h>
-#include <linux/freezer.h>
 
 #define DRIVER_NAME "tifm_7xx1"
-#define DRIVER_VERSION "0.7"
+#define DRIVER_VERSION "0.8"
+
+#define TIFM_IRQ_ENABLE           0x80000000
+#define TIFM_IRQ_SOCKMASK(x)      (x)
+#define TIFM_IRQ_CARDMASK(x)      ((x) << 8)
+#define TIFM_IRQ_FIFOMASK(x)      ((x) << 16)
+#define TIFM_IRQ_SETALL           0xffffffff
+
+static void tifm_7xx1_dummy_eject(struct tifm_adapter *fm,
+				  struct tifm_dev *sock)
+{
+}
 
 static void tifm_7xx1_eject(struct tifm_adapter *fm, struct tifm_dev *sock)
 {
@@ -22,7 +32,7 @@
 
 	spin_lock_irqsave(&fm->lock, flags);
 	fm->socket_change_set |= 1 << sock->socket_id;
-	wake_up_all(&fm->change_set_notify);
+	tifm_queue_work(&fm->media_switcher);
 	spin_unlock_irqrestore(&fm->lock, flags);
 }
 
@@ -30,8 +40,7 @@
 {
 	struct tifm_adapter *fm = dev_id;
 	struct tifm_dev *sock;
-	unsigned int irq_status;
-	unsigned int sock_irq_status, cnt;
+	unsigned int irq_status, cnt;
 
 	spin_lock(&fm->lock);
 	irq_status = readl(fm->addr + FM_INTERRUPT_STATUS);
@@ -45,12 +54,12 @@
 
 		for (cnt = 0; cnt < fm->num_sockets; cnt++) {
 			sock = fm->sockets[cnt];
-			sock_irq_status = (irq_status >> cnt)
-					  & (TIFM_IRQ_FIFOMASK(1)
-					     | TIFM_IRQ_CARDMASK(1));
-
-			if (sock && sock_irq_status)
-				sock->signal_irq(sock, sock_irq_status);
+			if (sock) {
+				if ((irq_status >> cnt) & TIFM_IRQ_FIFOMASK(1))
+					sock->data_event(sock);
+				if ((irq_status >> cnt) & TIFM_IRQ_CARDMASK(1))
+					sock->card_event(sock);
+			}
 		}
 
 		fm->socket_change_set |= irq_status
@@ -58,57 +67,57 @@
 	}
 	writel(irq_status, fm->addr + FM_INTERRUPT_STATUS);
 
-	if (!fm->socket_change_set)
+	if (fm->finish_me)
+		complete_all(fm->finish_me);
+	else if (!fm->socket_change_set)
 		writel(TIFM_IRQ_ENABLE, fm->addr + FM_SET_INTERRUPT_ENABLE);
 	else
-		wake_up_all(&fm->change_set_notify);
+		tifm_queue_work(&fm->media_switcher);
 
 	spin_unlock(&fm->lock);
 	return IRQ_HANDLED;
 }
 
-static tifm_media_id tifm_7xx1_toggle_sock_power(char __iomem *sock_addr,
-						 int is_x2)
+static unsigned char tifm_7xx1_toggle_sock_power(char __iomem *sock_addr)
 {
 	unsigned int s_state;
 	int cnt;
 
 	writel(0x0e00, sock_addr + SOCK_CONTROL);
 
-	for (cnt = 0; cnt < 100; cnt++) {
+	for (cnt = 16; cnt <= 256; cnt <<= 1) {
 		if (!(TIFM_SOCK_STATE_POWERED
 		      & readl(sock_addr + SOCK_PRESENT_STATE)))
 			break;
-		msleep(10);
+
+		msleep(cnt);
 	}
 
 	s_state = readl(sock_addr + SOCK_PRESENT_STATE);
 	if (!(TIFM_SOCK_STATE_OCCUPIED & s_state))
-		return FM_NULL;
+		return 0;
 
-	if (is_x2) {
-		writel((s_state & 7) | 0x0c00, sock_addr + SOCK_CONTROL);
-	} else {
-		// SmartMedia cards need extra 40 msec
-		if (((readl(sock_addr + SOCK_PRESENT_STATE) >> 4) & 7) == 1)
-			msleep(40);
-		writel(readl(sock_addr + SOCK_CONTROL) | TIFM_CTRL_LED,
-		       sock_addr + SOCK_CONTROL);
-		msleep(10);
-		writel((s_state & 0x7) | 0x0c00 | TIFM_CTRL_LED,
-			sock_addr + SOCK_CONTROL);
-	}
+	writel(readl(sock_addr + SOCK_CONTROL) | TIFM_CTRL_LED,
+	       sock_addr + SOCK_CONTROL);
 
-	for (cnt = 0; cnt < 100; cnt++) {
+	/* xd needs some extra time before power on */
+	if (((readl(sock_addr + SOCK_PRESENT_STATE) >> 4) & 7)
+	    == TIFM_TYPE_XD)
+		msleep(40);
+
+	writel((s_state & 7) | 0x0c00, sock_addr + SOCK_CONTROL);
+	/* wait for power to stabilize */
+	msleep(20);
+	for (cnt = 16; cnt <= 256; cnt <<= 1) {
 		if ((TIFM_SOCK_STATE_POWERED
 		     & readl(sock_addr + SOCK_PRESENT_STATE)))
 			break;
-		msleep(10);
+
+		msleep(cnt);
 	}
 
-	if (!is_x2)
-		writel(readl(sock_addr + SOCK_CONTROL) & (~TIFM_CTRL_LED),
-		       sock_addr + SOCK_CONTROL);
+	writel(readl(sock_addr + SOCK_CONTROL) & (~TIFM_CTRL_LED),
+	       sock_addr + SOCK_CONTROL);
 
 	return (readl(sock_addr + SOCK_PRESENT_STATE) >> 4) & 7;
 }
@@ -119,127 +128,77 @@
 	return base_addr + ((sock_num + 1) << 10);
 }
 
-static int tifm_7xx1_switch_media(void *data)
+static void tifm_7xx1_switch_media(struct work_struct *work)
 {
-	struct tifm_adapter *fm = data;
-	unsigned long flags;
-	tifm_media_id media_id;
-	char *card_name = "xx";
-	int cnt, rc;
+	struct tifm_adapter *fm = container_of(work, struct tifm_adapter,
+					       media_switcher);
 	struct tifm_dev *sock;
-	unsigned int socket_change_set;
+	unsigned long flags;
+	unsigned char media_id;
+	unsigned int socket_change_set, cnt;
 
-	while (1) {
-		rc = wait_event_interruptible(fm->change_set_notify,
-					      fm->socket_change_set);
-		if (rc == -ERESTARTSYS)
-			try_to_freeze();
+	spin_lock_irqsave(&fm->lock, flags);
+	socket_change_set = fm->socket_change_set;
+	fm->socket_change_set = 0;
 
-		spin_lock_irqsave(&fm->lock, flags);
-		socket_change_set = fm->socket_change_set;
-		fm->socket_change_set = 0;
+	dev_dbg(fm->cdev.dev, "checking media set %x\n",
+		socket_change_set);
 
-		dev_dbg(fm->dev, "checking media set %x\n",
-			socket_change_set);
+	if (!socket_change_set) {
+		spin_unlock_irqrestore(&fm->lock, flags);
+		return;
+	}
 
-		if (kthread_should_stop())
-			socket_change_set = (1 << fm->num_sockets) - 1;
+	for (cnt = 0; cnt < fm->num_sockets; cnt++) {
+		if (!(socket_change_set & (1 << cnt)))
+			continue;
+		sock = fm->sockets[cnt];
+		if (sock) {
+			printk(KERN_INFO
+			       "%s : demand removing card from socket %u:%u\n",
+			       fm->cdev.class_id, fm->id, cnt);
+			fm->sockets[cnt] = NULL;
+			spin_unlock_irqrestore(&fm->lock, flags);
+			device_unregister(&sock->dev);
+			spin_lock_irqsave(&fm->lock, flags);
+			writel(0x0e00, tifm_7xx1_sock_addr(fm->addr, cnt)
+			       + SOCK_CONTROL);
+		}
+
 		spin_unlock_irqrestore(&fm->lock, flags);
 
-		if (!socket_change_set)
-			continue;
+		media_id = tifm_7xx1_toggle_sock_power(
+				tifm_7xx1_sock_addr(fm->addr, cnt));
 
-		spin_lock_irqsave(&fm->lock, flags);
-		for (cnt = 0; cnt < fm->num_sockets; cnt++) {
-			if (!(socket_change_set & (1 << cnt)))
-				continue;
-			sock = fm->sockets[cnt];
-			if (sock) {
-				printk(KERN_INFO DRIVER_NAME
-				       ": demand removing card from socket %d\n",
-				       cnt);
-				fm->sockets[cnt] = NULL;
-				spin_unlock_irqrestore(&fm->lock, flags);
-				device_unregister(&sock->dev);
+		// tifm_alloc_device will check if media_id is valid
+		sock = tifm_alloc_device(fm, cnt, media_id);
+		if (sock) {
+			sock->addr = tifm_7xx1_sock_addr(fm->addr, cnt);
+
+			if (!device_register(&sock->dev)) {
 				spin_lock_irqsave(&fm->lock, flags);
-				writel(0x0e00,
-				       tifm_7xx1_sock_addr(fm->addr, cnt)
-				       + SOCK_CONTROL);
-			}
-			if (kthread_should_stop())
-				continue;
-
-			spin_unlock_irqrestore(&fm->lock, flags);
-			media_id = tifm_7xx1_toggle_sock_power(
-					tifm_7xx1_sock_addr(fm->addr, cnt),
-					fm->num_sockets == 2);
-			if (media_id) {
-				sock = tifm_alloc_device(fm);
-				if (sock) {
-					sock->addr = tifm_7xx1_sock_addr(fm->addr,
-									 cnt);
-					sock->media_id = media_id;
-					sock->socket_id = cnt;
-					switch (media_id) {
-					case 1:
-						card_name = "xd";
-						break;
-					case 2:
-						card_name = "ms";
-						break;
-					case 3:
-						card_name = "sd";
-						break;
-					default:
-						tifm_free_device(&sock->dev);
-						spin_lock_irqsave(&fm->lock, flags);
-						continue;
-					}
-					snprintf(sock->dev.bus_id, BUS_ID_SIZE,
-						 "tifm_%s%u:%u", card_name,
-						 fm->id, cnt);
-					printk(KERN_INFO DRIVER_NAME
-					       ": %s card detected in socket %d\n",
-					       card_name, cnt);
-					if (!device_register(&sock->dev)) {
-						spin_lock_irqsave(&fm->lock, flags);
-						if (!fm->sockets[cnt]) {
-							fm->sockets[cnt] = sock;
-							sock = NULL;
-						}
-						spin_unlock_irqrestore(&fm->lock, flags);
-					}
-					if (sock)
-						tifm_free_device(&sock->dev);
+				if (!fm->sockets[cnt]) {
+					fm->sockets[cnt] = sock;
+					sock = NULL;
 				}
-				spin_lock_irqsave(&fm->lock, flags);
-			}
-		}
-
-		if (!kthread_should_stop()) {
-			writel(TIFM_IRQ_FIFOMASK(socket_change_set)
-			       | TIFM_IRQ_CARDMASK(socket_change_set),
-			       fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
-			writel(TIFM_IRQ_FIFOMASK(socket_change_set)
-			       | TIFM_IRQ_CARDMASK(socket_change_set),
-			       fm->addr + FM_SET_INTERRUPT_ENABLE);
-			writel(TIFM_IRQ_ENABLE,
-			       fm->addr + FM_SET_INTERRUPT_ENABLE);
-			spin_unlock_irqrestore(&fm->lock, flags);
-		} else {
-			for (cnt = 0; cnt < fm->num_sockets; cnt++) {
-				if (fm->sockets[cnt])
-					fm->socket_change_set |= 1 << cnt;
-			}
-			if (!fm->socket_change_set) {
-				spin_unlock_irqrestore(&fm->lock, flags);
-				return 0;
-			} else {
 				spin_unlock_irqrestore(&fm->lock, flags);
 			}
+			if (sock)
+				tifm_free_device(&sock->dev);
 		}
+		spin_lock_irqsave(&fm->lock, flags);
 	}
-	return 0;
+
+	writel(TIFM_IRQ_FIFOMASK(socket_change_set)
+	       | TIFM_IRQ_CARDMASK(socket_change_set),
+	       fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
+
+	writel(TIFM_IRQ_FIFOMASK(socket_change_set)
+	       | TIFM_IRQ_CARDMASK(socket_change_set),
+	       fm->addr + FM_SET_INTERRUPT_ENABLE);
+
+	writel(TIFM_IRQ_ENABLE, fm->addr + FM_SET_INTERRUPT_ENABLE);
+	spin_unlock_irqrestore(&fm->lock, flags);
 }
 
 #ifdef CONFIG_PM
@@ -258,9 +217,11 @@
 static int tifm_7xx1_resume(struct pci_dev *dev)
 {
 	struct tifm_adapter *fm = pci_get_drvdata(dev);
-	int cnt, rc;
+	int rc;
+	unsigned int good_sockets = 0, bad_sockets = 0;
 	unsigned long flags;
-	tifm_media_id new_ids[fm->num_sockets];
+	unsigned char new_ids[fm->num_sockets];
+	DECLARE_COMPLETION_ONSTACK(finish_resume);
 
 	pci_set_power_state(dev, PCI_D0);
 	pci_restore_state(dev);
@@ -271,45 +232,49 @@
 
 	dev_dbg(&dev->dev, "resuming host\n");
 
-	for (cnt = 0; cnt < fm->num_sockets; cnt++)
-		new_ids[cnt] = tifm_7xx1_toggle_sock_power(
-					tifm_7xx1_sock_addr(fm->addr, cnt),
-					fm->num_sockets == 2);
+	for (rc = 0; rc < fm->num_sockets; rc++)
+		new_ids[rc] = tifm_7xx1_toggle_sock_power(
+					tifm_7xx1_sock_addr(fm->addr, rc));
 	spin_lock_irqsave(&fm->lock, flags);
-	fm->socket_change_set = 0;
-	for (cnt = 0; cnt < fm->num_sockets; cnt++) {
-		if (fm->sockets[cnt]) {
-			if (fm->sockets[cnt]->media_id == new_ids[cnt])
-				fm->socket_change_set |= 1 << cnt;
-
-			fm->sockets[cnt]->media_id = new_ids[cnt];
+	for (rc = 0; rc < fm->num_sockets; rc++) {
+		if (fm->sockets[rc]) {
+			if (fm->sockets[rc]->type == new_ids[rc])
+				good_sockets |= 1 << rc;
+			else
+				bad_sockets |= 1 << rc;
 		}
 	}
 
 	writel(TIFM_IRQ_ENABLE | TIFM_IRQ_SOCKMASK((1 << fm->num_sockets) - 1),
 	       fm->addr + FM_SET_INTERRUPT_ENABLE);
-	if (!fm->socket_change_set) {
+	dev_dbg(&dev->dev, "change sets on resume: good %x, bad %x\n",
+		good_sockets, bad_sockets);
+
+	fm->socket_change_set = 0;
+	if (good_sockets) {
+		fm->finish_me = &finish_resume;
 		spin_unlock_irqrestore(&fm->lock, flags);
-		return 0;
-	} else {
-		fm->socket_change_set = 0;
-		spin_unlock_irqrestore(&fm->lock, flags);
+		rc = wait_for_completion_timeout(&finish_resume, HZ);
+		dev_dbg(&dev->dev, "wait returned %d\n", rc);
+		writel(TIFM_IRQ_FIFOMASK(good_sockets)
+		       | TIFM_IRQ_CARDMASK(good_sockets),
+		       fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
+		writel(TIFM_IRQ_FIFOMASK(good_sockets)
+		       | TIFM_IRQ_CARDMASK(good_sockets),
+		       fm->addr + FM_SET_INTERRUPT_ENABLE);
+		spin_lock_irqsave(&fm->lock, flags);
+		fm->finish_me = NULL;
+		fm->socket_change_set ^= good_sockets & fm->socket_change_set;
 	}
 
-	wait_event_timeout(fm->change_set_notify, fm->socket_change_set, HZ);
-
-	spin_lock_irqsave(&fm->lock, flags);
-	writel(TIFM_IRQ_FIFOMASK(fm->socket_change_set)
-	       | TIFM_IRQ_CARDMASK(fm->socket_change_set),
-	       fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
-	writel(TIFM_IRQ_FIFOMASK(fm->socket_change_set)
-	       | TIFM_IRQ_CARDMASK(fm->socket_change_set),
-	       fm->addr + FM_SET_INTERRUPT_ENABLE);
-	writel(TIFM_IRQ_ENABLE,
-	       fm->addr + FM_SET_INTERRUPT_ENABLE);
-	fm->socket_change_set = 0;
+	fm->socket_change_set |= bad_sockets;
+	if (fm->socket_change_set)
+		tifm_queue_work(&fm->media_switcher);
 
 	spin_unlock_irqrestore(&fm->lock, flags);
+	writel(TIFM_IRQ_ENABLE,
+	       fm->addr + FM_SET_INTERRUPT_ENABLE);
+
 	return 0;
 }
 
@@ -345,20 +310,14 @@
 
 	pci_intx(dev, 1);
 
-	fm = tifm_alloc_adapter();
+	fm = tifm_alloc_adapter(dev->device == PCI_DEVICE_ID_TI_XX21_XX11_FM
+				? 4 : 2, &dev->dev);
 	if (!fm) {
 		rc = -ENOMEM;
 		goto err_out_int;
 	}
 
-	fm->dev = &dev->dev;
-	fm->num_sockets = (dev->device == PCI_DEVICE_ID_TI_XX21_XX11_FM)
-			  ? 4 : 2;
-	fm->sockets = kzalloc(sizeof(struct tifm_dev*) * fm->num_sockets,
-			      GFP_KERNEL);
-	if (!fm->sockets)
-		goto err_out_free;
-
+	INIT_WORK(&fm->media_switcher, tifm_7xx1_switch_media);
 	fm->eject = tifm_7xx1_eject;
 	pci_set_drvdata(dev, fm);
 
@@ -367,19 +326,16 @@
 	if (!fm->addr)
 		goto err_out_free;
 
-	rc = request_irq(dev->irq, tifm_7xx1_isr, IRQF_SHARED, DRIVER_NAME, fm);
+	rc = request_irq(dev->irq, tifm_7xx1_isr, SA_SHIRQ, DRIVER_NAME, fm);
 	if (rc)
 		goto err_out_unmap;
 
-	init_waitqueue_head(&fm->change_set_notify);
-	rc = tifm_add_adapter(fm, tifm_7xx1_switch_media);
+	rc = tifm_add_adapter(fm);
 	if (rc)
 		goto err_out_irq;
 
-	writel(TIFM_IRQ_SETALL, fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
 	writel(TIFM_IRQ_ENABLE | TIFM_IRQ_SOCKMASK((1 << fm->num_sockets) - 1),
 	       fm->addr + FM_SET_INTERRUPT_ENABLE);
-	wake_up_process(fm->media_switcher);
 	return 0;
 
 err_out_irq:
@@ -401,18 +357,12 @@
 static void tifm_7xx1_remove(struct pci_dev *dev)
 {
 	struct tifm_adapter *fm = pci_get_drvdata(dev);
-	unsigned long flags;
 
+	fm->eject = tifm_7xx1_dummy_eject;
 	writel(TIFM_IRQ_SETALL, fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
 	mmiowb();
 	free_irq(dev->irq, fm);
 
-	spin_lock_irqsave(&fm->lock, flags);
-	fm->socket_change_set = (1 << fm->num_sockets) - 1;
-	spin_unlock_irqrestore(&fm->lock, flags);
-
-	kthread_stop(fm->media_switcher);
-
 	tifm_remove_adapter(fm);
 
 	pci_set_drvdata(dev, NULL);
diff --git a/drivers/misc/tifm_core.c b/drivers/misc/tifm_core.c
index 6b10ebe..d195fb0 100644
--- a/drivers/misc/tifm_core.c
+++ b/drivers/misc/tifm_core.c
@@ -14,71 +14,124 @@
 #include <linux/idr.h>
 
 #define DRIVER_NAME "tifm_core"
-#define DRIVER_VERSION "0.7"
+#define DRIVER_VERSION "0.8"
 
+static struct workqueue_struct *workqueue;
 static DEFINE_IDR(tifm_adapter_idr);
 static DEFINE_SPINLOCK(tifm_adapter_lock);
 
-static tifm_media_id *tifm_device_match(tifm_media_id *ids,
-			struct tifm_dev *dev)
+static const char *tifm_media_type_name(unsigned char type, unsigned char nt)
 {
-	while (*ids) {
-		if (dev->media_id == *ids)
-			return ids;
-		ids++;
-	}
-	return NULL;
+	const char *card_type_name[3][3] = {
+		{ "SmartMedia/xD", "MemoryStick", "MMC/SD" },
+		{ "XD", "MS", "SD"},
+		{ "xd", "ms", "sd"}
+	};
+
+	if (nt > 2 || type < 1 || type > 3)
+		return NULL;
+	return card_type_name[nt][type - 1];
 }
 
-static int tifm_match(struct device *dev, struct device_driver *drv)
+static int tifm_dev_match(struct tifm_dev *sock, struct tifm_device_id *id)
 {
-	struct tifm_dev *fm_dev = container_of(dev, struct tifm_dev, dev);
-	struct tifm_driver *fm_drv;
-
-	fm_drv = container_of(drv, struct tifm_driver, driver);
-	if (!fm_drv->id_table)
-		return -EINVAL;
-	if (tifm_device_match(fm_drv->id_table, fm_dev))
+	if (sock->type == id->type)
 		return 1;
-	return -ENODEV;
+	return 0;
+}
+
+static int tifm_bus_match(struct device *dev, struct device_driver *drv)
+{
+	struct tifm_dev *sock = container_of(dev, struct tifm_dev, dev);
+	struct tifm_driver *fm_drv = container_of(drv, struct tifm_driver,
+						  driver);
+	struct tifm_device_id *ids = fm_drv->id_table;
+
+	if (ids) {
+		while (ids->type) {
+			if (tifm_dev_match(sock, ids))
+				return 1;
+			++ids;
+		}
+	}
+	return 0;
 }
 
 static int tifm_uevent(struct device *dev, char **envp, int num_envp,
 		       char *buffer, int buffer_size)
 {
-	struct tifm_dev *fm_dev;
+	struct tifm_dev *sock = container_of(dev, struct tifm_dev, dev);
 	int i = 0;
 	int length = 0;
-	const char *card_type_name[] = {"INV", "SM", "MS", "SD"};
 
-	if (!dev || !(fm_dev = container_of(dev, struct tifm_dev, dev)))
-		return -ENODEV;
 	if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length,
-			"TIFM_CARD_TYPE=%s", card_type_name[fm_dev->media_id]))
+			   "TIFM_CARD_TYPE=%s",
+			   tifm_media_type_name(sock->type, 1)))
 		return -ENOMEM;
 
 	return 0;
 }
 
+static int tifm_device_probe(struct device *dev)
+{
+	struct tifm_dev *sock = container_of(dev, struct tifm_dev, dev);
+	struct tifm_driver *drv = container_of(dev->driver, struct tifm_driver,
+					       driver);
+	int rc = -ENODEV;
+
+	get_device(dev);
+	if (dev->driver && drv->probe) {
+		rc = drv->probe(sock);
+		if (!rc)
+			return 0;
+	}
+	put_device(dev);
+	return rc;
+}
+
+static void tifm_dummy_event(struct tifm_dev *sock)
+{
+	return;
+}
+
+static int tifm_device_remove(struct device *dev)
+{
+	struct tifm_dev *sock = container_of(dev, struct tifm_dev, dev);
+	struct tifm_driver *drv = container_of(dev->driver, struct tifm_driver,
+					       driver);
+
+	if (dev->driver && drv->remove) {
+		sock->card_event = tifm_dummy_event;
+		sock->data_event = tifm_dummy_event;
+		drv->remove(sock);
+		sock->dev.driver = NULL;
+	}
+
+	put_device(dev);
+	return 0;
+}
+
 #ifdef CONFIG_PM
 
 static int tifm_device_suspend(struct device *dev, pm_message_t state)
 {
-	struct tifm_dev *fm_dev = container_of(dev, struct tifm_dev, dev);
-	struct tifm_driver *drv = fm_dev->drv;
+	struct tifm_dev *sock = container_of(dev, struct tifm_dev, dev);
+	struct tifm_driver *drv = container_of(dev->driver, struct tifm_driver,
+					       driver);
 
-	if (drv && drv->suspend)
-		return drv->suspend(fm_dev, state);
+	if (dev->driver && drv->suspend)
+		return drv->suspend(sock, state);
 	return 0;
 }
 
 static int tifm_device_resume(struct device *dev)
 {
-	struct tifm_dev *fm_dev = container_of(dev, struct tifm_dev, dev);
-	struct tifm_driver *drv = fm_dev->drv;
+	struct tifm_dev *sock = container_of(dev, struct tifm_dev, dev);
+	struct tifm_driver *drv = container_of(dev->driver, struct tifm_driver,
+					       driver);
 
-	if (drv && drv->resume)
-		return drv->resume(fm_dev);
+	if (dev->driver && drv->resume)
+		return drv->resume(sock);
 	return 0;
 }
 
@@ -89,19 +142,33 @@
 
 #endif /* CONFIG_PM */
 
+static ssize_t type_show(struct device *dev, struct device_attribute *attr,
+			 char *buf)
+{
+	struct tifm_dev *sock = container_of(dev, struct tifm_dev, dev);
+	return sprintf(buf, "%x", sock->type);
+}
+
+static struct device_attribute tifm_dev_attrs[] = {
+	__ATTR(type, S_IRUGO, type_show, NULL),
+	__ATTR_NULL
+};
+
 static struct bus_type tifm_bus_type = {
-	.name    = "tifm",
-	.match   = tifm_match,
-	.uevent  = tifm_uevent,
-	.suspend = tifm_device_suspend,
-	.resume  = tifm_device_resume
+	.name      = "tifm",
+	.dev_attrs = tifm_dev_attrs,
+	.match     = tifm_bus_match,
+	.uevent    = tifm_uevent,
+	.probe     = tifm_device_probe,
+	.remove    = tifm_device_remove,
+	.suspend   = tifm_device_suspend,
+	.resume    = tifm_device_resume
 };
 
 static void tifm_free(struct class_device *cdev)
 {
 	struct tifm_adapter *fm = container_of(cdev, struct tifm_adapter, cdev);
 
-	kfree(fm->sockets);
 	kfree(fm);
 }
 
@@ -110,28 +177,25 @@
 	.release = tifm_free
 };
 
-struct tifm_adapter *tifm_alloc_adapter(void)
+struct tifm_adapter *tifm_alloc_adapter(unsigned int num_sockets,
+					struct device *dev)
 {
 	struct tifm_adapter *fm;
 
-	fm = kzalloc(sizeof(struct tifm_adapter), GFP_KERNEL);
+	fm = kzalloc(sizeof(struct tifm_adapter)
+		     + sizeof(struct tifm_dev*) * num_sockets, GFP_KERNEL);
 	if (fm) {
 		fm->cdev.class = &tifm_adapter_class;
-		spin_lock_init(&fm->lock);
+		fm->cdev.dev = dev;
 		class_device_initialize(&fm->cdev);
+		spin_lock_init(&fm->lock);
+		fm->num_sockets = num_sockets;
 	}
 	return fm;
 }
 EXPORT_SYMBOL(tifm_alloc_adapter);
 
-void tifm_free_adapter(struct tifm_adapter *fm)
-{
-	class_device_put(&fm->cdev);
-}
-EXPORT_SYMBOL(tifm_free_adapter);
-
-int tifm_add_adapter(struct tifm_adapter *fm,
-		     int (*mediathreadfn)(void *data))
+int tifm_add_adapter(struct tifm_adapter *fm)
 {
 	int rc;
 
@@ -141,59 +205,80 @@
 	spin_lock(&tifm_adapter_lock);
 	rc = idr_get_new(&tifm_adapter_idr, fm, &fm->id);
 	spin_unlock(&tifm_adapter_lock);
-	if (!rc) {
-		snprintf(fm->cdev.class_id, BUS_ID_SIZE, "tifm%u", fm->id);
-		fm->media_switcher = kthread_create(mediathreadfn,
-						    fm, "tifm/%u", fm->id);
+	if (rc)
+		return rc;
 
-		if (!IS_ERR(fm->media_switcher))
-			return class_device_add(&fm->cdev);
-
+	snprintf(fm->cdev.class_id, BUS_ID_SIZE, "tifm%u", fm->id);
+	rc = class_device_add(&fm->cdev);
+	if (rc) {
 		spin_lock(&tifm_adapter_lock);
 		idr_remove(&tifm_adapter_idr, fm->id);
 		spin_unlock(&tifm_adapter_lock);
-		rc = -ENOMEM;
 	}
+
 	return rc;
 }
 EXPORT_SYMBOL(tifm_add_adapter);
 
 void tifm_remove_adapter(struct tifm_adapter *fm)
 {
-	class_device_del(&fm->cdev);
+	unsigned int cnt;
+
+	flush_workqueue(workqueue);
+	for (cnt = 0; cnt < fm->num_sockets; ++cnt) {
+		if (fm->sockets[cnt])
+			device_unregister(&fm->sockets[cnt]->dev);
+	}
 
 	spin_lock(&tifm_adapter_lock);
 	idr_remove(&tifm_adapter_idr, fm->id);
 	spin_unlock(&tifm_adapter_lock);
+	class_device_del(&fm->cdev);
 }
 EXPORT_SYMBOL(tifm_remove_adapter);
 
+void tifm_free_adapter(struct tifm_adapter *fm)
+{
+	class_device_put(&fm->cdev);
+}
+EXPORT_SYMBOL(tifm_free_adapter);
+
 void tifm_free_device(struct device *dev)
 {
-	struct tifm_dev *fm_dev = container_of(dev, struct tifm_dev, dev);
-	kfree(fm_dev);
+	struct tifm_dev *sock = container_of(dev, struct tifm_dev, dev);
+	kfree(sock);
 }
 EXPORT_SYMBOL(tifm_free_device);
 
-static void tifm_dummy_signal_irq(struct tifm_dev *sock,
-				  unsigned int sock_irq_status)
+struct tifm_dev *tifm_alloc_device(struct tifm_adapter *fm, unsigned int id,
+				   unsigned char type)
 {
-	return;
-}
+	struct tifm_dev *sock = NULL;
 
-struct tifm_dev *tifm_alloc_device(struct tifm_adapter *fm)
-{
-	struct tifm_dev *dev = kzalloc(sizeof(struct tifm_dev), GFP_KERNEL);
+	if (!tifm_media_type_name(type, 0))
+		return sock;
 
-	if (dev) {
-		spin_lock_init(&dev->lock);
+	sock = kzalloc(sizeof(struct tifm_dev), GFP_KERNEL);
+	if (sock) {
+		spin_lock_init(&sock->lock);
+		sock->type = type;
+		sock->socket_id = id;
+		sock->card_event = tifm_dummy_event;
+		sock->data_event = tifm_dummy_event;
 
-		dev->dev.parent = fm->dev;
-		dev->dev.bus = &tifm_bus_type;
-		dev->dev.release = tifm_free_device;
-		dev->signal_irq = tifm_dummy_signal_irq;
+		sock->dev.parent = fm->cdev.dev;
+		sock->dev.bus = &tifm_bus_type;
+		sock->dev.dma_mask = fm->cdev.dev->dma_mask;
+		sock->dev.release = tifm_free_device;
+
+		snprintf(sock->dev.bus_id, BUS_ID_SIZE,
+			 "tifm_%s%u:%u", tifm_media_type_name(type, 2),
+			 fm->id, id);
+		printk(KERN_INFO DRIVER_NAME
+		       ": %s card detected in socket %u:%u\n",
+		       tifm_media_type_name(type, 0), fm->id, id);
 	}
-	return dev;
+	return sock;
 }
 EXPORT_SYMBOL(tifm_alloc_device);
 
@@ -218,54 +303,15 @@
 }
 EXPORT_SYMBOL(tifm_unmap_sg);
 
-static int tifm_device_probe(struct device *dev)
+void tifm_queue_work(struct work_struct *work)
 {
-	struct tifm_driver *drv;
-	struct tifm_dev *fm_dev;
-	int rc = 0;
-	const tifm_media_id *id;
-
-	drv = container_of(dev->driver, struct tifm_driver, driver);
-	fm_dev = container_of(dev, struct tifm_dev, dev);
-	get_device(dev);
-	if (!fm_dev->drv && drv->probe && drv->id_table) {
-		rc = -ENODEV;
-		id = tifm_device_match(drv->id_table, fm_dev);
-		if (id)
-			rc = drv->probe(fm_dev);
-		if (rc >= 0) {
-			rc = 0;
-			fm_dev->drv = drv;
-		}
-	}
-	if (rc)
-		put_device(dev);
-	return rc;
+	queue_work(workqueue, work);
 }
-
-static int tifm_device_remove(struct device *dev)
-{
-	struct tifm_dev *fm_dev = container_of(dev, struct tifm_dev, dev);
-	struct tifm_driver *drv = fm_dev->drv;
-
-	if (drv) {
-		fm_dev->signal_irq = tifm_dummy_signal_irq;
-		if (drv->remove)
-			drv->remove(fm_dev);
-		fm_dev->drv = NULL;
-	}
-
-	put_device(dev);
-	return 0;
-}
+EXPORT_SYMBOL(tifm_queue_work);
 
 int tifm_register_driver(struct tifm_driver *drv)
 {
 	drv->driver.bus = &tifm_bus_type;
-	drv->driver.probe = tifm_device_probe;
-	drv->driver.remove = tifm_device_remove;
-	drv->driver.suspend = tifm_device_suspend;
-	drv->driver.resume = tifm_device_resume;
 
 	return driver_register(&drv->driver);
 }
@@ -279,13 +325,25 @@
 
 static int __init tifm_init(void)
 {
-	int rc = bus_register(&tifm_bus_type);
+	int rc;
 
-	if (!rc) {
-		rc = class_register(&tifm_adapter_class);
-		if (rc)
-			bus_unregister(&tifm_bus_type);
-	}
+	workqueue = create_freezeable_workqueue("tifm");
+	if (!workqueue)
+		return -ENOMEM;
+
+	rc = bus_register(&tifm_bus_type);
+
+	if (rc)
+		goto err_out_wq;
+
+	rc = class_register(&tifm_adapter_class);
+	if (!rc)
+		return 0;
+
+	bus_unregister(&tifm_bus_type);
+
+err_out_wq:
+	destroy_workqueue(workqueue);
 
 	return rc;
 }
@@ -294,6 +352,7 @@
 {
 	class_unregister(&tifm_adapter_class);
 	bus_unregister(&tifm_bus_type);
+	destroy_workqueue(workqueue);
 }
 
 subsys_initcall(tifm_init);
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index 12af9c7..6c97491 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -19,110 +19,10 @@
 	  This is an option for use by developers; most people should
 	  say N here.  This enables MMC core and driver debugging.
 
-config MMC_BLOCK
-	tristate "MMC block device driver"
-	depends on MMC && BLOCK
-	default y
-	help
-	  Say Y here to enable the MMC block device driver support.
-	  This provides a block device driver, which you can use to
-	  mount the filesystem. Almost everyone wishing MMC support
-	  should say Y or M here.
+source "drivers/mmc/core/Kconfig"
 
-config MMC_ARMMMCI
-	tristate "ARM AMBA Multimedia Card Interface support"
-	depends on ARM_AMBA && MMC
-	help
-	  This selects the ARM(R) AMBA(R) PrimeCell Multimedia Card
-	  Interface (PL180 and PL181) support.  If you have an ARM(R)
-	  platform with a Multimedia Card slot, say Y or M here.
+source "drivers/mmc/card/Kconfig"
 
-	  If unsure, say N.
-
-config MMC_PXA
-	tristate "Intel PXA25x/26x/27x Multimedia Card Interface support"
-	depends on ARCH_PXA && MMC
-	help
-	  This selects the Intel(R) PXA(R) Multimedia card Interface.
-	  If you have a PXA(R) platform with a Multimedia Card slot,
-	  say Y or M here.
-
-	  If unsure, say N.
-
-config MMC_SDHCI
-	tristate "Secure Digital Host Controller Interface support  (EXPERIMENTAL)"
-	depends on PCI && MMC && EXPERIMENTAL
-	help
-	  This select the generic Secure Digital Host Controller Interface.
-	  It is used by manufacturers such as Texas Instruments(R), Ricoh(R)
-	  and Toshiba(R). Most controllers found in laptops are of this type.
-	  If you have a controller with this interface, say Y or M here.
-
-	  If unsure, say N.
-
-config MMC_OMAP
-	tristate "TI OMAP Multimedia Card Interface support"
-	depends on ARCH_OMAP && MMC
-	select TPS65010 if MACH_OMAP_H2
-	help
-	  This selects the TI OMAP Multimedia card Interface.
-	  If you have an OMAP board with a Multimedia Card slot,
-	  say Y or M here.
-
-	  If unsure, say N.
-
-config MMC_WBSD
-	tristate "Winbond W83L51xD SD/MMC Card Interface support"
-	depends on MMC && ISA_DMA_API
-	help
-	  This selects the Winbond(R) W83L51xD Secure digital and
-          Multimedia card Interface.
-	  If you have a machine with a integrated W83L518D or W83L519D
-	  SD/MMC card reader, say Y or M here.
-
-	  If unsure, say N.
-
-config MMC_AU1X
-	tristate "Alchemy AU1XX0 MMC Card Interface support"
-	depends on MMC && SOC_AU1200
-	help
-	  This selects the AMD Alchemy(R) Multimedia card interface.
-	  If you have a Alchemy platform with a MMC slot, say Y or M here.
-
-	  If unsure, say N.
-
-config MMC_AT91
-	tristate "AT91 SD/MMC Card Interface support"
-	depends on ARCH_AT91 && MMC
-	help
-	  This selects the AT91 MCI controller.
-
-	  If unsure, say N.
-
-config MMC_IMX
-	tristate "Motorola i.MX Multimedia Card Interface support"
-	depends on ARCH_IMX && MMC
-	help
-	  This selects the Motorola i.MX Multimedia card Interface.
-	  If you have a i.MX platform with a Multimedia Card slot,
-	  say Y or M here.
-
-	  If unsure, say N.
-
-config MMC_TIFM_SD
-	tristate "TI Flash Media MMC/SD Interface support  (EXPERIMENTAL)"
-	depends on MMC && EXPERIMENTAL && PCI
-	select TIFM_CORE
-	help
-	  Say Y here if you want to be able to access MMC/SD cards with
-	  the Texas Instruments(R) Flash Media card reader, found in many
-	  laptops.
-	  This option 'selects' (turns on, enables) 'TIFM_CORE', but you
-	  probably also need appropriate card reader host adapter, such as
-	  'Misc devices: TI Flash Media PCI74xx/PCI76xx host adapter support
-	  (TIFM_7XX1)'.
-
-          To compile this driver as a module, choose M here: the
-	  module will be called tifm_sd.
+source "drivers/mmc/host/Kconfig"
 
 endmenu
diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
index 83ffb93..9979f5e 100644
--- a/drivers/mmc/Makefile
+++ b/drivers/mmc/Makefile
@@ -2,32 +2,11 @@
 # Makefile for the kernel mmc device drivers.
 #
 
-#
-# Core
-#
-obj-$(CONFIG_MMC)		+= mmc_core.o
-
-#
-# Media drivers
-#
-obj-$(CONFIG_MMC_BLOCK)		+= mmc_block.o
-
-#
-# Host drivers
-#
-obj-$(CONFIG_MMC_ARMMMCI)	+= mmci.o
-obj-$(CONFIG_MMC_PXA)		+= pxamci.o
-obj-$(CONFIG_MMC_IMX)		+= imxmmc.o
-obj-$(CONFIG_MMC_SDHCI)		+= sdhci.o
-obj-$(CONFIG_MMC_WBSD)		+= wbsd.o
-obj-$(CONFIG_MMC_AU1X)		+= au1xmmc.o
-obj-$(CONFIG_MMC_OMAP)		+= omap.o
-obj-$(CONFIG_MMC_AT91)		+= at91_mci.o
-obj-$(CONFIG_MMC_TIFM_SD)	+= tifm_sd.o
-
-mmc_core-y := mmc.o mmc_sysfs.o
-mmc_core-$(CONFIG_BLOCK) += mmc_queue.o
-
 ifeq ($(CONFIG_MMC_DEBUG),y)
-EXTRA_CFLAGS += -DDEBUG
+	EXTRA_CFLAGS		+= -DDEBUG
 endif
+
+obj-$(CONFIG_MMC)		+= core/
+obj-$(CONFIG_MMC)		+= card/
+obj-$(CONFIG_MMC)		+= host/
+
diff --git a/drivers/mmc/card/Kconfig b/drivers/mmc/card/Kconfig
new file mode 100644
index 0000000..01a9fd3
--- /dev/null
+++ b/drivers/mmc/card/Kconfig
@@ -0,0 +1,17 @@
+#
+# MMC/SD card drivers
+#
+
+comment "MMC/SD Card Drivers"
+	depends MMC
+
+config MMC_BLOCK
+	tristate "MMC block device driver"
+	depends on MMC && BLOCK
+	default y
+	help
+	  Say Y here to enable the MMC block device driver support.
+	  This provides a block device driver, which you can use to
+	  mount the filesystem. Almost everyone wishing MMC support
+	  should say Y or M here.
+
diff --git a/drivers/mmc/card/Makefile b/drivers/mmc/card/Makefile
new file mode 100644
index 0000000..cf8c939
--- /dev/null
+++ b/drivers/mmc/card/Makefile
@@ -0,0 +1,11 @@
+#
+# Makefile for MMC/SD card drivers
+#
+
+ifeq ($(CONFIG_MMC_DEBUG),y)
+	EXTRA_CFLAGS		+= -DDEBUG
+endif
+
+obj-$(CONFIG_MMC_BLOCK)		+= mmc_block.o
+mmc_block-objs			:= block.o queue.o
+
diff --git a/drivers/mmc/mmc_block.c b/drivers/mmc/card/block.c
similarity index 92%
rename from drivers/mmc/mmc_block.c
rename to drivers/mmc/card/block.c
index 86439a0..d24ab23 100644
--- a/drivers/mmc/mmc_block.c
+++ b/drivers/mmc/card/block.c
@@ -2,6 +2,7 @@
  * Block driver for media (i.e., flash cards)
  *
  * Copyright 2002 Hewlett-Packard Company
+ * Copyright 2005-2007 Pierre Ossman
  *
  * Use consistent with the GNU GPL is permitted,
  * provided that this copyright notice is
@@ -31,13 +32,13 @@
 
 #include <linux/mmc/card.h>
 #include <linux/mmc/host.h>
-#include <linux/mmc/protocol.h>
-#include <linux/mmc/host.h>
+#include <linux/mmc/mmc.h>
+#include <linux/mmc/sd.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
 
-#include "mmc_queue.h"
+#include "queue.h"
 
 /*
  * max 8 partitions per card
@@ -223,10 +224,9 @@
 	struct mmc_blk_data *md = mq->data;
 	struct mmc_card *card = md->queue.card;
 	struct mmc_blk_request brq;
-	int ret = 1;
+	int ret = 1, sg_pos, data_size;
 
-	if (mmc_card_claim_host(card))
-		goto flush_queue;
+	mmc_claim_host(card->host);
 
 	do {
 		struct mmc_command cmd;
@@ -283,6 +283,20 @@
 		brq.data.sg = mq->sg;
 		brq.data.sg_len = blk_rq_map_sg(req->q, req, brq.data.sg);
 
+		if (brq.data.blocks !=
+		    (req->nr_sectors >> (md->block_bits - 9))) {
+			data_size = brq.data.blocks * brq.data.blksz;
+			for (sg_pos = 0; sg_pos < brq.data.sg_len; sg_pos++) {
+				data_size -= mq->sg[sg_pos].length;
+				if (data_size <= 0) {
+					mq->sg[sg_pos].length += data_size;
+					sg_pos++;
+					break;
+				}
+			}
+			brq.data.sg_len = sg_pos;
+		}
+
 		mmc_wait_for_req(card->host, &brq.mrq);
 		if (brq.cmd.error) {
 			printk(KERN_ERR "%s: error %d sending read/write command\n",
@@ -342,7 +356,7 @@
 		spin_unlock_irq(&md->lock);
 	} while (ret);
 
-	mmc_card_release_host(card);
+	mmc_release_host(card->host);
 
 	return 1;
 
@@ -378,9 +392,7 @@
 		spin_unlock_irq(&md->lock);
 	}
 
-flush_queue:
-
-	mmc_card_release_host(card);
+	mmc_release_host(card->host);
 
 	spin_lock_irq(&md->lock);
 	while (ret) {
@@ -477,11 +489,20 @@
 
 	blk_queue_hardsect_size(md->queue.queue, 1 << md->block_bits);
 
-	/*
-	 * The CSD capacity field is in units of read_blkbits.
-	 * set_capacity takes units of 512 bytes.
-	 */
-	set_capacity(md->disk, card->csd.capacity << (card->csd.read_blkbits - 9));
+	if (!mmc_card_sd(card) && mmc_card_blockaddr(card)) {
+		/*
+		 * The EXT_CSD sector count is in number or 512 byte
+		 * sectors.
+		 */
+		set_capacity(md->disk, card->ext_csd.sectors);
+	} else {
+		/*
+		 * The CSD capacity field is in units of read_blkbits.
+		 * set_capacity takes units of 512 bytes.
+		 */
+		set_capacity(md->disk,
+			card->csd.capacity << (card->csd.read_blkbits - 9));
+	}
 	return md;
 
  err_putdisk:
@@ -502,12 +523,12 @@
 	if (mmc_card_blockaddr(card))
 		return 0;
 
-	mmc_card_claim_host(card);
+	mmc_claim_host(card->host);
 	cmd.opcode = MMC_SET_BLOCKLEN;
 	cmd.arg = 1 << md->block_bits;
 	cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
 	err = mmc_wait_for_cmd(card->host, &cmd, 5);
-	mmc_card_release_host(card);
+	mmc_release_host(card->host);
 
 	if (err) {
 		printk(KERN_ERR "%s: unable to set block size to %d: %d\n",
diff --git a/drivers/mmc/mmc_queue.c b/drivers/mmc/card/queue.c
similarity index 96%
rename from drivers/mmc/mmc_queue.c
rename to drivers/mmc/card/queue.c
index c27e426..2e77963 100644
--- a/drivers/mmc/mmc_queue.c
+++ b/drivers/mmc/card/queue.c
@@ -1,7 +1,8 @@
 /*
- *  linux/drivers/mmc/mmc_queue.c
+ *  linux/drivers/mmc/queue.c
  *
  *  Copyright (C) 2003 Russell King, All Rights Reserved.
+ *  Copyright 2006-2007 Pierre Ossman
  *
  * 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
@@ -14,7 +15,7 @@
 
 #include <linux/mmc/card.h>
 #include <linux/mmc/host.h>
-#include "mmc_queue.h"
+#include "queue.h"
 
 #define MMC_QUEUE_SUSPENDED	(1 << 0)
 
@@ -179,7 +180,6 @@
 	blk_cleanup_queue(mq->queue);
 	return ret;
 }
-EXPORT_SYMBOL(mmc_init_queue);
 
 void mmc_cleanup_queue(struct mmc_queue *mq)
 {
@@ -191,6 +191,9 @@
 	q->queuedata = NULL;
 	spin_unlock_irqrestore(q->queue_lock, flags);
 
+	/* Make sure the queue isn't suspended, as that will deadlock */
+	mmc_queue_resume(mq);
+
 	/* Then terminate our worker thread */
 	kthread_stop(mq->thread);
 
@@ -226,7 +229,6 @@
 		down(&mq->thread_sem);
 	}
 }
-EXPORT_SYMBOL(mmc_queue_suspend);
 
 /**
  * mmc_queue_resume - resume a previously suspended MMC request queue
@@ -247,4 +249,4 @@
 		spin_unlock_irqrestore(q->queue_lock, flags);
 	}
 }
-EXPORT_SYMBOL(mmc_queue_resume);
+
diff --git a/drivers/mmc/mmc_queue.h b/drivers/mmc/card/queue.h
similarity index 100%
rename from drivers/mmc/mmc_queue.h
rename to drivers/mmc/card/queue.h
diff --git a/drivers/mmc/core/Kconfig b/drivers/mmc/core/Kconfig
new file mode 100644
index 0000000..94222b9
--- /dev/null
+++ b/drivers/mmc/core/Kconfig
@@ -0,0 +1,17 @@
+#
+# MMC core configuration
+#
+
+config MMC_UNSAFE_RESUME
+	bool "Allow unsafe resume (DANGEROUS)"
+	depends on MMC != n
+	help
+	  If you say Y here, the MMC layer will assume that all cards
+	  stayed in their respective slots during the suspend. The
+	  normal behaviour is to remove them at suspend and
+	  redetecting them at resume. Breaking this assumption will
+	  in most cases result in data corruption.
+
+	  This option is usually just for embedded systems which use
+	  a MMC/SD card for rootfs. Most people should say N here.
+
diff --git a/drivers/mmc/core/Makefile b/drivers/mmc/core/Makefile
new file mode 100644
index 0000000..1075b02
--- /dev/null
+++ b/drivers/mmc/core/Makefile
@@ -0,0 +1,11 @@
+#
+# Makefile for the kernel mmc core.
+#
+
+ifeq ($(CONFIG_MMC_DEBUG),y)
+	EXTRA_CFLAGS		+= -DDEBUG
+endif
+
+obj-$(CONFIG_MMC)		+= mmc_core.o
+mmc_core-y			:= core.o sysfs.o mmc.o mmc_ops.o sd.o sd_ops.o
+
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
new file mode 100644
index 0000000..72c7cf4
--- /dev/null
+++ b/drivers/mmc/core/core.c
@@ -0,0 +1,727 @@
+/*
+ *  linux/drivers/mmc/core/core.c
+ *
+ *  Copyright (C) 2003-2004 Russell King, All Rights Reserved.
+ *  SD support Copyright (C) 2004 Ian Molton, All Rights Reserved.
+ *  Copyright (C) 2005-2007 Pierre Ossman, All Rights Reserved.
+ *  MMCv4 support Copyright (C) 2006 Philip Langdale, 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/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/completion.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/pagemap.h>
+#include <linux/err.h>
+#include <asm/scatterlist.h>
+#include <linux/scatterlist.h>
+
+#include <linux/mmc/card.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/mmc.h>
+#include <linux/mmc/sd.h>
+
+#include "core.h"
+#include "sysfs.h"
+
+#include "mmc_ops.h"
+#include "sd_ops.h"
+
+extern int mmc_attach_mmc(struct mmc_host *host, u32 ocr);
+extern int mmc_attach_sd(struct mmc_host *host, u32 ocr);
+
+/**
+ *	mmc_request_done - finish processing an MMC request
+ *	@host: MMC host which completed request
+ *	@mrq: MMC request which request
+ *
+ *	MMC drivers should call this function when they have completed
+ *	their processing of a request.
+ */
+void mmc_request_done(struct mmc_host *host, struct mmc_request *mrq)
+{
+	struct mmc_command *cmd = mrq->cmd;
+	int err = cmd->error;
+
+	pr_debug("%s: req done (CMD%u): %d/%d/%d: %08x %08x %08x %08x\n",
+		 mmc_hostname(host), cmd->opcode, err,
+		 mrq->data ? mrq->data->error : 0,
+		 mrq->stop ? mrq->stop->error : 0,
+		 cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]);
+
+	if (err && cmd->retries) {
+		cmd->retries--;
+		cmd->error = 0;
+		host->ops->request(host, mrq);
+	} else if (mrq->done) {
+		mrq->done(mrq);
+	}
+}
+
+EXPORT_SYMBOL(mmc_request_done);
+
+/**
+ *	mmc_start_request - start a command on a host
+ *	@host: MMC host to start command on
+ *	@mrq: MMC request to start
+ *
+ *	Queue a command on the specified host.  We expect the
+ *	caller to be holding the host lock with interrupts disabled.
+ */
+void
+mmc_start_request(struct mmc_host *host, struct mmc_request *mrq)
+{
+#ifdef CONFIG_MMC_DEBUG
+	unsigned int i, sz;
+#endif
+
+	pr_debug("%s: starting CMD%u arg %08x flags %08x\n",
+		 mmc_hostname(host), mrq->cmd->opcode,
+		 mrq->cmd->arg, mrq->cmd->flags);
+
+	WARN_ON(!host->claimed);
+
+	mrq->cmd->error = 0;
+	mrq->cmd->mrq = mrq;
+	if (mrq->data) {
+		BUG_ON(mrq->data->blksz > host->max_blk_size);
+		BUG_ON(mrq->data->blocks > host->max_blk_count);
+		BUG_ON(mrq->data->blocks * mrq->data->blksz >
+			host->max_req_size);
+
+#ifdef CONFIG_MMC_DEBUG
+		sz = 0;
+		for (i = 0;i < mrq->data->sg_len;i++)
+			sz += mrq->data->sg[i].length;
+		BUG_ON(sz != mrq->data->blocks * mrq->data->blksz);
+#endif
+
+		mrq->cmd->data = mrq->data;
+		mrq->data->error = 0;
+		mrq->data->mrq = mrq;
+		if (mrq->stop) {
+			mrq->data->stop = mrq->stop;
+			mrq->stop->error = 0;
+			mrq->stop->mrq = mrq;
+		}
+	}
+	host->ops->request(host, mrq);
+}
+
+EXPORT_SYMBOL(mmc_start_request);
+
+static void mmc_wait_done(struct mmc_request *mrq)
+{
+	complete(mrq->done_data);
+}
+
+int mmc_wait_for_req(struct mmc_host *host, struct mmc_request *mrq)
+{
+	DECLARE_COMPLETION_ONSTACK(complete);
+
+	mrq->done_data = &complete;
+	mrq->done = mmc_wait_done;
+
+	mmc_start_request(host, mrq);
+
+	wait_for_completion(&complete);
+
+	return 0;
+}
+
+EXPORT_SYMBOL(mmc_wait_for_req);
+
+/**
+ *	mmc_wait_for_cmd - start a command and wait for completion
+ *	@host: MMC host to start command
+ *	@cmd: MMC command to start
+ *	@retries: maximum number of retries
+ *
+ *	Start a new MMC command for a host, and wait for the command
+ *	to complete.  Return any error that occurred while the command
+ *	was executing.  Do not attempt to parse the response.
+ */
+int mmc_wait_for_cmd(struct mmc_host *host, struct mmc_command *cmd, int retries)
+{
+	struct mmc_request mrq;
+
+	BUG_ON(!host->claimed);
+
+	memset(&mrq, 0, sizeof(struct mmc_request));
+
+	memset(cmd->resp, 0, sizeof(cmd->resp));
+	cmd->retries = retries;
+
+	mrq.cmd = cmd;
+	cmd->data = NULL;
+
+	mmc_wait_for_req(host, &mrq);
+
+	return cmd->error;
+}
+
+EXPORT_SYMBOL(mmc_wait_for_cmd);
+
+/**
+ *	mmc_set_data_timeout - set the timeout for a data command
+ *	@data: data phase for command
+ *	@card: the MMC card associated with the data transfer
+ *	@write: flag to differentiate reads from writes
+ */
+void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card,
+			  int write)
+{
+	unsigned int mult;
+
+	/*
+	 * SD cards use a 100 multiplier rather than 10
+	 */
+	mult = mmc_card_sd(card) ? 100 : 10;
+
+	/*
+	 * Scale up the multiplier (and therefore the timeout) by
+	 * the r2w factor for writes.
+	 */
+	if (write)
+		mult <<= card->csd.r2w_factor;
+
+	data->timeout_ns = card->csd.tacc_ns * mult;
+	data->timeout_clks = card->csd.tacc_clks * mult;
+
+	/*
+	 * SD cards also have an upper limit on the timeout.
+	 */
+	if (mmc_card_sd(card)) {
+		unsigned int timeout_us, limit_us;
+
+		timeout_us = data->timeout_ns / 1000;
+		timeout_us += data->timeout_clks * 1000 /
+			(card->host->ios.clock / 1000);
+
+		if (write)
+			limit_us = 250000;
+		else
+			limit_us = 100000;
+
+		/*
+		 * SDHC cards always use these fixed values.
+		 */
+		if (timeout_us > limit_us || mmc_card_blockaddr(card)) {
+			data->timeout_ns = limit_us * 1000;
+			data->timeout_clks = 0;
+		}
+	}
+}
+EXPORT_SYMBOL(mmc_set_data_timeout);
+
+/**
+ *	__mmc_claim_host - exclusively claim a host
+ *	@host: mmc host to claim
+ *	@card: mmc card to claim host for
+ *
+ *	Claim a host for a set of operations.  If a valid card
+ *	is passed and this wasn't the last card selected, select
+ *	the card before returning.
+ *
+ *	Note: you should use mmc_card_claim_host or mmc_claim_host.
+ */
+void mmc_claim_host(struct mmc_host *host)
+{
+	DECLARE_WAITQUEUE(wait, current);
+	unsigned long flags;
+
+	add_wait_queue(&host->wq, &wait);
+	spin_lock_irqsave(&host->lock, flags);
+	while (1) {
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		if (!host->claimed)
+			break;
+		spin_unlock_irqrestore(&host->lock, flags);
+		schedule();
+		spin_lock_irqsave(&host->lock, flags);
+	}
+	set_current_state(TASK_RUNNING);
+	host->claimed = 1;
+	spin_unlock_irqrestore(&host->lock, flags);
+	remove_wait_queue(&host->wq, &wait);
+}
+
+EXPORT_SYMBOL(mmc_claim_host);
+
+/**
+ *	mmc_release_host - release a host
+ *	@host: mmc host to release
+ *
+ *	Release a MMC host, allowing others to claim the host
+ *	for their operations.
+ */
+void mmc_release_host(struct mmc_host *host)
+{
+	unsigned long flags;
+
+	BUG_ON(!host->claimed);
+
+	spin_lock_irqsave(&host->lock, flags);
+	host->claimed = 0;
+	spin_unlock_irqrestore(&host->lock, flags);
+
+	wake_up(&host->wq);
+}
+
+EXPORT_SYMBOL(mmc_release_host);
+
+/*
+ * Internal function that does the actual ios call to the host driver,
+ * optionally printing some debug output.
+ */
+static inline void mmc_set_ios(struct mmc_host *host)
+{
+	struct mmc_ios *ios = &host->ios;
+
+	pr_debug("%s: clock %uHz busmode %u powermode %u cs %u Vdd %u "
+		"width %u timing %u\n",
+		 mmc_hostname(host), ios->clock, ios->bus_mode,
+		 ios->power_mode, ios->chip_select, ios->vdd,
+		 ios->bus_width, ios->timing);
+
+	host->ops->set_ios(host, ios);
+}
+
+/*
+ * Control chip select pin on a host.
+ */
+void mmc_set_chip_select(struct mmc_host *host, int mode)
+{
+	host->ios.chip_select = mode;
+	mmc_set_ios(host);
+}
+
+/*
+ * Sets the host clock to the highest possible frequency that
+ * is below "hz".
+ */
+void mmc_set_clock(struct mmc_host *host, unsigned int hz)
+{
+	WARN_ON(hz < host->f_min);
+
+	if (hz > host->f_max)
+		hz = host->f_max;
+
+	host->ios.clock = hz;
+	mmc_set_ios(host);
+}
+
+/*
+ * Change the bus mode (open drain/push-pull) of a host.
+ */
+void mmc_set_bus_mode(struct mmc_host *host, unsigned int mode)
+{
+	host->ios.bus_mode = mode;
+	mmc_set_ios(host);
+}
+
+/*
+ * Change data bus width of a host.
+ */
+void mmc_set_bus_width(struct mmc_host *host, unsigned int width)
+{
+	host->ios.bus_width = width;
+	mmc_set_ios(host);
+}
+
+/*
+ * Mask off any voltages we don't support and select
+ * the lowest voltage
+ */
+u32 mmc_select_voltage(struct mmc_host *host, u32 ocr)
+{
+	int bit;
+
+	ocr &= host->ocr_avail;
+
+	bit = ffs(ocr);
+	if (bit) {
+		bit -= 1;
+
+		ocr &= 3 << bit;
+
+		host->ios.vdd = bit;
+		mmc_set_ios(host);
+	} else {
+		ocr = 0;
+	}
+
+	return ocr;
+}
+
+/*
+ * Select timing parameters for host.
+ */
+void mmc_set_timing(struct mmc_host *host, unsigned int timing)
+{
+	host->ios.timing = timing;
+	mmc_set_ios(host);
+}
+
+/*
+ * Allocate a new MMC card
+ */
+struct mmc_card *mmc_alloc_card(struct mmc_host *host)
+{
+	struct mmc_card *card;
+
+	card = kmalloc(sizeof(struct mmc_card), GFP_KERNEL);
+	if (!card)
+		return ERR_PTR(-ENOMEM);
+
+	mmc_init_card(card, host);
+
+	return card;
+}
+
+/*
+ * Apply power to the MMC stack.  This is a two-stage process.
+ * First, we enable power to the card without the clock running.
+ * We then wait a bit for the power to stabilise.  Finally,
+ * enable the bus drivers and clock to the card.
+ *
+ * We must _NOT_ enable the clock prior to power stablising.
+ *
+ * If a host does all the power sequencing itself, ignore the
+ * initial MMC_POWER_UP stage.
+ */
+static void mmc_power_up(struct mmc_host *host)
+{
+	int bit = fls(host->ocr_avail) - 1;
+
+	host->ios.vdd = bit;
+	host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN;
+	host->ios.chip_select = MMC_CS_DONTCARE;
+	host->ios.power_mode = MMC_POWER_UP;
+	host->ios.bus_width = MMC_BUS_WIDTH_1;
+	host->ios.timing = MMC_TIMING_LEGACY;
+	mmc_set_ios(host);
+
+	mmc_delay(1);
+
+	host->ios.clock = host->f_min;
+	host->ios.power_mode = MMC_POWER_ON;
+	mmc_set_ios(host);
+
+	mmc_delay(2);
+}
+
+static void mmc_power_off(struct mmc_host *host)
+{
+	host->ios.clock = 0;
+	host->ios.vdd = 0;
+	host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN;
+	host->ios.chip_select = MMC_CS_DONTCARE;
+	host->ios.power_mode = MMC_POWER_OFF;
+	host->ios.bus_width = MMC_BUS_WIDTH_1;
+	host->ios.timing = MMC_TIMING_LEGACY;
+	mmc_set_ios(host);
+}
+
+/*
+ * Assign a mmc bus handler to a host. Only one bus handler may control a
+ * host at any given time.
+ */
+void mmc_attach_bus(struct mmc_host *host, const struct mmc_bus_ops *ops)
+{
+	unsigned long flags;
+
+	BUG_ON(!host);
+	BUG_ON(!ops);
+
+	BUG_ON(!host->claimed);
+
+	spin_lock_irqsave(&host->lock, flags);
+
+	BUG_ON(host->bus_ops);
+	BUG_ON(host->bus_refs);
+
+	host->bus_ops = ops;
+	host->bus_refs = 1;
+	host->bus_dead = 0;
+
+	spin_unlock_irqrestore(&host->lock, flags);
+}
+
+/*
+ * Remove the current bus handler from a host. Assumes that there are
+ * no interesting cards left, so the bus is powered down.
+ */
+void mmc_detach_bus(struct mmc_host *host)
+{
+	unsigned long flags;
+
+	BUG_ON(!host);
+
+	BUG_ON(!host->claimed);
+	BUG_ON(!host->bus_ops);
+
+	spin_lock_irqsave(&host->lock, flags);
+
+	host->bus_dead = 1;
+
+	spin_unlock_irqrestore(&host->lock, flags);
+
+	mmc_power_off(host);
+
+	mmc_bus_put(host);
+}
+
+/*
+ * Cleanup when the last reference to the bus operator is dropped.
+ */
+void __mmc_release_bus(struct mmc_host *host)
+{
+	BUG_ON(!host);
+	BUG_ON(host->bus_refs);
+	BUG_ON(!host->bus_dead);
+
+	host->bus_ops = NULL;
+}
+
+/**
+ *	mmc_detect_change - process change of state on a MMC socket
+ *	@host: host which changed state.
+ *	@delay: optional delay to wait before detection (jiffies)
+ *
+ *	All we know is that card(s) have been inserted or removed
+ *	from the socket(s).  We don't know which socket or cards.
+ */
+void mmc_detect_change(struct mmc_host *host, unsigned long delay)
+{
+#ifdef CONFIG_MMC_DEBUG
+	mmc_claim_host(host);
+	BUG_ON(host->removed);
+	mmc_release_host(host);
+#endif
+
+	mmc_schedule_delayed_work(&host->detect, delay);
+}
+
+EXPORT_SYMBOL(mmc_detect_change);
+
+
+static void mmc_rescan(struct work_struct *work)
+{
+	struct mmc_host *host =
+		container_of(work, struct mmc_host, detect.work);
+	u32 ocr;
+	int err;
+
+	mmc_bus_get(host);
+
+	if (host->bus_ops == NULL) {
+		/*
+		 * Only we can add a new handler, so it's safe to
+		 * release the lock here.
+		 */
+		mmc_bus_put(host);
+
+		mmc_claim_host(host);
+
+		mmc_power_up(host);
+		mmc_go_idle(host);
+
+		mmc_send_if_cond(host, host->ocr_avail);
+
+		err = mmc_send_app_op_cond(host, 0, &ocr);
+		if (err == MMC_ERR_NONE) {
+			if (mmc_attach_sd(host, ocr))
+				mmc_power_off(host);
+		} else {
+			/*
+			 * If we fail to detect any SD cards then try
+			 * searching for MMC cards.
+			 */
+			err = mmc_send_op_cond(host, 0, &ocr);
+			if (err == MMC_ERR_NONE) {
+				if (mmc_attach_mmc(host, ocr))
+					mmc_power_off(host);
+			} else {
+				mmc_power_off(host);
+				mmc_release_host(host);
+			}
+		}
+	} else {
+		if (host->bus_ops->detect && !host->bus_dead)
+			host->bus_ops->detect(host);
+
+		mmc_bus_put(host);
+	}
+}
+
+
+/**
+ *	mmc_alloc_host - initialise the per-host structure.
+ *	@extra: sizeof private data structure
+ *	@dev: pointer to host device model structure
+ *
+ *	Initialise the per-host structure.
+ */
+struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
+{
+	struct mmc_host *host;
+
+	host = mmc_alloc_host_sysfs(extra, dev);
+	if (host) {
+		spin_lock_init(&host->lock);
+		init_waitqueue_head(&host->wq);
+		INIT_DELAYED_WORK(&host->detect, mmc_rescan);
+
+		/*
+		 * By default, hosts do not support SGIO or large requests.
+		 * They have to set these according to their abilities.
+		 */
+		host->max_hw_segs = 1;
+		host->max_phys_segs = 1;
+		host->max_seg_size = PAGE_CACHE_SIZE;
+
+		host->max_req_size = PAGE_CACHE_SIZE;
+		host->max_blk_size = 512;
+		host->max_blk_count = PAGE_CACHE_SIZE / 512;
+	}
+
+	return host;
+}
+
+EXPORT_SYMBOL(mmc_alloc_host);
+
+/**
+ *	mmc_add_host - initialise host hardware
+ *	@host: mmc host
+ */
+int mmc_add_host(struct mmc_host *host)
+{
+	int ret;
+
+	ret = mmc_add_host_sysfs(host);
+	if (ret == 0) {
+		mmc_power_off(host);
+		mmc_detect_change(host, 0);
+	}
+
+	return ret;
+}
+
+EXPORT_SYMBOL(mmc_add_host);
+
+/**
+ *	mmc_remove_host - remove host hardware
+ *	@host: mmc host
+ *
+ *	Unregister and remove all cards associated with this host,
+ *	and power down the MMC bus.
+ */
+void mmc_remove_host(struct mmc_host *host)
+{
+#ifdef CONFIG_MMC_DEBUG
+	mmc_claim_host(host);
+	host->removed = 1;
+	mmc_release_host(host);
+#endif
+
+	mmc_flush_scheduled_work();
+
+	mmc_bus_get(host);
+	if (host->bus_ops && !host->bus_dead) {
+		if (host->bus_ops->remove)
+			host->bus_ops->remove(host);
+
+		mmc_claim_host(host);
+		mmc_detach_bus(host);
+		mmc_release_host(host);
+	}
+	mmc_bus_put(host);
+
+	BUG_ON(host->card);
+
+	mmc_power_off(host);
+	mmc_remove_host_sysfs(host);
+}
+
+EXPORT_SYMBOL(mmc_remove_host);
+
+/**
+ *	mmc_free_host - free the host structure
+ *	@host: mmc host
+ *
+ *	Free the host once all references to it have been dropped.
+ */
+void mmc_free_host(struct mmc_host *host)
+{
+	mmc_free_host_sysfs(host);
+}
+
+EXPORT_SYMBOL(mmc_free_host);
+
+#ifdef CONFIG_PM
+
+/**
+ *	mmc_suspend_host - suspend a host
+ *	@host: mmc host
+ *	@state: suspend mode (PM_SUSPEND_xxx)
+ */
+int mmc_suspend_host(struct mmc_host *host, pm_message_t state)
+{
+	mmc_flush_scheduled_work();
+
+	mmc_bus_get(host);
+	if (host->bus_ops && !host->bus_dead) {
+		if (host->bus_ops->suspend)
+			host->bus_ops->suspend(host);
+		if (!host->bus_ops->resume) {
+			if (host->bus_ops->remove)
+				host->bus_ops->remove(host);
+
+			mmc_claim_host(host);
+			mmc_detach_bus(host);
+			mmc_release_host(host);
+		}
+	}
+	mmc_bus_put(host);
+
+	mmc_power_off(host);
+
+	return 0;
+}
+
+EXPORT_SYMBOL(mmc_suspend_host);
+
+/**
+ *	mmc_resume_host - resume a previously suspended host
+ *	@host: mmc host
+ */
+int mmc_resume_host(struct mmc_host *host)
+{
+	mmc_bus_get(host);
+	if (host->bus_ops && !host->bus_dead) {
+		mmc_power_up(host);
+		BUG_ON(!host->bus_ops->resume);
+		host->bus_ops->resume(host);
+	}
+	mmc_bus_put(host);
+
+	/*
+	 * We add a slight delay here so that resume can progress
+	 * in parallel.
+	 */
+	mmc_detect_change(host, 1);
+
+	return 0;
+}
+
+EXPORT_SYMBOL(mmc_resume_host);
+
+#endif
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h
new file mode 100644
index 0000000..177264d
--- /dev/null
+++ b/drivers/mmc/core/core.h
@@ -0,0 +1,70 @@
+/*
+ *  linux/drivers/mmc/core/core.h
+ *
+ *  Copyright (C) 2003 Russell King, All Rights Reserved.
+ *  Copyright 2007 Pierre Ossman
+ *
+ * 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 _MMC_CORE_CORE_H
+#define _MMC_CORE_CORE_H
+
+#include <linux/delay.h>
+
+#define MMC_CMD_RETRIES        3
+
+struct mmc_bus_ops {
+	void (*remove)(struct mmc_host *);
+	void (*detect)(struct mmc_host *);
+	void (*suspend)(struct mmc_host *);
+	void (*resume)(struct mmc_host *);
+};
+
+void mmc_attach_bus(struct mmc_host *host, const struct mmc_bus_ops *ops);
+void mmc_detach_bus(struct mmc_host *host);
+
+void __mmc_release_bus(struct mmc_host *host);
+
+static inline void mmc_bus_get(struct mmc_host *host)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&host->lock, flags);
+	host->bus_refs++;
+	spin_unlock_irqrestore(&host->lock, flags);
+}
+
+static inline void mmc_bus_put(struct mmc_host *host)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&host->lock, flags);
+	host->bus_refs--;
+	if ((host->bus_refs == 0) && host->bus_ops)
+		__mmc_release_bus(host);
+	spin_unlock_irqrestore(&host->lock, flags);
+}
+
+void mmc_set_chip_select(struct mmc_host *host, int mode);
+void mmc_set_clock(struct mmc_host *host, unsigned int hz);
+void mmc_set_bus_mode(struct mmc_host *host, unsigned int mode);
+void mmc_set_bus_width(struct mmc_host *host, unsigned int width);
+u32 mmc_select_voltage(struct mmc_host *host, u32 ocr);
+void mmc_set_timing(struct mmc_host *host, unsigned int timing);
+
+struct mmc_card *mmc_alloc_card(struct mmc_host *host);
+
+static inline void mmc_delay(unsigned int ms)
+{
+	if (ms < 1000 / HZ) {
+		cond_resched();
+		mdelay(ms);
+	} else {
+		msleep(ms);
+	}
+}
+
+#endif
+
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
new file mode 100644
index 0000000..42cc286
--- /dev/null
+++ b/drivers/mmc/core/mmc.c
@@ -0,0 +1,537 @@
+/*
+ *  linux/drivers/mmc/mmc.c
+ *
+ *  Copyright (C) 2003-2004 Russell King, All Rights Reserved.
+ *  Copyright (C) 2005-2007 Pierre Ossman, All Rights Reserved.
+ *  MMCv4 support Copyright (C) 2006 Philip Langdale, 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/err.h>
+
+#include <linux/mmc/host.h>
+#include <linux/mmc/card.h>
+#include <linux/mmc/mmc.h>
+
+#include "core.h"
+#include "sysfs.h"
+#include "mmc_ops.h"
+
+static const unsigned int tran_exp[] = {
+	10000,		100000,		1000000,	10000000,
+	0,		0,		0,		0
+};
+
+static const unsigned char tran_mant[] = {
+	0,	10,	12,	13,	15,	20,	25,	30,
+	35,	40,	45,	50,	55,	60,	70,	80,
+};
+
+static const unsigned int tacc_exp[] = {
+	1,	10,	100,	1000,	10000,	100000,	1000000, 10000000,
+};
+
+static const unsigned int tacc_mant[] = {
+	0,	10,	12,	13,	15,	20,	25,	30,
+	35,	40,	45,	50,	55,	60,	70,	80,
+};
+
+#define UNSTUFF_BITS(resp,start,size)					\
+	({								\
+		const int __size = size;				\
+		const u32 __mask = (__size < 32 ? 1 << __size : 0) - 1;	\
+		const int __off = 3 - ((start) / 32);			\
+		const int __shft = (start) & 31;			\
+		u32 __res;						\
+									\
+		__res = resp[__off] >> __shft;				\
+		if (__size + __shft > 32)				\
+			__res |= resp[__off-1] << ((32 - __shft) % 32);	\
+		__res & __mask;						\
+	})
+
+/*
+ * Given the decoded CSD structure, decode the raw CID to our CID structure.
+ */
+static int mmc_decode_cid(struct mmc_card *card)
+{
+	u32 *resp = card->raw_cid;
+
+	/*
+	 * The selection of the format here is based upon published
+	 * specs from sandisk and from what people have reported.
+	 */
+	switch (card->csd.mmca_vsn) {
+	case 0: /* MMC v1.0 - v1.2 */
+	case 1: /* MMC v1.4 */
+		card->cid.manfid	= UNSTUFF_BITS(resp, 104, 24);
+		card->cid.prod_name[0]	= UNSTUFF_BITS(resp, 96, 8);
+		card->cid.prod_name[1]	= UNSTUFF_BITS(resp, 88, 8);
+		card->cid.prod_name[2]	= UNSTUFF_BITS(resp, 80, 8);
+		card->cid.prod_name[3]	= UNSTUFF_BITS(resp, 72, 8);
+		card->cid.prod_name[4]	= UNSTUFF_BITS(resp, 64, 8);
+		card->cid.prod_name[5]	= UNSTUFF_BITS(resp, 56, 8);
+		card->cid.prod_name[6]	= UNSTUFF_BITS(resp, 48, 8);
+		card->cid.hwrev		= UNSTUFF_BITS(resp, 44, 4);
+		card->cid.fwrev		= UNSTUFF_BITS(resp, 40, 4);
+		card->cid.serial	= UNSTUFF_BITS(resp, 16, 24);
+		card->cid.month		= UNSTUFF_BITS(resp, 12, 4);
+		card->cid.year		= UNSTUFF_BITS(resp, 8, 4) + 1997;
+		break;
+
+	case 2: /* MMC v2.0 - v2.2 */
+	case 3: /* MMC v3.1 - v3.3 */
+	case 4: /* MMC v4 */
+		card->cid.manfid	= UNSTUFF_BITS(resp, 120, 8);
+		card->cid.oemid		= UNSTUFF_BITS(resp, 104, 16);
+		card->cid.prod_name[0]	= UNSTUFF_BITS(resp, 96, 8);
+		card->cid.prod_name[1]	= UNSTUFF_BITS(resp, 88, 8);
+		card->cid.prod_name[2]	= UNSTUFF_BITS(resp, 80, 8);
+		card->cid.prod_name[3]	= UNSTUFF_BITS(resp, 72, 8);
+		card->cid.prod_name[4]	= UNSTUFF_BITS(resp, 64, 8);
+		card->cid.prod_name[5]	= UNSTUFF_BITS(resp, 56, 8);
+		card->cid.serial	= UNSTUFF_BITS(resp, 16, 32);
+		card->cid.month		= UNSTUFF_BITS(resp, 12, 4);
+		card->cid.year		= UNSTUFF_BITS(resp, 8, 4) + 1997;
+		break;
+
+	default:
+		printk("%s: card has unknown MMCA version %d\n",
+			mmc_hostname(card->host), card->csd.mmca_vsn);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/*
+ * Given a 128-bit response, decode to our card CSD structure.
+ */
+static int mmc_decode_csd(struct mmc_card *card)
+{
+	struct mmc_csd *csd = &card->csd;
+	unsigned int e, m, csd_struct;
+	u32 *resp = card->raw_csd;
+
+	/*
+	 * We only understand CSD structure v1.1 and v1.2.
+	 * v1.2 has extra information in bits 15, 11 and 10.
+	 */
+	csd_struct = UNSTUFF_BITS(resp, 126, 2);
+	if (csd_struct != 1 && csd_struct != 2) {
+		printk("%s: unrecognised CSD structure version %d\n",
+			mmc_hostname(card->host), csd_struct);
+		return -EINVAL;
+	}
+
+	csd->mmca_vsn	 = UNSTUFF_BITS(resp, 122, 4);
+	m = UNSTUFF_BITS(resp, 115, 4);
+	e = UNSTUFF_BITS(resp, 112, 3);
+	csd->tacc_ns	 = (tacc_exp[e] * tacc_mant[m] + 9) / 10;
+	csd->tacc_clks	 = UNSTUFF_BITS(resp, 104, 8) * 100;
+
+	m = UNSTUFF_BITS(resp, 99, 4);
+	e = UNSTUFF_BITS(resp, 96, 3);
+	csd->max_dtr	  = tran_exp[e] * tran_mant[m];
+	csd->cmdclass	  = UNSTUFF_BITS(resp, 84, 12);
+
+	e = UNSTUFF_BITS(resp, 47, 3);
+	m = UNSTUFF_BITS(resp, 62, 12);
+	csd->capacity	  = (1 + m) << (e + 2);
+
+	csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4);
+	csd->read_partial = UNSTUFF_BITS(resp, 79, 1);
+	csd->write_misalign = UNSTUFF_BITS(resp, 78, 1);
+	csd->read_misalign = UNSTUFF_BITS(resp, 77, 1);
+	csd->r2w_factor = UNSTUFF_BITS(resp, 26, 3);
+	csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4);
+	csd->write_partial = UNSTUFF_BITS(resp, 21, 1);
+
+	return 0;
+}
+
+/*
+ * Read and decode extended CSD.
+ */
+static int mmc_read_ext_csd(struct mmc_card *card)
+{
+	int err;
+	u8 *ext_csd;
+
+	BUG_ON(!card);
+
+	err = MMC_ERR_FAILED;
+
+	if (card->csd.mmca_vsn < CSD_SPEC_VER_4)
+		return MMC_ERR_NONE;
+
+	/*
+	 * As the ext_csd is so large and mostly unused, we don't store the
+	 * raw block in mmc_card.
+	 */
+	ext_csd = kmalloc(512, GFP_KERNEL);
+	if (!ext_csd) {
+		printk(KERN_ERR "%s: could not allocate a buffer to "
+			"receive the ext_csd. mmc v4 cards will be "
+			"treated as v3.\n", mmc_hostname(card->host));
+		return MMC_ERR_FAILED;
+	}
+
+	err = mmc_send_ext_csd(card, ext_csd);
+	if (err != MMC_ERR_NONE) {
+		/*
+		 * High capacity cards should have this "magic" size
+		 * stored in their CSD.
+		 */
+		if (card->csd.capacity == (4096 * 512)) {
+			printk(KERN_ERR "%s: unable to read EXT_CSD "
+				"on a possible high capacity card. "
+				"Card will be ignored.\n",
+				mmc_hostname(card->host));
+		} else {
+			printk(KERN_WARNING "%s: unable to read "
+				"EXT_CSD, performance might "
+				"suffer.\n",
+				mmc_hostname(card->host));
+			err = MMC_ERR_NONE;
+		}
+		goto out;
+	}
+
+	card->ext_csd.sectors =
+		ext_csd[EXT_CSD_SEC_CNT + 0] << 0 |
+		ext_csd[EXT_CSD_SEC_CNT + 1] << 8 |
+		ext_csd[EXT_CSD_SEC_CNT + 2] << 16 |
+		ext_csd[EXT_CSD_SEC_CNT + 3] << 24;
+	if (card->ext_csd.sectors)
+		mmc_card_set_blockaddr(card);
+
+	switch (ext_csd[EXT_CSD_CARD_TYPE]) {
+	case EXT_CSD_CARD_TYPE_52 | EXT_CSD_CARD_TYPE_26:
+		card->ext_csd.hs_max_dtr = 52000000;
+		break;
+	case EXT_CSD_CARD_TYPE_26:
+		card->ext_csd.hs_max_dtr = 26000000;
+		break;
+	default:
+		/* MMC v4 spec says this cannot happen */
+		printk(KERN_WARNING "%s: card is mmc v4 but doesn't "
+			"support any high-speed modes.\n",
+			mmc_hostname(card->host));
+		goto out;
+	}
+
+out:
+	kfree(ext_csd);
+
+	return err;
+}
+
+/*
+ * Handle the detection and initialisation of a card.
+ *
+ * In the case of a resume, "curcard" will contain the card
+ * we're trying to reinitialise.
+ */
+static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
+	struct mmc_card *oldcard)
+{
+	struct mmc_card *card;
+	int err;
+	u32 cid[4];
+	unsigned int max_dtr;
+
+	BUG_ON(!host);
+	BUG_ON(!host->claimed);
+
+	/*
+	 * Since we're changing the OCR value, we seem to
+	 * need to tell some cards to go back to the idle
+	 * state.  We wait 1ms to give cards time to
+	 * respond.
+	 */
+	mmc_go_idle(host);
+
+	/* The extra bit indicates that we support high capacity */
+	err = mmc_send_op_cond(host, ocr | (1 << 30), NULL);
+	if (err != MMC_ERR_NONE)
+		goto err;
+
+	/*
+	 * Fetch CID from card.
+	 */
+	err = mmc_all_send_cid(host, cid);
+	if (err != MMC_ERR_NONE)
+		goto err;
+
+	if (oldcard) {
+		if (memcmp(cid, oldcard->raw_cid, sizeof(cid)) != 0)
+			goto err;
+
+		card = oldcard;
+	} else {
+		/*
+		 * Allocate card structure.
+		 */
+		card = mmc_alloc_card(host);
+		if (IS_ERR(card))
+			goto err;
+
+		card->type = MMC_TYPE_MMC;
+		card->rca = 1;
+		memcpy(card->raw_cid, cid, sizeof(card->raw_cid));
+	}
+
+	/*
+	 * Set card RCA.
+	 */
+	err = mmc_set_relative_addr(card);
+	if (err != MMC_ERR_NONE)
+		goto free_card;
+
+	mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL);
+
+	if (!oldcard) {
+		/*
+		 * Fetch CSD from card.
+		 */
+		err = mmc_send_csd(card, card->raw_csd);
+		if (err != MMC_ERR_NONE)
+			goto free_card;
+
+		err = mmc_decode_csd(card);
+		if (err < 0)
+			goto free_card;
+		err = mmc_decode_cid(card);
+		if (err < 0)
+			goto free_card;
+	}
+
+	/*
+	 * Select card, as all following commands rely on that.
+	 */
+	err = mmc_select_card(card);
+	if (err != MMC_ERR_NONE)
+		goto free_card;
+
+	if (!oldcard) {
+		/*
+		 * Fetch and process extened CSD.
+		 */
+		err = mmc_read_ext_csd(card);
+		if (err != MMC_ERR_NONE)
+			goto free_card;
+	}
+
+	/*
+	 * Activate high speed (if supported)
+	 */
+	if ((card->ext_csd.hs_max_dtr != 0) &&
+		(host->caps & MMC_CAP_MMC_HIGHSPEED)) {
+		err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+			EXT_CSD_HS_TIMING, 1);
+		if (err != MMC_ERR_NONE)
+			goto free_card;
+
+		mmc_card_set_highspeed(card);
+
+		mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
+	}
+
+	/*
+	 * Compute bus speed.
+	 */
+	max_dtr = (unsigned int)-1;
+
+	if (mmc_card_highspeed(card)) {
+		if (max_dtr > card->ext_csd.hs_max_dtr)
+			max_dtr = card->ext_csd.hs_max_dtr;
+	} else if (max_dtr > card->csd.max_dtr) {
+		max_dtr = card->csd.max_dtr;
+	}
+
+	mmc_set_clock(host, max_dtr);
+
+	/*
+	 * Activate wide bus (if supported).
+	 */
+	if ((card->csd.mmca_vsn >= CSD_SPEC_VER_4) &&
+		(host->caps & MMC_CAP_4_BIT_DATA)) {
+		err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+			EXT_CSD_BUS_WIDTH, EXT_CSD_BUS_WIDTH_4);
+		if (err != MMC_ERR_NONE)
+			goto free_card;
+
+		mmc_set_bus_width(card->host, MMC_BUS_WIDTH_4);
+	}
+
+	if (!oldcard)
+		host->card = card;
+
+	return MMC_ERR_NONE;
+
+free_card:
+	if (!oldcard)
+		mmc_remove_card(card);
+err:
+
+	return MMC_ERR_FAILED;
+}
+
+/*
+ * Host is being removed. Free up the current card.
+ */
+static void mmc_remove(struct mmc_host *host)
+{
+	BUG_ON(!host);
+	BUG_ON(!host->card);
+
+	mmc_remove_card(host->card);
+	host->card = NULL;
+}
+
+/*
+ * Card detection callback from host.
+ */
+static void mmc_detect(struct mmc_host *host)
+{
+	int err;
+
+	BUG_ON(!host);
+	BUG_ON(!host->card);
+
+	mmc_claim_host(host);
+
+	/*
+	 * Just check if our card has been removed.
+	 */
+	err = mmc_send_status(host->card, NULL);
+
+	mmc_release_host(host);
+
+	if (err != MMC_ERR_NONE) {
+		mmc_remove_card(host->card);
+		host->card = NULL;
+
+		mmc_claim_host(host);
+		mmc_detach_bus(host);
+		mmc_release_host(host);
+	}
+}
+
+#ifdef CONFIG_MMC_UNSAFE_RESUME
+
+/*
+ * Suspend callback from host.
+ */
+static void mmc_suspend(struct mmc_host *host)
+{
+	BUG_ON(!host);
+	BUG_ON(!host->card);
+
+	mmc_claim_host(host);
+	mmc_deselect_cards(host);
+	host->card->state &= ~MMC_STATE_HIGHSPEED;
+	mmc_release_host(host);
+}
+
+/*
+ * Resume callback from host.
+ *
+ * This function tries to determine if the same card is still present
+ * and, if so, restore all state to it.
+ */
+static void mmc_resume(struct mmc_host *host)
+{
+	int err;
+
+	BUG_ON(!host);
+	BUG_ON(!host->card);
+
+	mmc_claim_host(host);
+
+	err = mmc_sd_init_card(host, host->ocr, host->card);
+	if (err != MMC_ERR_NONE) {
+		mmc_remove_card(host->card);
+		host->card = NULL;
+
+		mmc_detach_bus(host);
+	}
+
+	mmc_release_host(host);
+}
+
+#else
+
+#define mmc_suspend NULL
+#define mmc_resume NULL
+
+#endif
+
+static const struct mmc_bus_ops mmc_ops = {
+	.remove = mmc_remove,
+	.detect = mmc_detect,
+	.suspend = mmc_suspend,
+	.resume = mmc_resume,
+};
+
+/*
+ * Starting point for MMC card init.
+ */
+int mmc_attach_mmc(struct mmc_host *host, u32 ocr)
+{
+	int err;
+
+	BUG_ON(!host);
+	BUG_ON(!host->claimed);
+
+	mmc_attach_bus(host, &mmc_ops);
+
+	/*
+	 * Sanity check the voltages that the card claims to
+	 * support.
+	 */
+	if (ocr & 0x7F) {
+		printk(KERN_WARNING "%s: card claims to support voltages "
+		       "below the defined range. These will be ignored.\n",
+		       mmc_hostname(host));
+		ocr &= ~0x7F;
+	}
+
+	host->ocr = mmc_select_voltage(host, ocr);
+
+	/*
+	 * Can we support the voltage of the card?
+	 */
+	if (!host->ocr)
+		goto err;
+
+	/*
+	 * Detect and init the card.
+	 */
+	err = mmc_sd_init_card(host, host->ocr, NULL);
+	if (err != MMC_ERR_NONE)
+		goto err;
+
+	mmc_release_host(host);
+
+	err = mmc_register_card(host->card);
+	if (err)
+		goto reclaim_host;
+
+	return 0;
+
+reclaim_host:
+	mmc_claim_host(host);
+	mmc_remove_card(host->card);
+	host->card = NULL;
+err:
+	mmc_detach_bus(host);
+	mmc_release_host(host);
+
+	return 0;
+}
+
diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c
new file mode 100644
index 0000000..7dd720f
--- /dev/null
+++ b/drivers/mmc/core/mmc_ops.c
@@ -0,0 +1,276 @@
+/*
+ *  linux/drivers/mmc/mmc_ops.h
+ *
+ *  Copyright 2006-2007 Pierre Ossman
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ */
+
+#include <linux/types.h>
+#include <asm/scatterlist.h>
+#include <linux/scatterlist.h>
+
+#include <linux/mmc/host.h>
+#include <linux/mmc/card.h>
+#include <linux/mmc/mmc.h>
+
+#include "core.h"
+#include "mmc_ops.h"
+
+static int _mmc_select_card(struct mmc_host *host, struct mmc_card *card)
+{
+	int err;
+	struct mmc_command cmd;
+
+	BUG_ON(!host);
+
+	memset(&cmd, 0, sizeof(struct mmc_command));
+
+	cmd.opcode = MMC_SELECT_CARD;
+
+	if (card) {
+		cmd.arg = card->rca << 16;
+		cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
+	} else {
+		cmd.arg = 0;
+		cmd.flags = MMC_RSP_NONE | MMC_CMD_AC;
+	}
+
+	err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES);
+	if (err != MMC_ERR_NONE)
+		return err;
+
+	return MMC_ERR_NONE;
+}
+
+int mmc_select_card(struct mmc_card *card)
+{
+	BUG_ON(!card);
+
+	return _mmc_select_card(card->host, card);
+}
+
+int mmc_deselect_cards(struct mmc_host *host)
+{
+	return _mmc_select_card(host, NULL);
+}
+
+int mmc_go_idle(struct mmc_host *host)
+{
+	int err;
+	struct mmc_command cmd;
+
+	mmc_set_chip_select(host, MMC_CS_HIGH);
+
+	mmc_delay(1);
+
+	memset(&cmd, 0, sizeof(struct mmc_command));
+
+	cmd.opcode = MMC_GO_IDLE_STATE;
+	cmd.arg = 0;
+	cmd.flags = MMC_RSP_NONE | MMC_CMD_BC;
+
+	err = mmc_wait_for_cmd(host, &cmd, 0);
+
+	mmc_delay(1);
+
+	mmc_set_chip_select(host, MMC_CS_DONTCARE);
+
+	mmc_delay(1);
+
+	return err;
+}
+
+int mmc_send_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr)
+{
+	struct mmc_command cmd;
+	int i, err = 0;
+
+	BUG_ON(!host);
+
+	memset(&cmd, 0, sizeof(struct mmc_command));
+
+	cmd.opcode = MMC_SEND_OP_COND;
+	cmd.arg = ocr;
+	cmd.flags = MMC_RSP_R3 | MMC_CMD_BCR;
+
+	for (i = 100; i; i--) {
+		err = mmc_wait_for_cmd(host, &cmd, 0);
+		if (err != MMC_ERR_NONE)
+			break;
+
+		if (cmd.resp[0] & MMC_CARD_BUSY || ocr == 0)
+			break;
+
+		err = MMC_ERR_TIMEOUT;
+
+		mmc_delay(10);
+	}
+
+	if (rocr)
+		*rocr = cmd.resp[0];
+
+	return err;
+}
+
+int mmc_all_send_cid(struct mmc_host *host, u32 *cid)
+{
+	int err;
+	struct mmc_command cmd;
+
+	BUG_ON(!host);
+	BUG_ON(!cid);
+
+	memset(&cmd, 0, sizeof(struct mmc_command));
+
+	cmd.opcode = MMC_ALL_SEND_CID;
+	cmd.arg = 0;
+	cmd.flags = MMC_RSP_R2 | MMC_CMD_BCR;
+
+	err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES);
+	if (err != MMC_ERR_NONE)
+		return err;
+
+	memcpy(cid, cmd.resp, sizeof(u32) * 4);
+
+	return MMC_ERR_NONE;
+}
+
+int mmc_set_relative_addr(struct mmc_card *card)
+{
+	int err;
+	struct mmc_command cmd;
+
+	BUG_ON(!card);
+	BUG_ON(!card->host);
+
+	memset(&cmd, 0, sizeof(struct mmc_command));
+
+	cmd.opcode = MMC_SET_RELATIVE_ADDR;
+	cmd.arg = card->rca << 16;
+	cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
+
+	err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES);
+	if (err != MMC_ERR_NONE)
+		return err;
+
+	return MMC_ERR_NONE;
+}
+
+int mmc_send_csd(struct mmc_card *card, u32 *csd)
+{
+	int err;
+	struct mmc_command cmd;
+
+	BUG_ON(!card);
+	BUG_ON(!card->host);
+	BUG_ON(!csd);
+
+	memset(&cmd, 0, sizeof(struct mmc_command));
+
+	cmd.opcode = MMC_SEND_CSD;
+	cmd.arg = card->rca << 16;
+	cmd.flags = MMC_RSP_R2 | MMC_CMD_AC;
+
+	err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES);
+	if (err != MMC_ERR_NONE)
+		return err;
+
+	memcpy(csd, cmd.resp, sizeof(u32) * 4);
+
+	return MMC_ERR_NONE;
+}
+
+int mmc_send_ext_csd(struct mmc_card *card, u8 *ext_csd)
+{
+	struct mmc_request mrq;
+	struct mmc_command cmd;
+	struct mmc_data data;
+	struct scatterlist sg;
+
+	BUG_ON(!card);
+	BUG_ON(!card->host);
+	BUG_ON(!ext_csd);
+
+	memset(&mrq, 0, sizeof(struct mmc_request));
+	memset(&cmd, 0, sizeof(struct mmc_command));
+	memset(&data, 0, sizeof(struct mmc_data));
+
+	mrq.cmd = &cmd;
+	mrq.data = &data;
+
+	cmd.opcode = MMC_SEND_EXT_CSD;
+	cmd.arg = 0;
+	cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
+
+	data.blksz = 512;
+	data.blocks = 1;
+	data.flags = MMC_DATA_READ;
+	data.sg = &sg;
+	data.sg_len = 1;
+
+	sg_init_one(&sg, ext_csd, 512);
+
+	mmc_set_data_timeout(&data, card, 0);
+
+	mmc_wait_for_req(card->host, &mrq);
+
+	if (cmd.error != MMC_ERR_NONE)
+		return cmd.error;
+	if (data.error != MMC_ERR_NONE)
+		return data.error;
+
+	return MMC_ERR_NONE;
+}
+
+int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value)
+{
+	int err;
+	struct mmc_command cmd;
+
+	BUG_ON(!card);
+	BUG_ON(!card->host);
+
+	memset(&cmd, 0, sizeof(struct mmc_command));
+
+	cmd.opcode = MMC_SWITCH;
+	cmd.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
+		  (index << 16) |
+		  (value << 8) |
+		  set;
+	cmd.flags = MMC_RSP_R1B | MMC_CMD_AC;
+
+	err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES);
+	if (err != MMC_ERR_NONE)
+		return err;
+
+	return MMC_ERR_NONE;
+}
+
+int mmc_send_status(struct mmc_card *card, u32 *status)
+{
+	int err;
+	struct mmc_command cmd;
+
+	BUG_ON(!card);
+	BUG_ON(!card->host);
+
+	memset(&cmd, 0, sizeof(struct mmc_command));
+
+	cmd.opcode = MMC_SEND_STATUS;
+	cmd.arg = card->rca << 16;
+	cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
+
+	err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES);
+	if (err != MMC_ERR_NONE)
+		return err;
+
+	if (status)
+		*status = cmd.resp[0];
+
+	return MMC_ERR_NONE;
+}
+
diff --git a/drivers/mmc/core/mmc_ops.h b/drivers/mmc/core/mmc_ops.h
new file mode 100644
index 0000000..7a481e8
--- /dev/null
+++ b/drivers/mmc/core/mmc_ops.h
@@ -0,0 +1,27 @@
+/*
+ *  linux/drivers/mmc/mmc_ops.h
+ *
+ *  Copyright 2006-2007 Pierre Ossman
+ *
+ * This program is free software; you can redistribute it and/or 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 _MMC_MMC_OPS_H
+#define _MMC_MMC_OPS_H
+
+int mmc_select_card(struct mmc_card *card);
+int mmc_deselect_cards(struct mmc_host *host);
+int mmc_go_idle(struct mmc_host *host);
+int mmc_send_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr);
+int mmc_all_send_cid(struct mmc_host *host, u32 *cid);
+int mmc_set_relative_addr(struct mmc_card *card);
+int mmc_send_csd(struct mmc_card *card, u32 *csd);
+int mmc_send_ext_csd(struct mmc_card *card, u8 *ext_csd);
+int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value);
+int mmc_send_status(struct mmc_card *card, u32 *status);
+
+#endif
+
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
new file mode 100644
index 0000000..c1dfd03
--- /dev/null
+++ b/drivers/mmc/core/sd.c
@@ -0,0 +1,587 @@
+/*
+ *  linux/drivers/mmc/sd.c
+ *
+ *  Copyright (C) 2003-2004 Russell King, All Rights Reserved.
+ *  SD support Copyright (C) 2004 Ian Molton, All Rights Reserved.
+ *  Copyright (C) 2005-2007 Pierre Ossman, 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/err.h>
+
+#include <linux/mmc/host.h>
+#include <linux/mmc/card.h>
+#include <linux/mmc/mmc.h>
+
+#include "core.h"
+#include "sysfs.h"
+#include "mmc_ops.h"
+#include "sd_ops.h"
+
+#include "core.h"
+
+static const unsigned int tran_exp[] = {
+	10000,		100000,		1000000,	10000000,
+	0,		0,		0,		0
+};
+
+static const unsigned char tran_mant[] = {
+	0,	10,	12,	13,	15,	20,	25,	30,
+	35,	40,	45,	50,	55,	60,	70,	80,
+};
+
+static const unsigned int tacc_exp[] = {
+	1,	10,	100,	1000,	10000,	100000,	1000000, 10000000,
+};
+
+static const unsigned int tacc_mant[] = {
+	0,	10,	12,	13,	15,	20,	25,	30,
+	35,	40,	45,	50,	55,	60,	70,	80,
+};
+
+#define UNSTUFF_BITS(resp,start,size)					\
+	({								\
+		const int __size = size;				\
+		const u32 __mask = (__size < 32 ? 1 << __size : 0) - 1;	\
+		const int __off = 3 - ((start) / 32);			\
+		const int __shft = (start) & 31;			\
+		u32 __res;						\
+									\
+		__res = resp[__off] >> __shft;				\
+		if (__size + __shft > 32)				\
+			__res |= resp[__off-1] << ((32 - __shft) % 32);	\
+		__res & __mask;						\
+	})
+
+/*
+ * Given the decoded CSD structure, decode the raw CID to our CID structure.
+ */
+static void mmc_decode_cid(struct mmc_card *card)
+{
+	u32 *resp = card->raw_cid;
+
+	memset(&card->cid, 0, sizeof(struct mmc_cid));
+
+	/*
+	 * SD doesn't currently have a version field so we will
+	 * have to assume we can parse this.
+	 */
+	card->cid.manfid		= UNSTUFF_BITS(resp, 120, 8);
+	card->cid.oemid			= UNSTUFF_BITS(resp, 104, 16);
+	card->cid.prod_name[0]		= UNSTUFF_BITS(resp, 96, 8);
+	card->cid.prod_name[1]		= UNSTUFF_BITS(resp, 88, 8);
+	card->cid.prod_name[2]		= UNSTUFF_BITS(resp, 80, 8);
+	card->cid.prod_name[3]		= UNSTUFF_BITS(resp, 72, 8);
+	card->cid.prod_name[4]		= UNSTUFF_BITS(resp, 64, 8);
+	card->cid.hwrev			= UNSTUFF_BITS(resp, 60, 4);
+	card->cid.fwrev			= UNSTUFF_BITS(resp, 56, 4);
+	card->cid.serial		= UNSTUFF_BITS(resp, 24, 32);
+	card->cid.year			= UNSTUFF_BITS(resp, 12, 8);
+	card->cid.month			= UNSTUFF_BITS(resp, 8, 4);
+
+	card->cid.year += 2000; /* SD cards year offset */
+}
+
+/*
+ * Given a 128-bit response, decode to our card CSD structure.
+ */
+static int mmc_decode_csd(struct mmc_card *card)
+{
+	struct mmc_csd *csd = &card->csd;
+	unsigned int e, m, csd_struct;
+	u32 *resp = card->raw_csd;
+
+	csd_struct = UNSTUFF_BITS(resp, 126, 2);
+
+	switch (csd_struct) {
+	case 0:
+		m = UNSTUFF_BITS(resp, 115, 4);
+		e = UNSTUFF_BITS(resp, 112, 3);
+		csd->tacc_ns	 = (tacc_exp[e] * tacc_mant[m] + 9) / 10;
+		csd->tacc_clks	 = UNSTUFF_BITS(resp, 104, 8) * 100;
+
+		m = UNSTUFF_BITS(resp, 99, 4);
+		e = UNSTUFF_BITS(resp, 96, 3);
+		csd->max_dtr	  = tran_exp[e] * tran_mant[m];
+		csd->cmdclass	  = UNSTUFF_BITS(resp, 84, 12);
+
+		e = UNSTUFF_BITS(resp, 47, 3);
+		m = UNSTUFF_BITS(resp, 62, 12);
+		csd->capacity	  = (1 + m) << (e + 2);
+
+		csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4);
+		csd->read_partial = UNSTUFF_BITS(resp, 79, 1);
+		csd->write_misalign = UNSTUFF_BITS(resp, 78, 1);
+		csd->read_misalign = UNSTUFF_BITS(resp, 77, 1);
+		csd->r2w_factor = UNSTUFF_BITS(resp, 26, 3);
+		csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4);
+		csd->write_partial = UNSTUFF_BITS(resp, 21, 1);
+		break;
+	case 1:
+		/*
+		 * This is a block-addressed SDHC card. Most
+		 * interesting fields are unused and have fixed
+		 * values. To avoid getting tripped by buggy cards,
+		 * we assume those fixed values ourselves.
+		 */
+		mmc_card_set_blockaddr(card);
+
+		csd->tacc_ns	 = 0; /* Unused */
+		csd->tacc_clks	 = 0; /* Unused */
+
+		m = UNSTUFF_BITS(resp, 99, 4);
+		e = UNSTUFF_BITS(resp, 96, 3);
+		csd->max_dtr	  = tran_exp[e] * tran_mant[m];
+		csd->cmdclass	  = UNSTUFF_BITS(resp, 84, 12);
+
+		m = UNSTUFF_BITS(resp, 48, 22);
+		csd->capacity     = (1 + m) << 10;
+
+		csd->read_blkbits = 9;
+		csd->read_partial = 0;
+		csd->write_misalign = 0;
+		csd->read_misalign = 0;
+		csd->r2w_factor = 4; /* Unused */
+		csd->write_blkbits = 9;
+		csd->write_partial = 0;
+		break;
+	default:
+		printk("%s: unrecognised CSD structure version %d\n",
+			mmc_hostname(card->host), csd_struct);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/*
+ * Given a 64-bit response, decode to our card SCR structure.
+ */
+static int mmc_decode_scr(struct mmc_card *card)
+{
+	struct sd_scr *scr = &card->scr;
+	unsigned int scr_struct;
+	u32 resp[4];
+
+	BUG_ON(!mmc_card_sd(card));
+
+	resp[3] = card->raw_scr[1];
+	resp[2] = card->raw_scr[0];
+
+	scr_struct = UNSTUFF_BITS(resp, 60, 4);
+	if (scr_struct != 0) {
+		printk("%s: unrecognised SCR structure version %d\n",
+			mmc_hostname(card->host), scr_struct);
+		return -EINVAL;
+	}
+
+	scr->sda_vsn = UNSTUFF_BITS(resp, 56, 4);
+	scr->bus_widths = UNSTUFF_BITS(resp, 48, 4);
+
+	return 0;
+}
+
+/*
+ * Fetches and decodes switch information
+ */
+static int mmc_read_switch(struct mmc_card *card)
+{
+	int err;
+	u8 *status;
+
+	err = MMC_ERR_FAILED;
+
+	status = kmalloc(64, GFP_KERNEL);
+	if (!status) {
+		printk("%s: could not allocate a buffer for switch "
+		       "capabilities.\n",
+			mmc_hostname(card->host));
+		return err;
+	}
+
+	err = mmc_sd_switch(card, 0, 0, 1, status);
+	if (err != MMC_ERR_NONE) {
+		/*
+		 * Card not supporting high-speed will ignore the
+		 * command.
+		 */
+		err = MMC_ERR_NONE;
+		goto out;
+	}
+
+	if (status[13] & 0x02)
+		card->sw_caps.hs_max_dtr = 50000000;
+
+out:
+	kfree(status);
+
+	return err;
+}
+
+/*
+ * Test if the card supports high-speed mode and, if so, switch to it.
+ */
+static int mmc_switch_hs(struct mmc_card *card)
+{
+	int err;
+	u8 *status;
+
+	if (!(card->host->caps & MMC_CAP_SD_HIGHSPEED))
+		return MMC_ERR_NONE;
+
+	if (card->sw_caps.hs_max_dtr == 0)
+		return MMC_ERR_NONE;
+
+	err = MMC_ERR_FAILED;
+
+	status = kmalloc(64, GFP_KERNEL);
+	if (!status) {
+		printk("%s: could not allocate a buffer for switch "
+		       "capabilities.\n",
+			mmc_hostname(card->host));
+		return err;
+	}
+
+	err = mmc_sd_switch(card, 1, 0, 1, status);
+	if (err != MMC_ERR_NONE)
+		goto out;
+
+	if ((status[16] & 0xF) != 1) {
+		printk(KERN_WARNING "%s: Problem switching card "
+			"into high-speed mode!\n",
+			mmc_hostname(card->host));
+	} else {
+		mmc_card_set_highspeed(card);
+		mmc_set_timing(card->host, MMC_TIMING_SD_HS);
+	}
+
+out:
+	kfree(status);
+
+	return err;
+}
+
+/*
+ * Handle the detection and initialisation of a card.
+ *
+ * In the case of a resume, "curcard" will contain the card
+ * we're trying to reinitialise.
+ */
+static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
+	struct mmc_card *oldcard)
+{
+	struct mmc_card *card;
+	int err;
+	u32 cid[4];
+	unsigned int max_dtr;
+
+	BUG_ON(!host);
+	BUG_ON(!host->claimed);
+
+	/*
+	 * Since we're changing the OCR value, we seem to
+	 * need to tell some cards to go back to the idle
+	 * state.  We wait 1ms to give cards time to
+	 * respond.
+	 */
+	mmc_go_idle(host);
+
+	/*
+	 * If SD_SEND_IF_COND indicates an SD 2.0
+	 * compliant card and we should set bit 30
+	 * of the ocr to indicate that we can handle
+	 * block-addressed SDHC cards.
+	 */
+	err = mmc_send_if_cond(host, ocr);
+	if (err == MMC_ERR_NONE)
+		ocr |= 1 << 30;
+
+	err = mmc_send_app_op_cond(host, ocr, NULL);
+	if (err != MMC_ERR_NONE)
+		goto err;
+
+	/*
+	 * Fetch CID from card.
+	 */
+	err = mmc_all_send_cid(host, cid);
+	if (err != MMC_ERR_NONE)
+		goto err;
+
+	if (oldcard) {
+		if (memcmp(cid, oldcard->raw_cid, sizeof(cid)) != 0)
+			goto err;
+
+		card = oldcard;
+	} else {
+		/*
+		 * Allocate card structure.
+		 */
+		card = mmc_alloc_card(host);
+		if (IS_ERR(card))
+			goto err;
+
+		card->type = MMC_TYPE_SD;
+		memcpy(card->raw_cid, cid, sizeof(card->raw_cid));
+	}
+
+	/*
+	 * Set card RCA.
+	 */
+	err = mmc_send_relative_addr(host, &card->rca);
+	if (err != MMC_ERR_NONE)
+		goto free_card;
+
+	mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL);
+
+	if (!oldcard) {
+		/*
+		 * Fetch CSD from card.
+		 */
+		err = mmc_send_csd(card, card->raw_csd);
+		if (err != MMC_ERR_NONE)
+			goto free_card;
+
+		err = mmc_decode_csd(card);
+		if (err < 0)
+			goto free_card;
+
+		mmc_decode_cid(card);
+	}
+
+	/*
+	 * Select card, as all following commands rely on that.
+	 */
+	err = mmc_select_card(card);
+	if (err != MMC_ERR_NONE)
+		goto free_card;
+
+	if (!oldcard) {
+		/*
+		 * Fetch SCR from card.
+		 */
+		err = mmc_app_send_scr(card, card->raw_scr);
+		if (err != MMC_ERR_NONE)
+			goto free_card;
+
+		err = mmc_decode_scr(card);
+		if (err < 0)
+			goto free_card;
+
+		/*
+		 * Fetch switch information from card.
+		 */
+		err = mmc_read_switch(card);
+		if (err != MMC_ERR_NONE)
+			goto free_card;
+	}
+
+	/*
+	 * Attempt to change to high-speed (if supported)
+	 */
+	err = mmc_switch_hs(card);
+	if (err != MMC_ERR_NONE)
+		goto free_card;
+
+	/*
+	 * Compute bus speed.
+	 */
+	max_dtr = (unsigned int)-1;
+
+	if (mmc_card_highspeed(card)) {
+		if (max_dtr > card->sw_caps.hs_max_dtr)
+			max_dtr = card->sw_caps.hs_max_dtr;
+	} else if (max_dtr > card->csd.max_dtr) {
+		max_dtr = card->csd.max_dtr;
+	}
+
+	mmc_set_clock(host, max_dtr);
+
+	/*
+	 * Switch to wider bus (if supported).
+	 */
+	if ((host->caps && MMC_CAP_4_BIT_DATA) &&
+		(card->scr.bus_widths & SD_SCR_BUS_WIDTH_4)) {
+		err = mmc_app_set_bus_width(card, MMC_BUS_WIDTH_4);
+		if (err != MMC_ERR_NONE)
+			goto free_card;
+
+		mmc_set_bus_width(host, MMC_BUS_WIDTH_4);
+	}
+
+	if (!oldcard)
+		host->card = card;
+
+	return MMC_ERR_NONE;
+
+free_card:
+	if (!oldcard)
+		mmc_remove_card(card);
+err:
+
+	return MMC_ERR_FAILED;
+}
+
+/*
+ * Host is being removed. Free up the current card.
+ */
+static void mmc_sd_remove(struct mmc_host *host)
+{
+	BUG_ON(!host);
+	BUG_ON(!host->card);
+
+	mmc_remove_card(host->card);
+	host->card = NULL;
+}
+
+/*
+ * Card detection callback from host.
+ */
+static void mmc_sd_detect(struct mmc_host *host)
+{
+	int err;
+
+	BUG_ON(!host);
+	BUG_ON(!host->card);
+
+	mmc_claim_host(host);
+
+	/*
+	 * Just check if our card has been removed.
+	 */
+	err = mmc_send_status(host->card, NULL);
+
+	mmc_release_host(host);
+
+	if (err != MMC_ERR_NONE) {
+		mmc_remove_card(host->card);
+		host->card = NULL;
+
+		mmc_claim_host(host);
+		mmc_detach_bus(host);
+		mmc_release_host(host);
+	}
+}
+
+#ifdef CONFIG_MMC_UNSAFE_RESUME
+
+/*
+ * Suspend callback from host.
+ */
+static void mmc_sd_suspend(struct mmc_host *host)
+{
+	BUG_ON(!host);
+	BUG_ON(!host->card);
+
+	mmc_claim_host(host);
+	mmc_deselect_cards(host);
+	host->card->state &= ~MMC_STATE_HIGHSPEED;
+	mmc_release_host(host);
+}
+
+/*
+ * Resume callback from host.
+ *
+ * This function tries to determine if the same card is still present
+ * and, if so, restore all state to it.
+ */
+static void mmc_sd_resume(struct mmc_host *host)
+{
+	int err;
+
+	BUG_ON(!host);
+	BUG_ON(!host->card);
+
+	mmc_claim_host(host);
+
+	err = mmc_sd_init_card(host, host->ocr, host->card);
+	if (err != MMC_ERR_NONE) {
+		mmc_remove_card(host->card);
+		host->card = NULL;
+
+		mmc_detach_bus(host);
+	}
+
+	mmc_release_host(host);
+}
+
+#else
+
+#define mmc_sd_suspend NULL
+#define mmc_sd_resume NULL
+
+#endif
+
+static const struct mmc_bus_ops mmc_sd_ops = {
+	.remove = mmc_sd_remove,
+	.detect = mmc_sd_detect,
+	.suspend = mmc_sd_suspend,
+	.resume = mmc_sd_resume,
+};
+
+/*
+ * Starting point for SD card init.
+ */
+int mmc_attach_sd(struct mmc_host *host, u32 ocr)
+{
+	int err;
+
+	BUG_ON(!host);
+	BUG_ON(!host->claimed);
+
+	mmc_attach_bus(host, &mmc_sd_ops);
+
+	/*
+	 * Sanity check the voltages that the card claims to
+	 * support.
+	 */
+	if (ocr & 0x7F) {
+		printk(KERN_WARNING "%s: card claims to support voltages "
+		       "below the defined range. These will be ignored.\n",
+		       mmc_hostname(host));
+		ocr &= ~0x7F;
+	}
+
+	if (ocr & MMC_VDD_165_195) {
+		printk(KERN_WARNING "%s: SD card claims to support the "
+		       "incompletely defined 'low voltage range'. This "
+		       "will be ignored.\n", mmc_hostname(host));
+		ocr &= ~MMC_VDD_165_195;
+	}
+
+	host->ocr = mmc_select_voltage(host, ocr);
+
+	/*
+	 * Can we support the voltage(s) of the card(s)?
+	 */
+	if (!host->ocr)
+		goto err;
+
+	/*
+	 * Detect and init the card.
+	 */
+	err = mmc_sd_init_card(host, host->ocr, NULL);
+	if (err != MMC_ERR_NONE)
+		goto err;
+
+	mmc_release_host(host);
+
+	err = mmc_register_card(host->card);
+	if (err)
+		goto reclaim_host;
+
+	return 0;
+
+reclaim_host:
+	mmc_claim_host(host);
+	mmc_remove_card(host->card);
+	host->card = NULL;
+err:
+	mmc_detach_bus(host);
+	mmc_release_host(host);
+
+	return 0;
+}
+
diff --git a/drivers/mmc/core/sd_ops.c b/drivers/mmc/core/sd_ops.c
new file mode 100644
index 0000000..9697ce5
--- /dev/null
+++ b/drivers/mmc/core/sd_ops.c
@@ -0,0 +1,316 @@
+/*
+ *  linux/drivers/mmc/sd_ops.h
+ *
+ *  Copyright 2006-2007 Pierre Ossman
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ */
+
+#include <linux/types.h>
+#include <asm/scatterlist.h>
+#include <linux/scatterlist.h>
+
+#include <linux/mmc/host.h>
+#include <linux/mmc/card.h>
+#include <linux/mmc/mmc.h>
+#include <linux/mmc/sd.h>
+
+#include "core.h"
+#include "sd_ops.h"
+
+/**
+ *	mmc_wait_for_app_cmd - start an application command and wait for
+ 			       completion
+ *	@host: MMC host to start command
+ *	@rca: RCA to send MMC_APP_CMD to
+ *	@cmd: MMC command to start
+ *	@retries: maximum number of retries
+ *
+ *	Sends a MMC_APP_CMD, checks the card response, sends the command
+ *	in the parameter and waits for it to complete. Return any error
+ *	that occurred while the command was executing.  Do not attempt to
+ *	parse the response.
+ */
+int mmc_wait_for_app_cmd(struct mmc_host *host, struct mmc_card *card,
+	struct mmc_command *cmd, int retries)
+{
+	struct mmc_request mrq;
+
+	int i, err;
+
+	BUG_ON(!cmd);
+	BUG_ON(retries < 0);
+
+	err = MMC_ERR_INVALID;
+
+	/*
+	 * We have to resend MMC_APP_CMD for each attempt so
+	 * we cannot use the retries field in mmc_command.
+	 */
+	for (i = 0;i <= retries;i++) {
+		memset(&mrq, 0, sizeof(struct mmc_request));
+
+		err = mmc_app_cmd(host, card);
+		if (err != MMC_ERR_NONE)
+			continue;
+
+		memset(&mrq, 0, sizeof(struct mmc_request));
+
+		memset(cmd->resp, 0, sizeof(cmd->resp));
+		cmd->retries = 0;
+
+		mrq.cmd = cmd;
+		cmd->data = NULL;
+
+		mmc_wait_for_req(host, &mrq);
+
+		err = cmd->error;
+		if (cmd->error == MMC_ERR_NONE)
+			break;
+	}
+
+	return err;
+}
+
+EXPORT_SYMBOL(mmc_wait_for_app_cmd);
+
+int mmc_app_cmd(struct mmc_host *host, struct mmc_card *card)
+{
+	int err;
+	struct mmc_command cmd;
+
+	BUG_ON(!host);
+	BUG_ON(card && (card->host != host));
+
+	cmd.opcode = MMC_APP_CMD;
+
+	if (card) {
+		cmd.arg = card->rca << 16;
+		cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
+	} else {
+		cmd.arg = 0;
+		cmd.flags = MMC_RSP_R1 | MMC_CMD_BCR;
+	}
+
+	err = mmc_wait_for_cmd(host, &cmd, 0);
+	if (err != MMC_ERR_NONE)
+		return err;
+
+	/* Check that card supported application commands */
+	if (!(cmd.resp[0] & R1_APP_CMD))
+		return MMC_ERR_FAILED;
+
+	return MMC_ERR_NONE;
+}
+
+int mmc_app_set_bus_width(struct mmc_card *card, int width)
+{
+	int err;
+	struct mmc_command cmd;
+
+	BUG_ON(!card);
+	BUG_ON(!card->host);
+
+	memset(&cmd, 0, sizeof(struct mmc_command));
+
+	cmd.opcode = SD_APP_SET_BUS_WIDTH;
+	cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
+
+	switch (width) {
+	case MMC_BUS_WIDTH_1:
+		cmd.arg = SD_BUS_WIDTH_1;
+		break;
+	case MMC_BUS_WIDTH_4:
+		cmd.arg = SD_BUS_WIDTH_4;
+		break;
+	default:
+		return MMC_ERR_INVALID;
+	}
+
+	err = mmc_wait_for_app_cmd(card->host, card, &cmd, MMC_CMD_RETRIES);
+	if (err != MMC_ERR_NONE)
+		return err;
+
+	return MMC_ERR_NONE;
+}
+
+int mmc_send_app_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr)
+{
+	struct mmc_command cmd;
+	int i, err = 0;
+
+	BUG_ON(!host);
+
+	memset(&cmd, 0, sizeof(struct mmc_command));
+
+	cmd.opcode = SD_APP_OP_COND;
+	cmd.arg = ocr;
+	cmd.flags = MMC_RSP_R3 | MMC_CMD_BCR;
+
+	for (i = 100; i; i--) {
+		err = mmc_wait_for_app_cmd(host, NULL, &cmd, MMC_CMD_RETRIES);
+		if (err != MMC_ERR_NONE)
+			break;
+
+		if (cmd.resp[0] & MMC_CARD_BUSY || ocr == 0)
+			break;
+
+		err = MMC_ERR_TIMEOUT;
+
+		mmc_delay(10);
+	}
+
+	if (rocr)
+		*rocr = cmd.resp[0];
+
+	return err;
+}
+
+int mmc_send_if_cond(struct mmc_host *host, u32 ocr)
+{
+	struct mmc_command cmd;
+	int err;
+	static const u8 test_pattern = 0xAA;
+
+	/*
+	 * To support SD 2.0 cards, we must always invoke SD_SEND_IF_COND
+	 * before SD_APP_OP_COND. This command will harmlessly fail for
+	 * SD 1.0 cards.
+	 */
+	cmd.opcode = SD_SEND_IF_COND;
+	cmd.arg = ((ocr & 0xFF8000) != 0) << 8 | test_pattern;
+	cmd.flags = MMC_RSP_R7 | MMC_CMD_BCR;
+
+	err = mmc_wait_for_cmd(host, &cmd, 0);
+	if (err != MMC_ERR_NONE)
+		return err;
+
+	if ((cmd.resp[0] & 0xFF) != test_pattern)
+		return MMC_ERR_FAILED;
+
+	return MMC_ERR_NONE;
+}
+
+int mmc_send_relative_addr(struct mmc_host *host, unsigned int *rca)
+{
+	int err;
+	struct mmc_command cmd;
+
+	BUG_ON(!host);
+	BUG_ON(!rca);
+
+	memset(&cmd, 0, sizeof(struct mmc_command));
+
+	cmd.opcode = SD_SEND_RELATIVE_ADDR;
+	cmd.arg = 0;
+	cmd.flags = MMC_RSP_R6 | MMC_CMD_BCR;
+
+	err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES);
+	if (err != MMC_ERR_NONE)
+		return err;
+
+	*rca = cmd.resp[0] >> 16;
+
+	return MMC_ERR_NONE;
+}
+
+int mmc_app_send_scr(struct mmc_card *card, u32 *scr)
+{
+	int err;
+	struct mmc_request mrq;
+	struct mmc_command cmd;
+	struct mmc_data data;
+	struct scatterlist sg;
+
+	BUG_ON(!card);
+	BUG_ON(!card->host);
+	BUG_ON(!scr);
+
+	err = mmc_app_cmd(card->host, card);
+	if (err != MMC_ERR_NONE)
+		return err;
+
+	memset(&mrq, 0, sizeof(struct mmc_request));
+	memset(&cmd, 0, sizeof(struct mmc_command));
+	memset(&data, 0, sizeof(struct mmc_data));
+
+	mrq.cmd = &cmd;
+	mrq.data = &data;
+
+	cmd.opcode = SD_APP_SEND_SCR;
+	cmd.arg = 0;
+	cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
+
+	data.blksz = 8;
+	data.blocks = 1;
+	data.flags = MMC_DATA_READ;
+	data.sg = &sg;
+	data.sg_len = 1;
+
+	sg_init_one(&sg, scr, 8);
+
+	mmc_set_data_timeout(&data, card, 0);
+
+	mmc_wait_for_req(card->host, &mrq);
+
+	if (cmd.error != MMC_ERR_NONE)
+		return cmd.error;
+	if (data.error != MMC_ERR_NONE)
+		return data.error;
+
+	scr[0] = ntohl(scr[0]);
+	scr[1] = ntohl(scr[1]);
+
+	return MMC_ERR_NONE;
+}
+
+int mmc_sd_switch(struct mmc_card *card, int mode, int group,
+	u8 value, u8 *resp)
+{
+	struct mmc_request mrq;
+	struct mmc_command cmd;
+	struct mmc_data data;
+	struct scatterlist sg;
+
+	BUG_ON(!card);
+	BUG_ON(!card->host);
+
+	mode = !!mode;
+	value &= 0xF;
+
+	memset(&mrq, 0, sizeof(struct mmc_request));
+	memset(&cmd, 0, sizeof(struct mmc_command));
+	memset(&data, 0, sizeof(struct mmc_data));
+
+	mrq.cmd = &cmd;
+	mrq.data = &data;
+
+	cmd.opcode = SD_SWITCH;
+	cmd.arg = mode << 31 | 0x00FFFFFF;
+	cmd.arg &= ~(0xF << (group * 4));
+	cmd.arg |= value << (group * 4);
+	cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
+
+	data.blksz = 64;
+	data.blocks = 1;
+	data.flags = MMC_DATA_READ;
+	data.sg = &sg;
+	data.sg_len = 1;
+
+	sg_init_one(&sg, resp, 64);
+
+	mmc_set_data_timeout(&data, card, 0);
+
+	mmc_wait_for_req(card->host, &mrq);
+
+	if (cmd.error != MMC_ERR_NONE)
+		return cmd.error;
+	if (data.error != MMC_ERR_NONE)
+		return data.error;
+
+	return MMC_ERR_NONE;
+}
+
diff --git a/drivers/mmc/core/sd_ops.h b/drivers/mmc/core/sd_ops.h
new file mode 100644
index 0000000..1240fdd
--- /dev/null
+++ b/drivers/mmc/core/sd_ops.h
@@ -0,0 +1,25 @@
+/*
+ *  linux/drivers/mmc/sd_ops.h
+ *
+ *  Copyright 2006-2007 Pierre Ossman
+ *
+ * This program is free software; you can redistribute it and/or 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 _MMC_SD_OPS_H
+#define _MMC_SD_OPS_H
+
+int mmc_app_cmd(struct mmc_host *host, struct mmc_card *card);
+int mmc_app_set_bus_width(struct mmc_card *card, int width);
+int mmc_send_app_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr);
+int mmc_send_if_cond(struct mmc_host *host, u32 ocr);
+int mmc_send_relative_addr(struct mmc_host *host, unsigned int *rca);
+int mmc_app_send_scr(struct mmc_card *card, u32 *scr);
+int mmc_sd_switch(struct mmc_card *card, int mode, int group,
+	u8 value, u8 *resp);
+
+#endif
+
diff --git a/drivers/mmc/mmc_sysfs.c b/drivers/mmc/core/sysfs.c
similarity index 97%
rename from drivers/mmc/mmc_sysfs.c
rename to drivers/mmc/core/sysfs.c
index e0e82d8..843b1fb 100644
--- a/drivers/mmc/mmc_sysfs.c
+++ b/drivers/mmc/core/sysfs.c
@@ -1,5 +1,5 @@
 /*
- *  linux/drivers/mmc/mmc_sysfs.c
+ *  linux/drivers/mmc/core/sysfs.c
  *
  *  Copyright (C) 2003 Russell King, All Rights Reserved.
  *
@@ -18,7 +18,7 @@
 #include <linux/mmc/card.h>
 #include <linux/mmc/host.h>
 
-#include "mmc.h"
+#include "sysfs.h"
 
 #define dev_to_mmc_card(d)	container_of(d, struct mmc_card, dev)
 #define to_mmc_driver(d)	container_of(d, struct mmc_driver, drv)
@@ -72,12 +72,11 @@
 /*
  * This currently matches any MMC driver to any MMC card - drivers
  * themselves make the decision whether to drive this card in their
- * probe method.  However, we force "bad" cards to fail.
+ * probe method.
  */
 static int mmc_bus_match(struct device *dev, struct device_driver *drv)
 {
-	struct mmc_card *card = dev_to_mmc_card(dev);
-	return !mmc_card_bad(card);
+	return 1;
 }
 
 static int
@@ -217,6 +216,8 @@
 				device_del(&card->dev);
 		}
 	}
+	if (ret == 0)
+		mmc_card_set_present(card);
 	return ret;
 }
 
diff --git a/drivers/mmc/mmc.h b/drivers/mmc/core/sysfs.h
similarity index 86%
rename from drivers/mmc/mmc.h
rename to drivers/mmc/core/sysfs.h
index 149affe..80e29b3 100644
--- a/drivers/mmc/mmc.h
+++ b/drivers/mmc/core/sysfs.h
@@ -1,15 +1,16 @@
 /*
- *  linux/drivers/mmc/mmc.h
+ *  linux/drivers/mmc/core/sysfs.h
  *
  *  Copyright (C) 2003 Russell King, All Rights Reserved.
+ *  Copyright 2007 Pierre Ossman
  *
  * 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 _MMC_H
-#define _MMC_H
-/* core-internal functions */
+#ifndef _MMC_CORE_SYSFS_H
+#define _MMC_CORE_SYSFS_H
+
 void mmc_init_card(struct mmc_card *card, struct mmc_host *host);
 int mmc_register_card(struct mmc_card *card);
 void mmc_remove_card(struct mmc_card *card);
@@ -22,4 +23,5 @@
 int mmc_schedule_work(struct work_struct *work);
 int mmc_schedule_delayed_work(struct delayed_work *work, unsigned long delay);
 void mmc_flush_scheduled_work(void);
+
 #endif
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
new file mode 100644
index 0000000..ed4deab
--- /dev/null
+++ b/drivers/mmc/host/Kconfig
@@ -0,0 +1,103 @@
+#
+# MMC/SD host controller drivers
+#
+
+comment "MMC/SD Host Controller Drivers"
+	depends on MMC
+
+config MMC_ARMMMCI
+	tristate "ARM AMBA Multimedia Card Interface support"
+	depends on ARM_AMBA && MMC
+	help
+	  This selects the ARM(R) AMBA(R) PrimeCell Multimedia Card
+	  Interface (PL180 and PL181) support.  If you have an ARM(R)
+	  platform with a Multimedia Card slot, say Y or M here.
+
+	  If unsure, say N.
+
+config MMC_PXA
+	tristate "Intel PXA25x/26x/27x Multimedia Card Interface support"
+	depends on ARCH_PXA && MMC
+	help
+	  This selects the Intel(R) PXA(R) Multimedia card Interface.
+	  If you have a PXA(R) platform with a Multimedia Card slot,
+	  say Y or M here.
+
+	  If unsure, say N.
+
+config MMC_SDHCI
+	tristate "Secure Digital Host Controller Interface support  (EXPERIMENTAL)"
+	depends on PCI && MMC && EXPERIMENTAL
+	help
+	  This select the generic Secure Digital Host Controller Interface.
+	  It is used by manufacturers such as Texas Instruments(R), Ricoh(R)
+	  and Toshiba(R). Most controllers found in laptops are of this type.
+	  If you have a controller with this interface, say Y or M here.
+
+	  If unsure, say N.
+
+config MMC_OMAP
+	tristate "TI OMAP Multimedia Card Interface support"
+	depends on ARCH_OMAP && MMC
+	select TPS65010 if MACH_OMAP_H2
+	help
+	  This selects the TI OMAP Multimedia card Interface.
+	  If you have an OMAP board with a Multimedia Card slot,
+	  say Y or M here.
+
+	  If unsure, say N.
+
+config MMC_WBSD
+	tristate "Winbond W83L51xD SD/MMC Card Interface support"
+	depends on MMC && ISA_DMA_API
+	help
+	  This selects the Winbond(R) W83L51xD Secure digital and
+          Multimedia card Interface.
+	  If you have a machine with a integrated W83L518D or W83L519D
+	  SD/MMC card reader, say Y or M here.
+
+	  If unsure, say N.
+
+config MMC_AU1X
+	tristate "Alchemy AU1XX0 MMC Card Interface support"
+	depends on MMC && SOC_AU1200
+	help
+	  This selects the AMD Alchemy(R) Multimedia card interface.
+	  If you have a Alchemy platform with a MMC slot, say Y or M here.
+
+	  If unsure, say N.
+
+config MMC_AT91
+	tristate "AT91 SD/MMC Card Interface support"
+	depends on ARCH_AT91 && MMC
+	help
+	  This selects the AT91 MCI controller.
+
+	  If unsure, say N.
+
+config MMC_IMX
+	tristate "Motorola i.MX Multimedia Card Interface support"
+	depends on ARCH_IMX && MMC
+	help
+	  This selects the Motorola i.MX Multimedia card Interface.
+	  If you have a i.MX platform with a Multimedia Card slot,
+	  say Y or M here.
+
+	  If unsure, say N.
+
+config MMC_TIFM_SD
+	tristate "TI Flash Media MMC/SD Interface support  (EXPERIMENTAL)"
+	depends on MMC && EXPERIMENTAL && PCI
+	select TIFM_CORE
+	help
+	  Say Y here if you want to be able to access MMC/SD cards with
+	  the Texas Instruments(R) Flash Media card reader, found in many
+	  laptops.
+	  This option 'selects' (turns on, enables) 'TIFM_CORE', but you
+	  probably also need appropriate card reader host adapter, such as
+	  'Misc devices: TI Flash Media PCI74xx/PCI76xx host adapter support
+	  (TIFM_7XX1)'.
+
+          To compile this driver as a module, choose M here: the
+	  module will be called tifm_sd.
+
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
new file mode 100644
index 0000000..6685f64
--- /dev/null
+++ b/drivers/mmc/host/Makefile
@@ -0,0 +1,18 @@
+#
+# Makefile for MMC/SD host controller drivers
+#
+
+ifeq ($(CONFIG_MMC_DEBUG),y)
+	EXTRA_CFLAGS		+= -DDEBUG
+endif
+
+obj-$(CONFIG_MMC_ARMMMCI)	+= mmci.o
+obj-$(CONFIG_MMC_PXA)		+= pxamci.o
+obj-$(CONFIG_MMC_IMX)		+= imxmmc.o
+obj-$(CONFIG_MMC_SDHCI)		+= sdhci.o
+obj-$(CONFIG_MMC_WBSD)		+= wbsd.o
+obj-$(CONFIG_MMC_AU1X)		+= au1xmmc.o
+obj-$(CONFIG_MMC_OMAP)		+= omap.o
+obj-$(CONFIG_MMC_AT91)		+= at91_mci.o
+obj-$(CONFIG_MMC_TIFM_SD)	+= tifm_sd.o
+
diff --git a/drivers/mmc/at91_mci.c b/drivers/mmc/host/at91_mci.c
similarity index 99%
rename from drivers/mmc/at91_mci.c
rename to drivers/mmc/host/at91_mci.c
index 459f4b4fe..e37943c 100644
--- a/drivers/mmc/at91_mci.c
+++ b/drivers/mmc/host/at91_mci.c
@@ -67,7 +67,6 @@
 #include <linux/atmel_pdc.h>
 
 #include <linux/mmc/host.h>
-#include <linux/mmc/protocol.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
diff --git a/drivers/mmc/au1xmmc.c b/drivers/mmc/host/au1xmmc.c
similarity index 99%
rename from drivers/mmc/au1xmmc.c
rename to drivers/mmc/host/au1xmmc.c
index b834be2..b7156a4 100644
--- a/drivers/mmc/au1xmmc.c
+++ b/drivers/mmc/host/au1xmmc.c
@@ -42,7 +42,6 @@
 #include <linux/dma-mapping.h>
 
 #include <linux/mmc/host.h>
-#include <linux/mmc/protocol.h>
 #include <asm/io.h>
 #include <asm/mach-au1x00/au1000.h>
 #include <asm/mach-au1x00/au1xxx_dbdma.h>
diff --git a/drivers/mmc/au1xmmc.h b/drivers/mmc/host/au1xmmc.h
similarity index 100%
rename from drivers/mmc/au1xmmc.h
rename to drivers/mmc/host/au1xmmc.h
diff --git a/drivers/mmc/imxmmc.c b/drivers/mmc/host/imxmmc.c
similarity index 99%
rename from drivers/mmc/imxmmc.c
rename to drivers/mmc/host/imxmmc.c
index 0de5c9e..7ee2045 100644
--- a/drivers/mmc/imxmmc.c
+++ b/drivers/mmc/host/imxmmc.c
@@ -41,7 +41,6 @@
 #include <linux/dma-mapping.h>
 #include <linux/mmc/host.h>
 #include <linux/mmc/card.h>
-#include <linux/mmc/protocol.h>
 #include <linux/delay.h>
 
 #include <asm/dma.h>
diff --git a/drivers/mmc/imxmmc.h b/drivers/mmc/host/imxmmc.h
similarity index 100%
rename from drivers/mmc/imxmmc.h
rename to drivers/mmc/host/imxmmc.h
diff --git a/drivers/mmc/mmci.c b/drivers/mmc/host/mmci.c
similarity index 99%
rename from drivers/mmc/mmci.c
rename to drivers/mmc/host/mmci.c
index 5941dd9..d11c2d2 100644
--- a/drivers/mmc/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -17,7 +17,6 @@
 #include <linux/err.h>
 #include <linux/highmem.h>
 #include <linux/mmc/host.h>
-#include <linux/mmc/protocol.h>
 #include <linux/amba/bus.h>
 #include <linux/clk.h>
 
diff --git a/drivers/mmc/mmci.h b/drivers/mmc/host/mmci.h
similarity index 100%
rename from drivers/mmc/mmci.h
rename to drivers/mmc/host/mmci.h
diff --git a/drivers/mmc/omap.c b/drivers/mmc/host/omap.c
similarity index 97%
rename from drivers/mmc/omap.c
rename to drivers/mmc/host/omap.c
index 1e96a2f..1914e65 100644
--- a/drivers/mmc/omap.c
+++ b/drivers/mmc/host/omap.c
@@ -22,7 +22,6 @@
 #include <linux/spinlock.h>
 #include <linux/timer.h>
 #include <linux/mmc/host.h>
-#include <linux/mmc/protocol.h>
 #include <linux/mmc/card.h>
 #include <linux/clk.h>
 
@@ -605,7 +604,7 @@
 	}
 	if (mmc_omap_cover_is_open(host)) {
 		if (!complained) {
-			dev_info(mmc_dev(host->mmc), "cover is open");
+			dev_info(mmc_dev(host->mmc), "cover is open\n");
 			complained = 1;
 		}
 		if (mmc_omap_enable_poll)
@@ -937,48 +936,55 @@
 	}
 }
 
+static int mmc_omap_calc_divisor(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+	struct mmc_omap_host *host = mmc_priv(mmc);
+	int func_clk_rate = clk_get_rate(host->fclk);
+	int dsor;
+
+	if (ios->clock == 0)
+		return 0;
+
+	dsor = func_clk_rate / ios->clock;
+	if (dsor < 1)
+		dsor = 1;
+
+	if (func_clk_rate / dsor > ios->clock)
+		dsor++;
+
+	if (dsor > 250)
+		dsor = 250;
+	dsor++;
+
+	if (ios->bus_width == MMC_BUS_WIDTH_4)
+		dsor |= 1 << 15;
+
+	return dsor;
+}
+
 static void mmc_omap_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 {
 	struct mmc_omap_host *host = mmc_priv(mmc);
 	int dsor;
-	int realclock, i;
+	int i;
 
-	realclock = ios->clock;
-
-	if (ios->clock == 0)
-		dsor = 0;
-	else {
-		int func_clk_rate = clk_get_rate(host->fclk);
-
-		dsor = func_clk_rate / realclock;
-		if (dsor < 1)
-			dsor = 1;
-
-		if (func_clk_rate / dsor > realclock)
-			dsor++;
-
-		if (dsor > 250)
-			dsor = 250;
-		dsor++;
-
-		if (ios->bus_width == MMC_BUS_WIDTH_4)
-			dsor |= 1 << 15;
-	}
+	dsor = mmc_omap_calc_divisor(mmc, ios);
+	host->bus_mode = ios->bus_mode;
+	host->hw_bus_mode = host->bus_mode;
 
 	switch (ios->power_mode) {
 	case MMC_POWER_OFF:
 		mmc_omap_power(host, 0);
 		break;
 	case MMC_POWER_UP:
-	case MMC_POWER_ON:
+		/* Cannot touch dsor yet, just power up MMC */
 		mmc_omap_power(host, 1);
+		return;
+	case MMC_POWER_ON:
 		dsor |= 1 << 11;
 		break;
 	}
 
-	host->bus_mode = ios->bus_mode;
-	host->hw_bus_mode = host->bus_mode;
-
 	clk_enable(host->fclk);
 
 	/* On insanely high arm_per frequencies something sometimes
@@ -987,7 +993,7 @@
 	 * Writing to the CON register twice seems to do the trick. */
 	for (i = 0; i < 2; i++)
 		OMAP_MMC_WRITE(host, CON, dsor);
-	if (ios->power_mode == MMC_POWER_UP) {
+	if (ios->power_mode == MMC_POWER_ON) {
 		/* Send clock cycles, poll completion */
 		OMAP_MMC_WRITE(host, IE, 0);
 		OMAP_MMC_WRITE(host, STAT, 0xffff);
diff --git a/drivers/mmc/pxamci.c b/drivers/mmc/host/pxamci.c
similarity index 99%
rename from drivers/mmc/pxamci.c
rename to drivers/mmc/host/pxamci.c
index 9774fc6..a98ff98 100644
--- a/drivers/mmc/pxamci.c
+++ b/drivers/mmc/host/pxamci.c
@@ -24,7 +24,6 @@
 #include <linux/interrupt.h>
 #include <linux/dma-mapping.h>
 #include <linux/mmc/host.h>
-#include <linux/mmc/protocol.h>
 
 #include <asm/dma.h>
 #include <asm/io.h>
diff --git a/drivers/mmc/pxamci.h b/drivers/mmc/host/pxamci.h
similarity index 100%
rename from drivers/mmc/pxamci.h
rename to drivers/mmc/host/pxamci.h
diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/host/sdhci.c
similarity index 97%
rename from drivers/mmc/sdhci.c
rename to drivers/mmc/host/sdhci.c
index d749f08..ff5bf73 100644
--- a/drivers/mmc/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -1,7 +1,7 @@
 /*
  *  linux/drivers/mmc/sdhci.c - Secure Digital Host Controller Interface driver
  *
- *  Copyright (C) 2005-2006 Pierre Ossman, All Rights Reserved.
+ *  Copyright (C) 2005-2007 Pierre Ossman, 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
@@ -15,7 +15,6 @@
 #include <linux/dma-mapping.h>
 
 #include <linux/mmc/host.h>
-#include <linux/mmc/protocol.h>
 
 #include <asm/scatterlist.h>
 
@@ -247,14 +246,13 @@
 			chunk_remain = min(blksize, 4);
 		}
 
-		size = min(host->size, host->remain);
-		size = min(size, chunk_remain);
+		size = min(host->remain, chunk_remain);
 
 		chunk_remain -= size;
 		blksize -= size;
 		host->offset += size;
 		host->remain -= size;
-		host->size -= size;
+
 		while (size) {
 			*buffer = data & 0xFF;
 			buffer++;
@@ -289,14 +287,13 @@
 	buffer = sdhci_sg_to_buffer(host) + host->offset;
 
 	while (blksize) {
-		size = min(host->size, host->remain);
-		size = min(size, chunk_remain);
+		size = min(host->remain, chunk_remain);
 
 		chunk_remain -= size;
 		blksize -= size;
 		host->offset += size;
 		host->remain -= size;
-		host->size -= size;
+
 		while (size) {
 			data >>= 8;
 			data |= (u32)*buffer << 24;
@@ -325,7 +322,7 @@
 
 	BUG_ON(!host->data);
 
-	if (host->size == 0)
+	if (host->num_sg == 0)
 		return;
 
 	if (host->data->flags & MMC_DATA_READ)
@@ -339,10 +336,8 @@
 		else
 			sdhci_write_block_pio(host);
 
-		if (host->size == 0)
+		if (host->num_sg == 0)
 			break;
-
-		BUG_ON(host->num_sg == 0);
 	}
 
 	DBG("PIO transfer complete.\n");
@@ -408,8 +403,6 @@
 
 		writel(sg_dma_address(data->sg), host->ioaddr + SDHCI_DMA_ADDRESS);
 	} else {
-		host->size = data->blksz * data->blocks;
-
 		host->cur_sg = data->sg;
 		host->num_sg = data->sg_len;
 
@@ -473,10 +466,6 @@
 			"though there were blocks left.\n",
 			mmc_hostname(host->mmc));
 		data->error = MMC_ERR_FAILED;
-	} else if (host->size != 0) {
-		printk(KERN_ERR "%s: %d bytes were left untransferred.\n",
-			mmc_hostname(host->mmc), host->size);
-		data->error = MMC_ERR_FAILED;
 	}
 
 	DBG("Ending data transfer (%d bytes)\n", data->bytes_xfered);
@@ -669,20 +658,16 @@
 
 	pwr = SDHCI_POWER_ON;
 
-	switch (power) {
-	case MMC_VDD_170:
-	case MMC_VDD_180:
-	case MMC_VDD_190:
+	switch (1 << power) {
+	case MMC_VDD_165_195:
 		pwr |= SDHCI_POWER_180;
 		break;
-	case MMC_VDD_290:
-	case MMC_VDD_300:
-	case MMC_VDD_310:
+	case MMC_VDD_29_30:
+	case MMC_VDD_30_31:
 		pwr |= SDHCI_POWER_300;
 		break;
-	case MMC_VDD_320:
-	case MMC_VDD_330:
-	case MMC_VDD_340:
+	case MMC_VDD_32_33:
+	case MMC_VDD_33_34:
 		pwr |= SDHCI_POWER_330;
 		break;
 	default:
@@ -1294,7 +1279,7 @@
 	if (caps & SDHCI_CAN_VDD_300)
 		mmc->ocr_avail |= MMC_VDD_29_30|MMC_VDD_30_31;
 	if (caps & SDHCI_CAN_VDD_180)
-		mmc->ocr_avail |= MMC_VDD_17_18|MMC_VDD_18_19;
+		mmc->ocr_avail |= MMC_VDD_165_195;
 
 	if (mmc->ocr_avail == 0) {
 		printk(KERN_ERR "%s: Hardware doesn't report any "
diff --git a/drivers/mmc/sdhci.h b/drivers/mmc/host/sdhci.h
similarity index 97%
rename from drivers/mmc/sdhci.h
rename to drivers/mmc/host/sdhci.h
index e324f0a..7400f4b 100644
--- a/drivers/mmc/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -1,7 +1,7 @@
 /*
  *  linux/drivers/mmc/sdhci.h - Secure Digital Host Controller Interface driver
  *
- *  Copyright (C) 2005 Pierre Ossman, All Rights Reserved.
+ *  Copyright (C) 2005-2007 Pierre Ossman, 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
@@ -187,8 +187,6 @@
 	int			offset;		/* Offset into current sg */
 	int			remain;		/* Bytes left in current */
 
-	int			size;		/* Remaining bytes in transfer */
-
 	char			slot_descr[20];	/* Name for reservations */
 
 	int			irq;		/* Device IRQ */
diff --git a/drivers/mmc/host/tifm_sd.c b/drivers/mmc/host/tifm_sd.c
new file mode 100644
index 0000000..7511f96
--- /dev/null
+++ b/drivers/mmc/host/tifm_sd.c
@@ -0,0 +1,1102 @@
+/*
+ *  tifm_sd.c - TI FlashMedia driver
+ *
+ *  Copyright (C) 2006 Alex Dubov <oakad@yahoo.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.
+ *
+ * Special thanks to Brad Campbell for extensive testing of this driver.
+ *
+ */
+
+
+#include <linux/tifm.h>
+#include <linux/mmc/host.h>
+#include <linux/highmem.h>
+#include <linux/scatterlist.h>
+#include <asm/io.h>
+
+#define DRIVER_NAME "tifm_sd"
+#define DRIVER_VERSION "0.8"
+
+static int no_dma = 0;
+static int fixed_timeout = 0;
+module_param(no_dma, bool, 0644);
+module_param(fixed_timeout, bool, 0644);
+
+/* Constants here are mostly from OMAP5912 datasheet */
+#define TIFM_MMCSD_RESET      0x0002
+#define TIFM_MMCSD_CLKMASK    0x03ff
+#define TIFM_MMCSD_POWER      0x0800
+#define TIFM_MMCSD_4BBUS      0x8000
+#define TIFM_MMCSD_RXDE       0x8000   /* rx dma enable */
+#define TIFM_MMCSD_TXDE       0x0080   /* tx dma enable */
+#define TIFM_MMCSD_BUFINT     0x0c00   /* set bits: AE, AF */
+#define TIFM_MMCSD_DPE        0x0020   /* data timeout counted in kilocycles */
+#define TIFM_MMCSD_INAB       0x0080   /* abort / initialize command */
+#define TIFM_MMCSD_READ       0x8000
+
+#define TIFM_MMCSD_ERRMASK    0x01e0   /* set bits: CCRC, CTO, DCRC, DTO */
+#define TIFM_MMCSD_EOC        0x0001   /* end of command phase  */
+#define TIFM_MMCSD_CD         0x0002   /* card detect           */
+#define TIFM_MMCSD_CB         0x0004   /* card enter busy state */
+#define TIFM_MMCSD_BRS        0x0008   /* block received/sent   */
+#define TIFM_MMCSD_EOFB       0x0010   /* card exit busy state  */
+#define TIFM_MMCSD_DTO        0x0020   /* data time-out         */
+#define TIFM_MMCSD_DCRC       0x0040   /* data crc error        */
+#define TIFM_MMCSD_CTO        0x0080   /* command time-out      */
+#define TIFM_MMCSD_CCRC       0x0100   /* command crc error     */
+#define TIFM_MMCSD_AF         0x0400   /* fifo almost full      */
+#define TIFM_MMCSD_AE         0x0800   /* fifo almost empty     */
+#define TIFM_MMCSD_OCRB       0x1000   /* OCR busy              */
+#define TIFM_MMCSD_CIRQ       0x2000   /* card irq (cmd40/sdio) */
+#define TIFM_MMCSD_CERR       0x4000   /* card status error     */
+
+#define TIFM_MMCSD_ODTO       0x0040   /* open drain / extended timeout */
+#define TIFM_MMCSD_CARD_RO    0x0200   /* card is read-only     */
+
+#define TIFM_MMCSD_FIFO_SIZE  0x0020
+
+#define TIFM_MMCSD_RSP_R0     0x0000
+#define TIFM_MMCSD_RSP_R1     0x0100
+#define TIFM_MMCSD_RSP_R2     0x0200
+#define TIFM_MMCSD_RSP_R3     0x0300
+#define TIFM_MMCSD_RSP_R4     0x0400
+#define TIFM_MMCSD_RSP_R5     0x0500
+#define TIFM_MMCSD_RSP_R6     0x0600
+
+#define TIFM_MMCSD_RSP_BUSY   0x0800
+
+#define TIFM_MMCSD_CMD_BC     0x0000
+#define TIFM_MMCSD_CMD_BCR    0x1000
+#define TIFM_MMCSD_CMD_AC     0x2000
+#define TIFM_MMCSD_CMD_ADTC   0x3000
+
+#define TIFM_MMCSD_MAX_BLOCK_SIZE  0x0800UL
+
+enum {
+	CMD_READY    = 0x0001,
+	FIFO_READY   = 0x0002,
+	BRS_READY    = 0x0004,
+	SCMD_ACTIVE  = 0x0008,
+	SCMD_READY   = 0x0010,
+	CARD_BUSY    = 0x0020,
+	DATA_CARRY   = 0x0040
+};
+
+struct tifm_sd {
+	struct tifm_dev       *dev;
+
+	unsigned short        eject:1,
+			      open_drain:1,
+			      no_dma:1;
+	unsigned short        cmd_flags;
+
+	unsigned int          clk_freq;
+	unsigned int          clk_div;
+	unsigned long         timeout_jiffies;
+
+	struct tasklet_struct finish_tasklet;
+	struct timer_list     timer;
+	struct mmc_request    *req;
+
+	int                   sg_len;
+	int                   sg_pos;
+	unsigned int          block_pos;
+	struct scatterlist    bounce_buf;
+	unsigned char         bounce_buf_data[TIFM_MMCSD_MAX_BLOCK_SIZE];
+};
+
+/* for some reason, host won't respond correctly to readw/writew */
+static void tifm_sd_read_fifo(struct tifm_sd *host, struct page *pg,
+			      unsigned int off, unsigned int cnt)
+{
+	struct tifm_dev *sock = host->dev;
+	unsigned char *buf;
+	unsigned int pos = 0, val;
+
+	buf = kmap_atomic(pg, KM_BIO_DST_IRQ) + off;
+	if (host->cmd_flags & DATA_CARRY) {
+		buf[pos++] = host->bounce_buf_data[0];
+		host->cmd_flags &= ~DATA_CARRY;
+	}
+
+	while (pos < cnt) {
+		val = readl(sock->addr + SOCK_MMCSD_DATA);
+		buf[pos++] = val & 0xff;
+		if (pos == cnt) {
+			host->bounce_buf_data[0] = (val >> 8) & 0xff;
+			host->cmd_flags |= DATA_CARRY;
+			break;
+		}
+		buf[pos++] = (val >> 8) & 0xff;
+	}
+	kunmap_atomic(buf - off, KM_BIO_DST_IRQ);
+}
+
+static void tifm_sd_write_fifo(struct tifm_sd *host, struct page *pg,
+			       unsigned int off, unsigned int cnt)
+{
+	struct tifm_dev *sock = host->dev;
+	unsigned char *buf;
+	unsigned int pos = 0, val;
+
+	buf = kmap_atomic(pg, KM_BIO_SRC_IRQ) + off;
+	if (host->cmd_flags & DATA_CARRY) {
+		val = host->bounce_buf_data[0] | ((buf[pos++] << 8) & 0xff00);
+		writel(val, sock->addr + SOCK_MMCSD_DATA);
+		host->cmd_flags &= ~DATA_CARRY;
+	}
+
+	while (pos < cnt) {
+		val = buf[pos++];
+		if (pos == cnt) {
+			host->bounce_buf_data[0] = val & 0xff;
+			host->cmd_flags |= DATA_CARRY;
+			break;
+		}
+		val |= (buf[pos++] << 8) & 0xff00;
+		writel(val, sock->addr + SOCK_MMCSD_DATA);
+	}
+	kunmap_atomic(buf - off, KM_BIO_SRC_IRQ);
+}
+
+static void tifm_sd_transfer_data(struct tifm_sd *host)
+{
+	struct mmc_data *r_data = host->req->cmd->data;
+	struct scatterlist *sg = r_data->sg;
+	unsigned int off, cnt, t_size = TIFM_MMCSD_FIFO_SIZE * 2;
+	unsigned int p_off, p_cnt;
+	struct page *pg;
+
+	if (host->sg_pos == host->sg_len)
+		return;
+	while (t_size) {
+		cnt = sg[host->sg_pos].length - host->block_pos;
+		if (!cnt) {
+			host->block_pos = 0;
+			host->sg_pos++;
+			if (host->sg_pos == host->sg_len) {
+				if ((r_data->flags & MMC_DATA_WRITE)
+				    && DATA_CARRY)
+					writel(host->bounce_buf_data[0],
+					       host->dev->addr
+					       + SOCK_MMCSD_DATA);
+
+				return;
+			}
+			cnt = sg[host->sg_pos].length;
+		}
+		off = sg[host->sg_pos].offset + host->block_pos;
+
+		pg = nth_page(sg[host->sg_pos].page, off >> PAGE_SHIFT);
+		p_off = offset_in_page(off);
+		p_cnt = PAGE_SIZE - p_off;
+		p_cnt = min(p_cnt, cnt);
+		p_cnt = min(p_cnt, t_size);
+
+		if (r_data->flags & MMC_DATA_READ)
+			tifm_sd_read_fifo(host, pg, p_off, p_cnt);
+		else if (r_data->flags & MMC_DATA_WRITE)
+			tifm_sd_write_fifo(host, pg, p_off, p_cnt);
+
+		t_size -= p_cnt;
+		host->block_pos += p_cnt;
+	}
+}
+
+static void tifm_sd_copy_page(struct page *dst, unsigned int dst_off,
+			      struct page *src, unsigned int src_off,
+			      unsigned int count)
+{
+	unsigned char *src_buf = kmap_atomic(src, KM_BIO_SRC_IRQ) + src_off;
+	unsigned char *dst_buf = kmap_atomic(dst, KM_BIO_DST_IRQ) + dst_off;
+
+	memcpy(dst_buf, src_buf, count);
+
+	kunmap_atomic(dst_buf - dst_off, KM_BIO_DST_IRQ);
+	kunmap_atomic(src_buf - src_off, KM_BIO_SRC_IRQ);
+}
+
+static void tifm_sd_bounce_block(struct tifm_sd *host, struct mmc_data *r_data)
+{
+	struct scatterlist *sg = r_data->sg;
+	unsigned int t_size = r_data->blksz;
+	unsigned int off, cnt;
+	unsigned int p_off, p_cnt;
+	struct page *pg;
+
+	dev_dbg(&host->dev->dev, "bouncing block\n");
+	while (t_size) {
+		cnt = sg[host->sg_pos].length - host->block_pos;
+		if (!cnt) {
+			host->block_pos = 0;
+			host->sg_pos++;
+			if (host->sg_pos == host->sg_len)
+				return;
+			cnt = sg[host->sg_pos].length;
+		}
+		off = sg[host->sg_pos].offset + host->block_pos;
+
+		pg = nth_page(sg[host->sg_pos].page, off >> PAGE_SHIFT);
+		p_off = offset_in_page(off);
+		p_cnt = PAGE_SIZE - p_off;
+		p_cnt = min(p_cnt, cnt);
+		p_cnt = min(p_cnt, t_size);
+
+		if (r_data->flags & MMC_DATA_WRITE)
+			tifm_sd_copy_page(host->bounce_buf.page,
+					  r_data->blksz - t_size,
+					  pg, p_off, p_cnt);
+		else if (r_data->flags & MMC_DATA_READ)
+			tifm_sd_copy_page(pg, p_off, host->bounce_buf.page,
+					  r_data->blksz - t_size, p_cnt);
+
+		t_size -= p_cnt;
+		host->block_pos += p_cnt;
+	}
+}
+
+static int tifm_sd_set_dma_data(struct tifm_sd *host, struct mmc_data *r_data)
+{
+	struct tifm_dev *sock = host->dev;
+	unsigned int t_size = TIFM_DMA_TSIZE * r_data->blksz;
+	unsigned int dma_len, dma_blk_cnt, dma_off;
+	struct scatterlist *sg = NULL;
+	unsigned long flags;
+
+	if (host->sg_pos == host->sg_len)
+		return 1;
+
+	if (host->cmd_flags & DATA_CARRY) {
+		host->cmd_flags &= ~DATA_CARRY;
+		local_irq_save(flags);
+		tifm_sd_bounce_block(host, r_data);
+		local_irq_restore(flags);
+		if (host->sg_pos == host->sg_len)
+			return 1;
+	}
+
+	dma_len = sg_dma_len(&r_data->sg[host->sg_pos]) - host->block_pos;
+	if (!dma_len) {
+		host->block_pos = 0;
+		host->sg_pos++;
+		if (host->sg_pos == host->sg_len)
+			return 1;
+		dma_len = sg_dma_len(&r_data->sg[host->sg_pos]);
+	}
+
+	if (dma_len < t_size) {
+		dma_blk_cnt = dma_len / r_data->blksz;
+		dma_off = host->block_pos;
+		host->block_pos += dma_blk_cnt * r_data->blksz;
+	} else {
+		dma_blk_cnt = TIFM_DMA_TSIZE;
+		dma_off = host->block_pos;
+		host->block_pos += t_size;
+	}
+
+	if (dma_blk_cnt)
+		sg = &r_data->sg[host->sg_pos];
+	else if (dma_len) {
+		if (r_data->flags & MMC_DATA_WRITE) {
+			local_irq_save(flags);
+			tifm_sd_bounce_block(host, r_data);
+			local_irq_restore(flags);
+		} else
+			host->cmd_flags |= DATA_CARRY;
+
+		sg = &host->bounce_buf;
+		dma_off = 0;
+		dma_blk_cnt = 1;
+	} else
+		return 1;
+
+	dev_dbg(&sock->dev, "setting dma for %d blocks\n", dma_blk_cnt);
+	writel(sg_dma_address(sg) + dma_off, sock->addr + SOCK_DMA_ADDRESS);
+	if (r_data->flags & MMC_DATA_WRITE)
+		writel((dma_blk_cnt << 8) | TIFM_DMA_TX | TIFM_DMA_EN,
+		       sock->addr + SOCK_DMA_CONTROL);
+	else
+		writel((dma_blk_cnt << 8) | TIFM_DMA_EN,
+		       sock->addr + SOCK_DMA_CONTROL);
+
+	return 0;
+}
+
+static unsigned int tifm_sd_op_flags(struct mmc_command *cmd)
+{
+	unsigned int rc = 0;
+
+	switch (mmc_resp_type(cmd)) {
+	case MMC_RSP_NONE:
+		rc |= TIFM_MMCSD_RSP_R0;
+		break;
+	case MMC_RSP_R1B:
+		rc |= TIFM_MMCSD_RSP_BUSY; // deliberate fall-through
+	case MMC_RSP_R1:
+		rc |= TIFM_MMCSD_RSP_R1;
+		break;
+	case MMC_RSP_R2:
+		rc |= TIFM_MMCSD_RSP_R2;
+		break;
+	case MMC_RSP_R3:
+		rc |= TIFM_MMCSD_RSP_R3;
+		break;
+	default:
+		BUG();
+	}
+
+	switch (mmc_cmd_type(cmd)) {
+	case MMC_CMD_BC:
+		rc |= TIFM_MMCSD_CMD_BC;
+		break;
+	case MMC_CMD_BCR:
+		rc |= TIFM_MMCSD_CMD_BCR;
+		break;
+	case MMC_CMD_AC:
+		rc |= TIFM_MMCSD_CMD_AC;
+		break;
+	case MMC_CMD_ADTC:
+		rc |= TIFM_MMCSD_CMD_ADTC;
+		break;
+	default:
+		BUG();
+	}
+	return rc;
+}
+
+static void tifm_sd_exec(struct tifm_sd *host, struct mmc_command *cmd)
+{
+	struct tifm_dev *sock = host->dev;
+	unsigned int cmd_mask = tifm_sd_op_flags(cmd);
+
+	if (host->open_drain)
+		cmd_mask |= TIFM_MMCSD_ODTO;
+
+	if (cmd->data && (cmd->data->flags & MMC_DATA_READ))
+		cmd_mask |= TIFM_MMCSD_READ;
+
+	dev_dbg(&sock->dev, "executing opcode 0x%x, arg: 0x%x, mask: 0x%x\n",
+		cmd->opcode, cmd->arg, cmd_mask);
+
+	writel((cmd->arg >> 16) & 0xffff, sock->addr + SOCK_MMCSD_ARG_HIGH);
+	writel(cmd->arg & 0xffff, sock->addr + SOCK_MMCSD_ARG_LOW);
+	writel(cmd->opcode | cmd_mask, sock->addr + SOCK_MMCSD_COMMAND);
+}
+
+static void tifm_sd_fetch_resp(struct mmc_command *cmd, struct tifm_dev *sock)
+{
+	cmd->resp[0] = (readl(sock->addr + SOCK_MMCSD_RESPONSE + 0x1c) << 16)
+		       | readl(sock->addr + SOCK_MMCSD_RESPONSE + 0x18);
+	cmd->resp[1] = (readl(sock->addr + SOCK_MMCSD_RESPONSE + 0x14) << 16)
+		       | readl(sock->addr + SOCK_MMCSD_RESPONSE + 0x10);
+	cmd->resp[2] = (readl(sock->addr + SOCK_MMCSD_RESPONSE + 0x0c) << 16)
+		       | readl(sock->addr + SOCK_MMCSD_RESPONSE + 0x08);
+	cmd->resp[3] = (readl(sock->addr + SOCK_MMCSD_RESPONSE + 0x04) << 16)
+		       | readl(sock->addr + SOCK_MMCSD_RESPONSE + 0x00);
+}
+
+static void tifm_sd_check_status(struct tifm_sd *host)
+{
+	struct tifm_dev *sock = host->dev;
+	struct mmc_command *cmd = host->req->cmd;
+
+	if (cmd->error != MMC_ERR_NONE)
+		goto finish_request;
+
+	if (!(host->cmd_flags & CMD_READY))
+		return;
+
+	if (cmd->data) {
+		if (cmd->data->error != MMC_ERR_NONE) {
+			if ((host->cmd_flags & SCMD_ACTIVE)
+			    && !(host->cmd_flags & SCMD_READY))
+				return;
+
+			goto finish_request;
+		}
+
+		if (!(host->cmd_flags & BRS_READY))
+			return;
+
+		if (!(host->no_dma || (host->cmd_flags & FIFO_READY)))
+			return;
+
+		if (cmd->data->flags & MMC_DATA_WRITE) {
+			if (host->req->stop) {
+				if (!(host->cmd_flags & SCMD_ACTIVE)) {
+					host->cmd_flags |= SCMD_ACTIVE;
+					writel(TIFM_MMCSD_EOFB
+					       | readl(sock->addr
+						       + SOCK_MMCSD_INT_ENABLE),
+					       sock->addr
+					       + SOCK_MMCSD_INT_ENABLE);
+					tifm_sd_exec(host, host->req->stop);
+					return;
+				} else {
+					if (!(host->cmd_flags & SCMD_READY)
+					    || (host->cmd_flags & CARD_BUSY))
+						return;
+					writel((~TIFM_MMCSD_EOFB)
+					       & readl(sock->addr
+						       + SOCK_MMCSD_INT_ENABLE),
+					       sock->addr
+					       + SOCK_MMCSD_INT_ENABLE);
+				}
+			} else {
+				if (host->cmd_flags & CARD_BUSY)
+					return;
+				writel((~TIFM_MMCSD_EOFB)
+				       & readl(sock->addr
+					       + SOCK_MMCSD_INT_ENABLE),
+				       sock->addr + SOCK_MMCSD_INT_ENABLE);
+			}
+		} else {
+			if (host->req->stop) {
+				if (!(host->cmd_flags & SCMD_ACTIVE)) {
+					host->cmd_flags |= SCMD_ACTIVE;
+					tifm_sd_exec(host, host->req->stop);
+					return;
+				} else {
+					if (!(host->cmd_flags & SCMD_READY))
+						return;
+				}
+			}
+		}
+	}
+finish_request:
+	tasklet_schedule(&host->finish_tasklet);
+}
+
+/* Called from interrupt handler */
+static void tifm_sd_data_event(struct tifm_dev *sock)
+{
+	struct tifm_sd *host;
+	unsigned int fifo_status = 0;
+	struct mmc_data *r_data = NULL;
+
+	spin_lock(&sock->lock);
+	host = mmc_priv((struct mmc_host*)tifm_get_drvdata(sock));
+	fifo_status = readl(sock->addr + SOCK_DMA_FIFO_STATUS);
+	dev_dbg(&sock->dev, "data event: fifo_status %x, flags %x\n",
+		fifo_status, host->cmd_flags);
+
+	if (host->req) {
+		r_data = host->req->cmd->data;
+
+		if (r_data && (fifo_status & TIFM_FIFO_READY)) {
+			if (tifm_sd_set_dma_data(host, r_data)) {
+				host->cmd_flags |= FIFO_READY;
+				tifm_sd_check_status(host);
+			}
+		}
+	}
+
+	writel(fifo_status, sock->addr + SOCK_DMA_FIFO_STATUS);
+	spin_unlock(&sock->lock);
+}
+
+/* Called from interrupt handler */
+static void tifm_sd_card_event(struct tifm_dev *sock)
+{
+	struct tifm_sd *host;
+	unsigned int host_status = 0;
+	int cmd_error = MMC_ERR_NONE;
+	struct mmc_command *cmd = NULL;
+	unsigned long flags;
+
+	spin_lock(&sock->lock);
+	host = mmc_priv((struct mmc_host*)tifm_get_drvdata(sock));
+	host_status = readl(sock->addr + SOCK_MMCSD_STATUS);
+	dev_dbg(&sock->dev, "host event: host_status %x, flags %x\n",
+		host_status, host->cmd_flags);
+
+	if (host->req) {
+		cmd = host->req->cmd;
+
+		if (host_status & TIFM_MMCSD_ERRMASK) {
+			writel(host_status & TIFM_MMCSD_ERRMASK,
+			       sock->addr + SOCK_MMCSD_STATUS);
+			if (host_status & TIFM_MMCSD_CTO)
+				cmd_error = MMC_ERR_TIMEOUT;
+			else if (host_status & TIFM_MMCSD_CCRC)
+				cmd_error = MMC_ERR_BADCRC;
+
+			if (cmd->data) {
+				if (host_status & TIFM_MMCSD_DTO)
+					cmd->data->error = MMC_ERR_TIMEOUT;
+				else if (host_status & TIFM_MMCSD_DCRC)
+					cmd->data->error = MMC_ERR_BADCRC;
+			}
+
+			writel(TIFM_FIFO_INT_SETALL,
+			       sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR);
+			writel(TIFM_DMA_RESET, sock->addr + SOCK_DMA_CONTROL);
+
+			if (host->req->stop) {
+				if (host->cmd_flags & SCMD_ACTIVE) {
+					host->req->stop->error = cmd_error;
+					host->cmd_flags |= SCMD_READY;
+				} else {
+					cmd->error = cmd_error;
+					host->cmd_flags |= SCMD_ACTIVE;
+					tifm_sd_exec(host, host->req->stop);
+					goto done;
+				}
+			} else
+				cmd->error = cmd_error;
+		} else {
+			if (host_status & (TIFM_MMCSD_EOC | TIFM_MMCSD_CERR)) {
+				if (!(host->cmd_flags & CMD_READY)) {
+					host->cmd_flags |= CMD_READY;
+					tifm_sd_fetch_resp(cmd, sock);
+				} else if (host->cmd_flags & SCMD_ACTIVE) {
+					host->cmd_flags |= SCMD_READY;
+					tifm_sd_fetch_resp(host->req->stop,
+							   sock);
+				}
+			}
+			if (host_status & TIFM_MMCSD_BRS)
+				host->cmd_flags |= BRS_READY;
+		}
+
+		if (host->no_dma && cmd->data) {
+			if (host_status & TIFM_MMCSD_AE)
+				writel(host_status & TIFM_MMCSD_AE,
+				       sock->addr + SOCK_MMCSD_STATUS);
+
+			if (host_status & (TIFM_MMCSD_AE | TIFM_MMCSD_AF
+					   | TIFM_MMCSD_BRS)) {
+				local_irq_save(flags);
+				tifm_sd_transfer_data(host);
+				local_irq_restore(flags);
+				host_status &= ~TIFM_MMCSD_AE;
+			}
+		}
+
+		if (host_status & TIFM_MMCSD_EOFB)
+			host->cmd_flags &= ~CARD_BUSY;
+		else if (host_status & TIFM_MMCSD_CB)
+			host->cmd_flags |= CARD_BUSY;
+
+		tifm_sd_check_status(host);
+	}
+done:
+	writel(host_status, sock->addr + SOCK_MMCSD_STATUS);
+	spin_unlock(&sock->lock);
+}
+
+static void tifm_sd_set_data_timeout(struct tifm_sd *host,
+				     struct mmc_data *data)
+{
+	struct tifm_dev *sock = host->dev;
+	unsigned int data_timeout = data->timeout_clks;
+
+	if (fixed_timeout)
+		return;
+
+	data_timeout += data->timeout_ns /
+			((1000000000UL / host->clk_freq) * host->clk_div);
+
+	if (data_timeout < 0xffff) {
+		writel(data_timeout, sock->addr + SOCK_MMCSD_DATA_TO);
+		writel((~TIFM_MMCSD_DPE)
+		       & readl(sock->addr + SOCK_MMCSD_SDIO_MODE_CONFIG),
+		       sock->addr + SOCK_MMCSD_SDIO_MODE_CONFIG);
+	} else {
+		data_timeout = (data_timeout >> 10) + 1;
+		if (data_timeout > 0xffff)
+			data_timeout = 0;	/* set to unlimited */
+		writel(data_timeout, sock->addr + SOCK_MMCSD_DATA_TO);
+		writel(TIFM_MMCSD_DPE
+		       | readl(sock->addr + SOCK_MMCSD_SDIO_MODE_CONFIG),
+		       sock->addr + SOCK_MMCSD_SDIO_MODE_CONFIG);
+	}
+}
+
+static void tifm_sd_request(struct mmc_host *mmc, struct mmc_request *mrq)
+{
+	struct tifm_sd *host = mmc_priv(mmc);
+	struct tifm_dev *sock = host->dev;
+	unsigned long flags;
+	struct mmc_data *r_data = mrq->cmd->data;
+
+	spin_lock_irqsave(&sock->lock, flags);
+	if (host->eject) {
+		spin_unlock_irqrestore(&sock->lock, flags);
+		goto err_out;
+	}
+
+	if (host->req) {
+		printk(KERN_ERR "%s : unfinished request detected\n",
+		       sock->dev.bus_id);
+		spin_unlock_irqrestore(&sock->lock, flags);
+		goto err_out;
+	}
+
+	host->cmd_flags = 0;
+	host->block_pos = 0;
+	host->sg_pos = 0;
+
+	if (r_data) {
+		tifm_sd_set_data_timeout(host, r_data);
+
+		if ((r_data->flags & MMC_DATA_WRITE) && !mrq->stop)
+			 writel(TIFM_MMCSD_EOFB
+				| readl(sock->addr + SOCK_MMCSD_INT_ENABLE),
+				sock->addr + SOCK_MMCSD_INT_ENABLE);
+
+		if (host->no_dma) {
+			writel(TIFM_MMCSD_BUFINT
+			       | readl(sock->addr + SOCK_MMCSD_INT_ENABLE),
+			       sock->addr + SOCK_MMCSD_INT_ENABLE);
+			writel(((TIFM_MMCSD_FIFO_SIZE - 1) << 8)
+			       | (TIFM_MMCSD_FIFO_SIZE - 1),
+			       sock->addr + SOCK_MMCSD_BUFFER_CONFIG);
+
+			host->sg_len = r_data->sg_len;
+		} else {
+			sg_init_one(&host->bounce_buf, host->bounce_buf_data,
+				    r_data->blksz);
+
+			if(1 != tifm_map_sg(sock, &host->bounce_buf, 1,
+					    r_data->flags & MMC_DATA_WRITE
+					    ? PCI_DMA_TODEVICE
+					    : PCI_DMA_FROMDEVICE)) {
+				printk(KERN_ERR "%s : scatterlist map failed\n",
+				       sock->dev.bus_id);
+				spin_unlock_irqrestore(&sock->lock, flags);
+				goto err_out;
+			}
+			host->sg_len = tifm_map_sg(sock, r_data->sg,
+						   r_data->sg_len,
+						   r_data->flags
+						   & MMC_DATA_WRITE
+						   ? PCI_DMA_TODEVICE
+						   : PCI_DMA_FROMDEVICE);
+			if (host->sg_len < 1) {
+				printk(KERN_ERR "%s : scatterlist map failed\n",
+				       sock->dev.bus_id);
+				tifm_unmap_sg(sock, &host->bounce_buf, 1,
+					      r_data->flags & MMC_DATA_WRITE
+					      ? PCI_DMA_TODEVICE
+					      : PCI_DMA_FROMDEVICE);
+				spin_unlock_irqrestore(&sock->lock, flags);
+				goto err_out;
+			}
+
+			writel(TIFM_FIFO_INT_SETALL,
+			       sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR);
+			writel(ilog2(r_data->blksz) - 2,
+			       sock->addr + SOCK_FIFO_PAGE_SIZE);
+			writel(TIFM_FIFO_ENABLE,
+			       sock->addr + SOCK_FIFO_CONTROL);
+			writel(TIFM_FIFO_INTMASK,
+			       sock->addr + SOCK_DMA_FIFO_INT_ENABLE_SET);
+
+			if (r_data->flags & MMC_DATA_WRITE)
+				writel(TIFM_MMCSD_TXDE,
+				       sock->addr + SOCK_MMCSD_BUFFER_CONFIG);
+			else
+				writel(TIFM_MMCSD_RXDE,
+				       sock->addr + SOCK_MMCSD_BUFFER_CONFIG);
+
+			tifm_sd_set_dma_data(host, r_data);
+		}
+
+		writel(r_data->blocks - 1,
+		       sock->addr + SOCK_MMCSD_NUM_BLOCKS);
+		writel(r_data->blksz - 1,
+		       sock->addr + SOCK_MMCSD_BLOCK_LEN);
+	}
+
+	host->req = mrq;
+	mod_timer(&host->timer, jiffies + host->timeout_jiffies);
+	writel(TIFM_CTRL_LED | readl(sock->addr + SOCK_CONTROL),
+	       sock->addr + SOCK_CONTROL);
+	tifm_sd_exec(host, mrq->cmd);
+	spin_unlock_irqrestore(&sock->lock, flags);
+	return;
+
+err_out:
+	mrq->cmd->error = MMC_ERR_TIMEOUT;
+	mmc_request_done(mmc, mrq);
+}
+
+static void tifm_sd_end_cmd(unsigned long data)
+{
+	struct tifm_sd *host = (struct tifm_sd*)data;
+	struct tifm_dev *sock = host->dev;
+	struct mmc_host *mmc = tifm_get_drvdata(sock);
+	struct mmc_request *mrq;
+	struct mmc_data *r_data = NULL;
+	unsigned long flags;
+
+	spin_lock_irqsave(&sock->lock, flags);
+
+	del_timer(&host->timer);
+	mrq = host->req;
+	host->req = NULL;
+
+	if (!mrq) {
+		printk(KERN_ERR " %s : no request to complete?\n",
+		       sock->dev.bus_id);
+		spin_unlock_irqrestore(&sock->lock, flags);
+		return;
+	}
+
+	r_data = mrq->cmd->data;
+	if (r_data) {
+		if (host->no_dma) {
+			writel((~TIFM_MMCSD_BUFINT)
+			       & readl(sock->addr + SOCK_MMCSD_INT_ENABLE),
+			       sock->addr + SOCK_MMCSD_INT_ENABLE);
+		} else {
+			tifm_unmap_sg(sock, &host->bounce_buf, 1,
+				      (r_data->flags & MMC_DATA_WRITE)
+				      ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE);
+			tifm_unmap_sg(sock, r_data->sg, r_data->sg_len,
+				      (r_data->flags & MMC_DATA_WRITE)
+				      ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE);
+		}
+
+		r_data->bytes_xfered = r_data->blocks
+			- readl(sock->addr + SOCK_MMCSD_NUM_BLOCKS) - 1;
+		r_data->bytes_xfered *= r_data->blksz;
+		r_data->bytes_xfered += r_data->blksz
+			- readl(sock->addr + SOCK_MMCSD_BLOCK_LEN) + 1;
+	}
+
+	writel((~TIFM_CTRL_LED) & readl(sock->addr + SOCK_CONTROL),
+	       sock->addr + SOCK_CONTROL);
+
+	spin_unlock_irqrestore(&sock->lock, flags);
+	mmc_request_done(mmc, mrq);
+}
+
+static void tifm_sd_abort(unsigned long data)
+{
+	struct tifm_sd *host = (struct tifm_sd*)data;
+
+	printk(KERN_ERR
+	       "%s : card failed to respond for a long period of time "
+	       "(%x, %x)\n",
+	       host->dev->dev.bus_id, host->req->cmd->opcode, host->cmd_flags);
+
+	tifm_eject(host->dev);
+}
+
+static void tifm_sd_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+	struct tifm_sd *host = mmc_priv(mmc);
+	struct tifm_dev *sock = host->dev;
+	unsigned int clk_div1, clk_div2;
+	unsigned long flags;
+
+	spin_lock_irqsave(&sock->lock, flags);
+
+	dev_dbg(&sock->dev, "ios: clock = %u, vdd = %x, bus_mode = %x, "
+		"chip_select = %x, power_mode = %x, bus_width = %x\n",
+		ios->clock, ios->vdd, ios->bus_mode, ios->chip_select,
+		ios->power_mode, ios->bus_width);
+
+	if (ios->bus_width == MMC_BUS_WIDTH_4) {
+		writel(TIFM_MMCSD_4BBUS | readl(sock->addr + SOCK_MMCSD_CONFIG),
+		       sock->addr + SOCK_MMCSD_CONFIG);
+	} else {
+		writel((~TIFM_MMCSD_4BBUS)
+		       & readl(sock->addr + SOCK_MMCSD_CONFIG),
+		       sock->addr + SOCK_MMCSD_CONFIG);
+	}
+
+	if (ios->clock) {
+		clk_div1 = 20000000 / ios->clock;
+		if (!clk_div1)
+			clk_div1 = 1;
+
+		clk_div2 = 24000000 / ios->clock;
+		if (!clk_div2)
+			clk_div2 = 1;
+
+		if ((20000000 / clk_div1) > ios->clock)
+			clk_div1++;
+		if ((24000000 / clk_div2) > ios->clock)
+			clk_div2++;
+		if ((20000000 / clk_div1) > (24000000 / clk_div2)) {
+			host->clk_freq = 20000000;
+			host->clk_div = clk_div1;
+			writel((~TIFM_CTRL_FAST_CLK)
+			       & readl(sock->addr + SOCK_CONTROL),
+			       sock->addr + SOCK_CONTROL);
+		} else {
+			host->clk_freq = 24000000;
+			host->clk_div = clk_div2;
+			writel(TIFM_CTRL_FAST_CLK
+			       | readl(sock->addr + SOCK_CONTROL),
+			       sock->addr + SOCK_CONTROL);
+		}
+	} else {
+		host->clk_div = 0;
+	}
+	host->clk_div &= TIFM_MMCSD_CLKMASK;
+	writel(host->clk_div
+	       | ((~TIFM_MMCSD_CLKMASK)
+		  & readl(sock->addr + SOCK_MMCSD_CONFIG)),
+	       sock->addr + SOCK_MMCSD_CONFIG);
+
+	host->open_drain = (ios->bus_mode == MMC_BUSMODE_OPENDRAIN);
+
+	/* chip_select : maybe later */
+	//vdd
+	//power is set before probe / after remove
+
+	spin_unlock_irqrestore(&sock->lock, flags);
+}
+
+static int tifm_sd_ro(struct mmc_host *mmc)
+{
+	int rc = 0;
+	struct tifm_sd *host = mmc_priv(mmc);
+	struct tifm_dev *sock = host->dev;
+	unsigned long flags;
+
+	spin_lock_irqsave(&sock->lock, flags);
+	if (TIFM_MMCSD_CARD_RO & readl(sock->addr + SOCK_PRESENT_STATE))
+		rc = 1;
+	spin_unlock_irqrestore(&sock->lock, flags);
+	return rc;
+}
+
+static const struct mmc_host_ops tifm_sd_ops = {
+	.request = tifm_sd_request,
+	.set_ios = tifm_sd_ios,
+	.get_ro  = tifm_sd_ro
+};
+
+static int tifm_sd_initialize_host(struct tifm_sd *host)
+{
+	int rc;
+	unsigned int host_status = 0;
+	struct tifm_dev *sock = host->dev;
+
+	writel(0, sock->addr + SOCK_MMCSD_INT_ENABLE);
+	mmiowb();
+	host->clk_div = 61;
+	host->clk_freq = 20000000;
+	writel(TIFM_MMCSD_RESET, sock->addr + SOCK_MMCSD_SYSTEM_CONTROL);
+	writel(host->clk_div | TIFM_MMCSD_POWER,
+	       sock->addr + SOCK_MMCSD_CONFIG);
+
+	/* wait up to 0.51 sec for reset */
+	for (rc = 32; rc <= 256; rc <<= 1) {
+		if (1 & readl(sock->addr + SOCK_MMCSD_SYSTEM_STATUS)) {
+			rc = 0;
+			break;
+		}
+		msleep(rc);
+	}
+
+	if (rc) {
+		printk(KERN_ERR "%s : controller failed to reset\n",
+		       sock->dev.bus_id);
+		return -ENODEV;
+	}
+
+	writel(0, sock->addr + SOCK_MMCSD_NUM_BLOCKS);
+	writel(host->clk_div | TIFM_MMCSD_POWER,
+	       sock->addr + SOCK_MMCSD_CONFIG);
+	writel(TIFM_MMCSD_RXDE, sock->addr + SOCK_MMCSD_BUFFER_CONFIG);
+
+	// command timeout fixed to 64 clocks for now
+	writel(64, sock->addr + SOCK_MMCSD_COMMAND_TO);
+	writel(TIFM_MMCSD_INAB, sock->addr + SOCK_MMCSD_COMMAND);
+
+	for (rc = 16; rc <= 64; rc <<= 1) {
+		host_status = readl(sock->addr + SOCK_MMCSD_STATUS);
+		writel(host_status, sock->addr + SOCK_MMCSD_STATUS);
+		if (!(host_status & TIFM_MMCSD_ERRMASK)
+		    && (host_status & TIFM_MMCSD_EOC)) {
+			rc = 0;
+			break;
+		}
+		msleep(rc);
+	}
+
+	if (rc) {
+		printk(KERN_ERR
+		       "%s : card not ready - probe failed on initialization\n",
+		       sock->dev.bus_id);
+		return -ENODEV;
+	}
+
+	writel(TIFM_MMCSD_CERR | TIFM_MMCSD_BRS | TIFM_MMCSD_EOC
+	       | TIFM_MMCSD_ERRMASK,
+	       sock->addr + SOCK_MMCSD_INT_ENABLE);
+	mmiowb();
+
+	return 0;
+}
+
+static int tifm_sd_probe(struct tifm_dev *sock)
+{
+	struct mmc_host *mmc;
+	struct tifm_sd *host;
+	int rc = -EIO;
+
+	if (!(TIFM_SOCK_STATE_OCCUPIED
+	      & readl(sock->addr + SOCK_PRESENT_STATE))) {
+		printk(KERN_WARNING "%s : card gone, unexpectedly\n",
+		       sock->dev.bus_id);
+		return rc;
+	}
+
+	mmc = mmc_alloc_host(sizeof(struct tifm_sd), &sock->dev);
+	if (!mmc)
+		return -ENOMEM;
+
+	host = mmc_priv(mmc);
+	host->no_dma = no_dma;
+	tifm_set_drvdata(sock, mmc);
+	host->dev = sock;
+	host->timeout_jiffies = msecs_to_jiffies(1000);
+
+	tasklet_init(&host->finish_tasklet, tifm_sd_end_cmd,
+		     (unsigned long)host);
+	setup_timer(&host->timer, tifm_sd_abort, (unsigned long)host);
+
+	mmc->ops = &tifm_sd_ops;
+	mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
+	mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_MULTIWRITE;
+	mmc->f_min = 20000000 / 60;
+	mmc->f_max = 24000000;
+
+	mmc->max_blk_count = 2048;
+	mmc->max_hw_segs = mmc->max_blk_count;
+	mmc->max_blk_size = min(TIFM_MMCSD_MAX_BLOCK_SIZE, PAGE_SIZE);
+	mmc->max_seg_size = mmc->max_blk_count * mmc->max_blk_size;
+	mmc->max_req_size = mmc->max_seg_size;
+	mmc->max_phys_segs = mmc->max_hw_segs;
+
+	sock->card_event = tifm_sd_card_event;
+	sock->data_event = tifm_sd_data_event;
+	rc = tifm_sd_initialize_host(host);
+
+	if (!rc)
+		rc = mmc_add_host(mmc);
+	if (!rc)
+		return 0;
+
+	mmc_free_host(mmc);
+	return rc;
+}
+
+static void tifm_sd_remove(struct tifm_dev *sock)
+{
+	struct mmc_host *mmc = tifm_get_drvdata(sock);
+	struct tifm_sd *host = mmc_priv(mmc);
+	unsigned long flags;
+
+	spin_lock_irqsave(&sock->lock, flags);
+	host->eject = 1;
+	writel(0, sock->addr + SOCK_MMCSD_INT_ENABLE);
+	mmiowb();
+	spin_unlock_irqrestore(&sock->lock, flags);
+
+	tasklet_kill(&host->finish_tasklet);
+
+	spin_lock_irqsave(&sock->lock, flags);
+	if (host->req) {
+		writel(TIFM_FIFO_INT_SETALL,
+		       sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR);
+		writel(0, sock->addr + SOCK_DMA_FIFO_INT_ENABLE_SET);
+		host->req->cmd->error = MMC_ERR_TIMEOUT;
+		if (host->req->stop)
+			host->req->stop->error = MMC_ERR_TIMEOUT;
+		tasklet_schedule(&host->finish_tasklet);
+	}
+	spin_unlock_irqrestore(&sock->lock, flags);
+	mmc_remove_host(mmc);
+	dev_dbg(&sock->dev, "after remove\n");
+
+	/* The meaning of the bit majority in this constant is unknown. */
+	writel(0xfff8 & readl(sock->addr + SOCK_CONTROL),
+	       sock->addr + SOCK_CONTROL);
+
+	mmc_free_host(mmc);
+}
+
+#ifdef CONFIG_PM
+
+static int tifm_sd_suspend(struct tifm_dev *sock, pm_message_t state)
+{
+	struct mmc_host *mmc = tifm_get_drvdata(sock);
+	int rc;
+
+	rc = mmc_suspend_host(mmc, state);
+	/* The meaning of the bit majority in this constant is unknown. */
+	writel(0xfff8 & readl(sock->addr + SOCK_CONTROL),
+	       sock->addr + SOCK_CONTROL);
+	return rc;
+}
+
+static int tifm_sd_resume(struct tifm_dev *sock)
+{
+	struct mmc_host *mmc = tifm_get_drvdata(sock);
+	struct tifm_sd *host = mmc_priv(mmc);
+	int rc;
+
+	rc = tifm_sd_initialize_host(host);
+	dev_dbg(&sock->dev, "resume initialize %d\n", rc);
+
+	if (rc)
+		host->eject = 1;
+	else
+		rc = mmc_resume_host(mmc);
+
+	return rc;
+}
+
+#else
+
+#define tifm_sd_suspend NULL
+#define tifm_sd_resume NULL
+
+#endif /* CONFIG_PM */
+
+static struct tifm_device_id tifm_sd_id_tbl[] = {
+	{ TIFM_TYPE_SD }, { }
+};
+
+static struct tifm_driver tifm_sd_driver = {
+	.driver = {
+		.name  = DRIVER_NAME,
+		.owner = THIS_MODULE
+	},
+	.id_table = tifm_sd_id_tbl,
+	.probe    = tifm_sd_probe,
+	.remove   = tifm_sd_remove,
+	.suspend  = tifm_sd_suspend,
+	.resume   = tifm_sd_resume
+};
+
+static int __init tifm_sd_init(void)
+{
+	return tifm_register_driver(&tifm_sd_driver);
+}
+
+static void __exit tifm_sd_exit(void)
+{
+	tifm_unregister_driver(&tifm_sd_driver);
+}
+
+MODULE_AUTHOR("Alex Dubov");
+MODULE_DESCRIPTION("TI FlashMedia SD driver");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(tifm, tifm_sd_id_tbl);
+MODULE_VERSION(DRIVER_VERSION);
+
+module_init(tifm_sd_init);
+module_exit(tifm_sd_exit);
diff --git a/drivers/mmc/wbsd.c b/drivers/mmc/host/wbsd.c
similarity index 92%
rename from drivers/mmc/wbsd.c
rename to drivers/mmc/host/wbsd.c
index 05ccfc4..867ca6a 100644
--- a/drivers/mmc/wbsd.c
+++ b/drivers/mmc/host/wbsd.c
@@ -1,7 +1,7 @@
 /*
  *  linux/drivers/mmc/wbsd.c - Winbond W83L51xD SD/MMC driver
  *
- *  Copyright (C) 2004-2006 Pierre Ossman, All Rights Reserved.
+ *  Copyright (C) 2004-2007 Pierre Ossman, 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
@@ -33,7 +33,6 @@
 #include <linux/pnp.h>
 #include <linux/highmem.h>
 #include <linux/mmc/host.h>
-#include <linux/mmc/protocol.h>
 
 #include <asm/io.h>
 #include <asm/dma.h>
@@ -178,9 +177,8 @@
 	ier = 0;
 	ier |= WBSD_EINT_CARD;
 	ier |= WBSD_EINT_FIFO_THRE;
-	ier |= WBSD_EINT_CCRC;
-	ier |= WBSD_EINT_TIMEOUT;
 	ier |= WBSD_EINT_CRC;
+	ier |= WBSD_EINT_TIMEOUT;
 	ier |= WBSD_EINT_TC;
 
 	outb(ier, host->base + WBSD_EIR);
@@ -278,90 +276,36 @@
 
 static inline void wbsd_sg_to_dma(struct wbsd_host *host, struct mmc_data *data)
 {
-	unsigned int len, i, size;
+	unsigned int len, i;
 	struct scatterlist *sg;
 	char *dmabuf = host->dma_buffer;
 	char *sgbuf;
 
-	size = host->size;
-
 	sg = data->sg;
 	len = data->sg_len;
 
-	/*
-	 * Just loop through all entries. Size might not
-	 * be the entire list though so make sure that
-	 * we do not transfer too much.
-	 */
 	for (i = 0; i < len; i++) {
 		sgbuf = page_address(sg[i].page) + sg[i].offset;
-		if (size < sg[i].length)
-			memcpy(dmabuf, sgbuf, size);
-		else
-			memcpy(dmabuf, sgbuf, sg[i].length);
+		memcpy(dmabuf, sgbuf, sg[i].length);
 		dmabuf += sg[i].length;
-
-		if (size < sg[i].length)
-			size = 0;
-		else
-			size -= sg[i].length;
-
-		if (size == 0)
-			break;
 	}
-
-	/*
-	 * Check that we didn't get a request to transfer
-	 * more data than can fit into the SG list.
-	 */
-
-	BUG_ON(size != 0);
-
-	host->size -= size;
 }
 
 static inline void wbsd_dma_to_sg(struct wbsd_host *host, struct mmc_data *data)
 {
-	unsigned int len, i, size;
+	unsigned int len, i;
 	struct scatterlist *sg;
 	char *dmabuf = host->dma_buffer;
 	char *sgbuf;
 
-	size = host->size;
-
 	sg = data->sg;
 	len = data->sg_len;
 
-	/*
-	 * Just loop through all entries. Size might not
-	 * be the entire list though so make sure that
-	 * we do not transfer too much.
-	 */
 	for (i = 0; i < len; i++) {
 		sgbuf = page_address(sg[i].page) + sg[i].offset;
-		if (size < sg[i].length)
-			memcpy(sgbuf, dmabuf, size);
-		else
-			memcpy(sgbuf, dmabuf, sg[i].length);
+		memcpy(sgbuf, dmabuf, sg[i].length);
 		dmabuf += sg[i].length;
-
-		if (size < sg[i].length)
-			size = 0;
-		else
-			size -= sg[i].length;
-
-		if (size == 0)
-			break;
 	}
-
-	/*
-	 * Check that we didn't get a request to transfer
-	 * more data than can fit into the SG list.
-	 */
-
-	BUG_ON(size != 0);
-
-	host->size -= size;
 }
 
 /*
@@ -484,7 +428,7 @@
 	/*
 	 * Handle excessive data.
 	 */
-	if (data->bytes_xfered == host->size)
+	if (host->num_sg == 0)
 		return;
 
 	buffer = wbsd_sg_to_buffer(host) + host->offset;
@@ -514,31 +458,14 @@
 			data->bytes_xfered++;
 
 			/*
-			 * Transfer done?
-			 */
-			if (data->bytes_xfered == host->size)
-				return;
-
-			/*
 			 * End of scatter list entry?
 			 */
 			if (host->remain == 0) {
 				/*
 				 * Get next entry. Check if last.
 				 */
-				if (!wbsd_next_sg(host)) {
-					/*
-					 * We should never reach this point.
-					 * It means that we're trying to
-					 * transfer more blocks than can fit
-					 * into the scatter list.
-					 */
-					BUG_ON(1);
-
-					host->size = data->bytes_xfered;
-
+				if (!wbsd_next_sg(host))
 					return;
-				}
 
 				buffer = wbsd_sg_to_buffer(host);
 			}
@@ -550,7 +477,7 @@
 	 * hardware problem. The chip doesn't trigger
 	 * FIFO threshold interrupts properly.
 	 */
-	if ((host->size - data->bytes_xfered) < 16)
+	if ((data->blocks * data->blksz - data->bytes_xfered) < 16)
 		tasklet_schedule(&host->fifo_tasklet);
 }
 
@@ -564,7 +491,7 @@
 	 * Check that we aren't being called after the
 	 * entire buffer has been transfered.
 	 */
-	if (data->bytes_xfered == host->size)
+	if (host->num_sg == 0)
 		return;
 
 	buffer = wbsd_sg_to_buffer(host) + host->offset;
@@ -594,31 +521,14 @@
 			data->bytes_xfered++;
 
 			/*
-			 * Transfer done?
-			 */
-			if (data->bytes_xfered == host->size)
-				return;
-
-			/*
 			 * End of scatter list entry?
 			 */
 			if (host->remain == 0) {
 				/*
 				 * Get next entry. Check if last.
 				 */
-				if (!wbsd_next_sg(host)) {
-					/*
-					 * We should never reach this point.
-					 * It means that we're trying to
-					 * transfer more blocks than can fit
-					 * into the scatter list.
-					 */
-					BUG_ON(1);
-
-					host->size = data->bytes_xfered;
-
+				if (!wbsd_next_sg(host))
 					return;
-				}
 
 				buffer = wbsd_sg_to_buffer(host);
 			}
@@ -638,6 +548,7 @@
 	u16 blksize;
 	u8 setup;
 	unsigned long dmaflags;
+	unsigned int size;
 
 	DBGF("blksz %04x blks %04x flags %08x\n",
 		data->blksz, data->blocks, data->flags);
@@ -647,7 +558,7 @@
 	/*
 	 * Calculate size.
 	 */
-	host->size = data->blocks * data->blksz;
+	size = data->blocks * data->blksz;
 
 	/*
 	 * Check timeout values for overflow.
@@ -705,8 +616,8 @@
 		/*
 		 * The buffer for DMA is only 64 kB.
 		 */
-		BUG_ON(host->size > 0x10000);
-		if (host->size > 0x10000) {
+		BUG_ON(size > 0x10000);
+		if (size > 0x10000) {
 			data->error = MMC_ERR_INVALID;
 			return;
 		}
@@ -729,7 +640,7 @@
 		else
 			set_dma_mode(host->dma, DMA_MODE_WRITE & ~0x40);
 		set_dma_addr(host->dma, host->dma_addr);
-		set_dma_count(host->dma, host->size);
+		set_dma_count(host->dma, size);
 
 		enable_dma(host->dma);
 		release_dma_lock(dmaflags);
@@ -812,6 +723,10 @@
 		count = get_dma_residue(host->dma);
 		release_dma_lock(dmaflags);
 
+		data->bytes_xfered = host->mrq->data->blocks *
+			host->mrq->data->blksz - count;
+		data->bytes_xfered -= data->bytes_xfered % data->blksz;
+
 		/*
 		 * Any leftover data?
 		 */
@@ -820,7 +735,8 @@
 				"%d bytes left.\n",
 				mmc_hostname(host->mmc), count);
 
-			data->error = MMC_ERR_FAILED;
+			if (data->error == MMC_ERR_NONE)
+				data->error = MMC_ERR_FAILED;
 		} else {
 			/*
 			 * Transfer data from DMA buffer to
@@ -828,8 +744,11 @@
 			 */
 			if (data->flags & MMC_DATA_READ)
 				wbsd_dma_to_sg(host, data);
+		}
 
-			data->bytes_xfered = host->size;
+		if (data->error != MMC_ERR_NONE) {
+			if (data->bytes_xfered)
+				data->bytes_xfered -= data->blksz;
 		}
 	}
 
@@ -869,24 +788,7 @@
 		goto done;
 	}
 
-	/*
-	 * Does the request include data?
-	 */
 	if (cmd->data) {
-		wbsd_prepare_data(host, cmd->data);
-
-		if (cmd->data->error != MMC_ERR_NONE)
-			goto done;
-	}
-
-	wbsd_send_command(host, cmd);
-
-	/*
-	 * If this is a data transfer the request
-	 * will be finished after the data has
-	 * transfered.
-	 */
-	if (cmd->data && (cmd->error == MMC_ERR_NONE)) {
 		/*
 		 * The hardware is so delightfully stupid that it has a list
 		 * of "data" commands. If a command isn't on this list, it'll
@@ -918,14 +820,30 @@
 				"supported by this controller.\n",
 				mmc_hostname(host->mmc), cmd->opcode);
 #endif
-			cmd->data->error = MMC_ERR_INVALID;
-
-			if (cmd->data->stop)
-				wbsd_send_command(host, cmd->data->stop);
+			cmd->error = MMC_ERR_INVALID;
 
 			goto done;
 		};
+	}
 
+	/*
+	 * Does the request include data?
+	 */
+	if (cmd->data) {
+		wbsd_prepare_data(host, cmd->data);
+
+		if (cmd->data->error != MMC_ERR_NONE)
+			goto done;
+	}
+
+	wbsd_send_command(host, cmd);
+
+	/*
+	 * If this is a data transfer the request
+	 * will be finished after the data has
+	 * transfered.
+	 */
+	if (cmd->data && (cmd->error == MMC_ERR_NONE)) {
 		/*
 		 * Dirty fix for hardware bug.
 		 */
@@ -1167,7 +1085,7 @@
 	/*
 	 * Done?
 	 */
-	if (host->size == data->bytes_xfered) {
+	if (host->num_sg == 0) {
 		wbsd_write_index(host, WBSD_IDX_FIFOEN, 0);
 		tasklet_schedule(&host->finish_tasklet);
 	}
@@ -1245,30 +1163,6 @@
 	spin_unlock(&host->lock);
 }
 
-static void wbsd_tasklet_block(unsigned long param)
-{
-	struct wbsd_host *host = (struct wbsd_host *)param;
-	struct mmc_data *data;
-
-	spin_lock(&host->lock);
-
-	if ((wbsd_read_index(host, WBSD_IDX_CRCSTATUS) & WBSD_CRC_MASK) !=
-		WBSD_CRC_OK) {
-		data = wbsd_get_data(host);
-		if (!data)
-			goto end;
-
-		DBGF("CRC error\n");
-
-		data->error = MMC_ERR_BADCRC;
-
-		tasklet_schedule(&host->finish_tasklet);
-	}
-
-end:
-	spin_unlock(&host->lock);
-}
-
 /*
  * Interrupt handling
  */
@@ -1299,8 +1193,6 @@
 		tasklet_hi_schedule(&host->crc_tasklet);
 	if (isr & WBSD_INT_TIMEOUT)
 		tasklet_hi_schedule(&host->timeout_tasklet);
-	if (isr & WBSD_INT_BUSYEND)
-		tasklet_hi_schedule(&host->block_tasklet);
 	if (isr & WBSD_INT_TC)
 		tasklet_schedule(&host->finish_tasklet);
 
@@ -1601,8 +1493,6 @@
 			(unsigned long)host);
 	tasklet_init(&host->finish_tasklet, wbsd_tasklet_finish,
 			(unsigned long)host);
-	tasklet_init(&host->block_tasklet, wbsd_tasklet_block,
-			(unsigned long)host);
 
 	return 0;
 }
@@ -1621,7 +1511,6 @@
 	tasklet_kill(&host->crc_tasklet);
 	tasklet_kill(&host->timeout_tasklet);
 	tasklet_kill(&host->finish_tasklet);
-	tasklet_kill(&host->block_tasklet);
 }
 
 /*
diff --git a/drivers/mmc/wbsd.h b/drivers/mmc/host/wbsd.h
similarity index 95%
rename from drivers/mmc/wbsd.h
rename to drivers/mmc/host/wbsd.h
index d06718b..873bda1 100644
--- a/drivers/mmc/wbsd.h
+++ b/drivers/mmc/host/wbsd.h
@@ -1,7 +1,7 @@
 /*
  *  linux/drivers/mmc/wbsd.h - Winbond W83L51xD SD/MMC driver
  *
- *  Copyright (C) 2004-2005 Pierre Ossman, All Rights Reserved.
+ *  Copyright (C) 2004-2007 Pierre Ossman, 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
@@ -46,10 +46,10 @@
 
 #define WBSD_EINT_CARD		0x40
 #define WBSD_EINT_FIFO_THRE	0x20
-#define WBSD_EINT_CCRC		0x10
+#define WBSD_EINT_CRC		0x10
 #define WBSD_EINT_TIMEOUT	0x08
 #define WBSD_EINT_PROGEND	0x04
-#define WBSD_EINT_CRC		0x02
+#define WBSD_EINT_BUSYEND	0x02
 #define WBSD_EINT_TC		0x01
 
 #define WBSD_INT_PENDING	0x80
@@ -158,8 +158,6 @@
 	unsigned int		offset;		/* Offset into current entry */
 	unsigned int		remain;		/* Data left in curren entry */
 
-	int			size;		/* Total size of transfer */
-
 	char*			dma_buffer;	/* ISA DMA buffer */
 	dma_addr_t		dma_addr;	/* Physical address for same */
 
@@ -182,7 +180,6 @@
 	struct tasklet_struct	crc_tasklet;
 	struct tasklet_struct	timeout_tasklet;
 	struct tasklet_struct	finish_tasklet;
-	struct tasklet_struct	block_tasklet;
 
 	struct timer_list	ignore_timer;	/* Ignore detection timer */
 };
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
deleted file mode 100644
index 4a73e8b..0000000
--- a/drivers/mmc/mmc.c
+++ /dev/null
@@ -1,1724 +0,0 @@
-/*
- *  linux/drivers/mmc/mmc.c
- *
- *  Copyright (C) 2003-2004 Russell King, All Rights Reserved.
- *  SD support Copyright (C) 2004 Ian Molton, All Rights Reserved.
- *  SD support Copyright (C) 2005 Pierre Ossman, All Rights Reserved.
- *  MMCv4 support Copyright (C) 2006 Philip Langdale, 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/module.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/completion.h>
-#include <linux/device.h>
-#include <linux/delay.h>
-#include <linux/pagemap.h>
-#include <linux/err.h>
-#include <asm/scatterlist.h>
-#include <linux/scatterlist.h>
-
-#include <linux/mmc/card.h>
-#include <linux/mmc/host.h>
-#include <linux/mmc/protocol.h>
-
-#include "mmc.h"
-
-#define CMD_RETRIES	3
-
-/*
- * OCR Bit positions to 10s of Vdd mV.
- */
-static const unsigned short mmc_ocr_bit_to_vdd[] = {
-	150,	155,	160,	165,	170,	180,	190,	200,
-	210,	220,	230,	240,	250,	260,	270,	280,
-	290,	300,	310,	320,	330,	340,	350,	360
-};
-
-static const unsigned int tran_exp[] = {
-	10000,		100000,		1000000,	10000000,
-	0,		0,		0,		0
-};
-
-static const unsigned char tran_mant[] = {
-	0,	10,	12,	13,	15,	20,	25,	30,
-	35,	40,	45,	50,	55,	60,	70,	80,
-};
-
-static const unsigned int tacc_exp[] = {
-	1,	10,	100,	1000,	10000,	100000,	1000000, 10000000,
-};
-
-static const unsigned int tacc_mant[] = {
-	0,	10,	12,	13,	15,	20,	25,	30,
-	35,	40,	45,	50,	55,	60,	70,	80,
-};
-
-
-/**
- *	mmc_request_done - finish processing an MMC request
- *	@host: MMC host which completed request
- *	@mrq: MMC request which request
- *
- *	MMC drivers should call this function when they have completed
- *	their processing of a request.
- */
-void mmc_request_done(struct mmc_host *host, struct mmc_request *mrq)
-{
-	struct mmc_command *cmd = mrq->cmd;
-	int err = cmd->error;
-
-	pr_debug("%s: req done (CMD%u): %d/%d/%d: %08x %08x %08x %08x\n",
-		 mmc_hostname(host), cmd->opcode, err,
-		 mrq->data ? mrq->data->error : 0,
-		 mrq->stop ? mrq->stop->error : 0,
-		 cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]);
-
-	if (err && cmd->retries) {
-		cmd->retries--;
-		cmd->error = 0;
-		host->ops->request(host, mrq);
-	} else if (mrq->done) {
-		mrq->done(mrq);
-	}
-}
-
-EXPORT_SYMBOL(mmc_request_done);
-
-/**
- *	mmc_start_request - start a command on a host
- *	@host: MMC host to start command on
- *	@mrq: MMC request to start
- *
- *	Queue a command on the specified host.  We expect the
- *	caller to be holding the host lock with interrupts disabled.
- */
-void
-mmc_start_request(struct mmc_host *host, struct mmc_request *mrq)
-{
-	pr_debug("%s: starting CMD%u arg %08x flags %08x\n",
-		 mmc_hostname(host), mrq->cmd->opcode,
-		 mrq->cmd->arg, mrq->cmd->flags);
-
-	WARN_ON(!host->claimed);
-
-	mrq->cmd->error = 0;
-	mrq->cmd->mrq = mrq;
-	if (mrq->data) {
-		BUG_ON(mrq->data->blksz > host->max_blk_size);
-		BUG_ON(mrq->data->blocks > host->max_blk_count);
-		BUG_ON(mrq->data->blocks * mrq->data->blksz >
-			host->max_req_size);
-
-		mrq->cmd->data = mrq->data;
-		mrq->data->error = 0;
-		mrq->data->mrq = mrq;
-		if (mrq->stop) {
-			mrq->data->stop = mrq->stop;
-			mrq->stop->error = 0;
-			mrq->stop->mrq = mrq;
-		}
-	}
-	host->ops->request(host, mrq);
-}
-
-EXPORT_SYMBOL(mmc_start_request);
-
-static void mmc_wait_done(struct mmc_request *mrq)
-{
-	complete(mrq->done_data);
-}
-
-int mmc_wait_for_req(struct mmc_host *host, struct mmc_request *mrq)
-{
-	DECLARE_COMPLETION_ONSTACK(complete);
-
-	mrq->done_data = &complete;
-	mrq->done = mmc_wait_done;
-
-	mmc_start_request(host, mrq);
-
-	wait_for_completion(&complete);
-
-	return 0;
-}
-
-EXPORT_SYMBOL(mmc_wait_for_req);
-
-/**
- *	mmc_wait_for_cmd - start a command and wait for completion
- *	@host: MMC host to start command
- *	@cmd: MMC command to start
- *	@retries: maximum number of retries
- *
- *	Start a new MMC command for a host, and wait for the command
- *	to complete.  Return any error that occurred while the command
- *	was executing.  Do not attempt to parse the response.
- */
-int mmc_wait_for_cmd(struct mmc_host *host, struct mmc_command *cmd, int retries)
-{
-	struct mmc_request mrq;
-
-	BUG_ON(!host->claimed);
-
-	memset(&mrq, 0, sizeof(struct mmc_request));
-
-	memset(cmd->resp, 0, sizeof(cmd->resp));
-	cmd->retries = retries;
-
-	mrq.cmd = cmd;
-	cmd->data = NULL;
-
-	mmc_wait_for_req(host, &mrq);
-
-	return cmd->error;
-}
-
-EXPORT_SYMBOL(mmc_wait_for_cmd);
-
-/**
- *	mmc_wait_for_app_cmd - start an application command and wait for
- 			       completion
- *	@host: MMC host to start command
- *	@rca: RCA to send MMC_APP_CMD to
- *	@cmd: MMC command to start
- *	@retries: maximum number of retries
- *
- *	Sends a MMC_APP_CMD, checks the card response, sends the command
- *	in the parameter and waits for it to complete. Return any error
- *	that occurred while the command was executing.  Do not attempt to
- *	parse the response.
- */
-int mmc_wait_for_app_cmd(struct mmc_host *host, unsigned int rca,
-	struct mmc_command *cmd, int retries)
-{
-	struct mmc_request mrq;
-	struct mmc_command appcmd;
-
-	int i, err;
-
-	BUG_ON(!host->claimed);
-	BUG_ON(retries < 0);
-
-	err = MMC_ERR_INVALID;
-
-	/*
-	 * We have to resend MMC_APP_CMD for each attempt so
-	 * we cannot use the retries field in mmc_command.
-	 */
-	for (i = 0;i <= retries;i++) {
-		memset(&mrq, 0, sizeof(struct mmc_request));
-
-		appcmd.opcode = MMC_APP_CMD;
-		appcmd.arg = rca << 16;
-		appcmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
-		appcmd.retries = 0;
-		memset(appcmd.resp, 0, sizeof(appcmd.resp));
-		appcmd.data = NULL;
-
-		mrq.cmd = &appcmd;
-		appcmd.data = NULL;
-
-		mmc_wait_for_req(host, &mrq);
-
-		if (appcmd.error) {
-			err = appcmd.error;
-			continue;
-		}
-
-		/* Check that card supported application commands */
-		if (!(appcmd.resp[0] & R1_APP_CMD))
-			return MMC_ERR_FAILED;
-
-		memset(&mrq, 0, sizeof(struct mmc_request));
-
-		memset(cmd->resp, 0, sizeof(cmd->resp));
-		cmd->retries = 0;
-
-		mrq.cmd = cmd;
-		cmd->data = NULL;
-
-		mmc_wait_for_req(host, &mrq);
-
-		err = cmd->error;
-		if (cmd->error == MMC_ERR_NONE)
-			break;
-	}
-
-	return err;
-}
-
-EXPORT_SYMBOL(mmc_wait_for_app_cmd);
-
-/**
- *	mmc_set_data_timeout - set the timeout for a data command
- *	@data: data phase for command
- *	@card: the MMC card associated with the data transfer
- *	@write: flag to differentiate reads from writes
- */
-void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card,
-			  int write)
-{
-	unsigned int mult;
-
-	/*
-	 * SD cards use a 100 multiplier rather than 10
-	 */
-	mult = mmc_card_sd(card) ? 100 : 10;
-
-	/*
-	 * Scale up the multiplier (and therefore the timeout) by
-	 * the r2w factor for writes.
-	 */
-	if (write)
-		mult <<= card->csd.r2w_factor;
-
-	data->timeout_ns = card->csd.tacc_ns * mult;
-	data->timeout_clks = card->csd.tacc_clks * mult;
-
-	/*
-	 * SD cards also have an upper limit on the timeout.
-	 */
-	if (mmc_card_sd(card)) {
-		unsigned int timeout_us, limit_us;
-
-		timeout_us = data->timeout_ns / 1000;
-		timeout_us += data->timeout_clks * 1000 /
-			(card->host->ios.clock / 1000);
-
-		if (write)
-			limit_us = 250000;
-		else
-			limit_us = 100000;
-
-		/*
-		 * SDHC cards always use these fixed values.
-		 */
-		if (timeout_us > limit_us || mmc_card_blockaddr(card)) {
-			data->timeout_ns = limit_us * 1000;
-			data->timeout_clks = 0;
-		}
-	}
-}
-EXPORT_SYMBOL(mmc_set_data_timeout);
-
-static int mmc_select_card(struct mmc_host *host, struct mmc_card *card);
-
-/**
- *	__mmc_claim_host - exclusively claim a host
- *	@host: mmc host to claim
- *	@card: mmc card to claim host for
- *
- *	Claim a host for a set of operations.  If a valid card
- *	is passed and this wasn't the last card selected, select
- *	the card before returning.
- *
- *	Note: you should use mmc_card_claim_host or mmc_claim_host.
- */
-int __mmc_claim_host(struct mmc_host *host, struct mmc_card *card)
-{
-	DECLARE_WAITQUEUE(wait, current);
-	unsigned long flags;
-	int err = 0;
-
-	add_wait_queue(&host->wq, &wait);
-	spin_lock_irqsave(&host->lock, flags);
-	while (1) {
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		if (!host->claimed)
-			break;
-		spin_unlock_irqrestore(&host->lock, flags);
-		schedule();
-		spin_lock_irqsave(&host->lock, flags);
-	}
-	set_current_state(TASK_RUNNING);
-	host->claimed = 1;
-	spin_unlock_irqrestore(&host->lock, flags);
-	remove_wait_queue(&host->wq, &wait);
-
-	if (card != (void *)-1) {
-		err = mmc_select_card(host, card);
-		if (err != MMC_ERR_NONE)
-			return err;
-	}
-
-	return err;
-}
-
-EXPORT_SYMBOL(__mmc_claim_host);
-
-/**
- *	mmc_release_host - release a host
- *	@host: mmc host to release
- *
- *	Release a MMC host, allowing others to claim the host
- *	for their operations.
- */
-void mmc_release_host(struct mmc_host *host)
-{
-	unsigned long flags;
-
-	BUG_ON(!host->claimed);
-
-	spin_lock_irqsave(&host->lock, flags);
-	host->claimed = 0;
-	spin_unlock_irqrestore(&host->lock, flags);
-
-	wake_up(&host->wq);
-}
-
-EXPORT_SYMBOL(mmc_release_host);
-
-static inline void mmc_set_ios(struct mmc_host *host)
-{
-	struct mmc_ios *ios = &host->ios;
-
-	pr_debug("%s: clock %uHz busmode %u powermode %u cs %u Vdd %u "
-		"width %u timing %u\n",
-		 mmc_hostname(host), ios->clock, ios->bus_mode,
-		 ios->power_mode, ios->chip_select, ios->vdd,
-		 ios->bus_width, ios->timing);
-
-	host->ops->set_ios(host, ios);
-}
-
-static int mmc_select_card(struct mmc_host *host, struct mmc_card *card)
-{
-	int err;
-	struct mmc_command cmd;
-
-	BUG_ON(!host->claimed);
-
-	if (host->card_selected == card)
-		return MMC_ERR_NONE;
-
-	host->card_selected = card;
-
-	cmd.opcode = MMC_SELECT_CARD;
-	cmd.arg = card->rca << 16;
-	cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
-
-	err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
-	if (err != MMC_ERR_NONE)
-		return err;
-
-	/*
-	 * We can only change the bus width of SD cards when
-	 * they are selected so we have to put the handling
-	 * here.
-	 *
-	 * The card is in 1 bit mode by default so
-	 * we only need to change if it supports the
-	 * wider version.
-	 */
-	if (mmc_card_sd(card) &&
-		(card->scr.bus_widths & SD_SCR_BUS_WIDTH_4)) {
-
-		/*
-		* Default bus width is 1 bit.
-		*/
-		host->ios.bus_width = MMC_BUS_WIDTH_1;
-
-		if (host->caps & MMC_CAP_4_BIT_DATA) {
-			struct mmc_command cmd;
-			cmd.opcode = SD_APP_SET_BUS_WIDTH;
-			cmd.arg = SD_BUS_WIDTH_4;
-			cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
-
-			err = mmc_wait_for_app_cmd(host, card->rca, &cmd,
-				CMD_RETRIES);
-			if (err != MMC_ERR_NONE)
-				return err;
-
-			host->ios.bus_width = MMC_BUS_WIDTH_4;
-		}
-	}
-
-	mmc_set_ios(host);
-
-	return MMC_ERR_NONE;
-}
-
-/*
- * Ensure that no card is selected.
- */
-static void mmc_deselect_cards(struct mmc_host *host)
-{
-	struct mmc_command cmd;
-
-	if (host->card_selected) {
-		host->card_selected = NULL;
-
-		cmd.opcode = MMC_SELECT_CARD;
-		cmd.arg = 0;
-		cmd.flags = MMC_RSP_NONE | MMC_CMD_AC;
-
-		mmc_wait_for_cmd(host, &cmd, 0);
-	}
-}
-
-
-static inline void mmc_delay(unsigned int ms)
-{
-	if (ms < 1000 / HZ) {
-		cond_resched();
-		mdelay(ms);
-	} else {
-		msleep(ms);
-	}
-}
-
-/*
- * Mask off any voltages we don't support and select
- * the lowest voltage
- */
-static u32 mmc_select_voltage(struct mmc_host *host, u32 ocr)
-{
-	int bit;
-
-	ocr &= host->ocr_avail;
-
-	bit = ffs(ocr);
-	if (bit) {
-		bit -= 1;
-
-		ocr &= 3 << bit;
-
-		host->ios.vdd = bit;
-		mmc_set_ios(host);
-	} else {
-		ocr = 0;
-	}
-
-	return ocr;
-}
-
-#define UNSTUFF_BITS(resp,start,size)					\
-	({								\
-		const int __size = size;				\
-		const u32 __mask = (__size < 32 ? 1 << __size : 0) - 1;	\
-		const int __off = 3 - ((start) / 32);			\
-		const int __shft = (start) & 31;			\
-		u32 __res;						\
-									\
-		__res = resp[__off] >> __shft;				\
-		if (__size + __shft > 32)				\
-			__res |= resp[__off-1] << ((32 - __shft) % 32);	\
-		__res & __mask;						\
-	})
-
-/*
- * Given the decoded CSD structure, decode the raw CID to our CID structure.
- */
-static void mmc_decode_cid(struct mmc_card *card)
-{
-	u32 *resp = card->raw_cid;
-
-	memset(&card->cid, 0, sizeof(struct mmc_cid));
-
-	if (mmc_card_sd(card)) {
-		/*
-		 * SD doesn't currently have a version field so we will
-		 * have to assume we can parse this.
-		 */
-		card->cid.manfid		= UNSTUFF_BITS(resp, 120, 8);
-		card->cid.oemid			= UNSTUFF_BITS(resp, 104, 16);
-		card->cid.prod_name[0]		= UNSTUFF_BITS(resp, 96, 8);
-		card->cid.prod_name[1]		= UNSTUFF_BITS(resp, 88, 8);
-		card->cid.prod_name[2]		= UNSTUFF_BITS(resp, 80, 8);
-		card->cid.prod_name[3]		= UNSTUFF_BITS(resp, 72, 8);
-		card->cid.prod_name[4]		= UNSTUFF_BITS(resp, 64, 8);
-		card->cid.hwrev			= UNSTUFF_BITS(resp, 60, 4);
-		card->cid.fwrev			= UNSTUFF_BITS(resp, 56, 4);
-		card->cid.serial		= UNSTUFF_BITS(resp, 24, 32);
-		card->cid.year			= UNSTUFF_BITS(resp, 12, 8);
-		card->cid.month			= UNSTUFF_BITS(resp, 8, 4);
-
-		card->cid.year += 2000; /* SD cards year offset */
-	} else {
-		/*
-		 * The selection of the format here is based upon published
-		 * specs from sandisk and from what people have reported.
-		 */
-		switch (card->csd.mmca_vsn) {
-		case 0: /* MMC v1.0 - v1.2 */
-		case 1: /* MMC v1.4 */
-			card->cid.manfid	= UNSTUFF_BITS(resp, 104, 24);
-			card->cid.prod_name[0]	= UNSTUFF_BITS(resp, 96, 8);
-			card->cid.prod_name[1]	= UNSTUFF_BITS(resp, 88, 8);
-			card->cid.prod_name[2]	= UNSTUFF_BITS(resp, 80, 8);
-			card->cid.prod_name[3]	= UNSTUFF_BITS(resp, 72, 8);
-			card->cid.prod_name[4]	= UNSTUFF_BITS(resp, 64, 8);
-			card->cid.prod_name[5]	= UNSTUFF_BITS(resp, 56, 8);
-			card->cid.prod_name[6]	= UNSTUFF_BITS(resp, 48, 8);
-			card->cid.hwrev		= UNSTUFF_BITS(resp, 44, 4);
-			card->cid.fwrev		= UNSTUFF_BITS(resp, 40, 4);
-			card->cid.serial	= UNSTUFF_BITS(resp, 16, 24);
-			card->cid.month		= UNSTUFF_BITS(resp, 12, 4);
-			card->cid.year		= UNSTUFF_BITS(resp, 8, 4) + 1997;
-			break;
-
-		case 2: /* MMC v2.0 - v2.2 */
-		case 3: /* MMC v3.1 - v3.3 */
-		case 4: /* MMC v4 */
-			card->cid.manfid	= UNSTUFF_BITS(resp, 120, 8);
-			card->cid.oemid		= UNSTUFF_BITS(resp, 104, 16);
-			card->cid.prod_name[0]	= UNSTUFF_BITS(resp, 96, 8);
-			card->cid.prod_name[1]	= UNSTUFF_BITS(resp, 88, 8);
-			card->cid.prod_name[2]	= UNSTUFF_BITS(resp, 80, 8);
-			card->cid.prod_name[3]	= UNSTUFF_BITS(resp, 72, 8);
-			card->cid.prod_name[4]	= UNSTUFF_BITS(resp, 64, 8);
-			card->cid.prod_name[5]	= UNSTUFF_BITS(resp, 56, 8);
-			card->cid.serial	= UNSTUFF_BITS(resp, 16, 32);
-			card->cid.month		= UNSTUFF_BITS(resp, 12, 4);
-			card->cid.year		= UNSTUFF_BITS(resp, 8, 4) + 1997;
-			break;
-
-		default:
-			printk("%s: card has unknown MMCA version %d\n",
-				mmc_hostname(card->host), card->csd.mmca_vsn);
-			mmc_card_set_bad(card);
-			break;
-		}
-	}
-}
-
-/*
- * Given a 128-bit response, decode to our card CSD structure.
- */
-static void mmc_decode_csd(struct mmc_card *card)
-{
-	struct mmc_csd *csd = &card->csd;
-	unsigned int e, m, csd_struct;
-	u32 *resp = card->raw_csd;
-
-	if (mmc_card_sd(card)) {
-		csd_struct = UNSTUFF_BITS(resp, 126, 2);
-
-		switch (csd_struct) {
-		case 0:
-			m = UNSTUFF_BITS(resp, 115, 4);
-			e = UNSTUFF_BITS(resp, 112, 3);
-			csd->tacc_ns	 = (tacc_exp[e] * tacc_mant[m] + 9) / 10;
-			csd->tacc_clks	 = UNSTUFF_BITS(resp, 104, 8) * 100;
-
-			m = UNSTUFF_BITS(resp, 99, 4);
-			e = UNSTUFF_BITS(resp, 96, 3);
-			csd->max_dtr	  = tran_exp[e] * tran_mant[m];
-			csd->cmdclass	  = UNSTUFF_BITS(resp, 84, 12);
-
-			e = UNSTUFF_BITS(resp, 47, 3);
-			m = UNSTUFF_BITS(resp, 62, 12);
-			csd->capacity	  = (1 + m) << (e + 2);
-
-			csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4);
-			csd->read_partial = UNSTUFF_BITS(resp, 79, 1);
-			csd->write_misalign = UNSTUFF_BITS(resp, 78, 1);
-			csd->read_misalign = UNSTUFF_BITS(resp, 77, 1);
-			csd->r2w_factor = UNSTUFF_BITS(resp, 26, 3);
-			csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4);
-			csd->write_partial = UNSTUFF_BITS(resp, 21, 1);
-			break;
-		case 1:
-			/*
-			 * This is a block-addressed SDHC card. Most
-			 * interesting fields are unused and have fixed
-			 * values. To avoid getting tripped by buggy cards,
-			 * we assume those fixed values ourselves.
-			 */
-			mmc_card_set_blockaddr(card);
-
-			csd->tacc_ns	 = 0; /* Unused */
-			csd->tacc_clks	 = 0; /* Unused */
-
-			m = UNSTUFF_BITS(resp, 99, 4);
-			e = UNSTUFF_BITS(resp, 96, 3);
-			csd->max_dtr	  = tran_exp[e] * tran_mant[m];
-			csd->cmdclass	  = UNSTUFF_BITS(resp, 84, 12);
-
-			m = UNSTUFF_BITS(resp, 48, 22);
-			csd->capacity     = (1 + m) << 10;
-
-			csd->read_blkbits = 9;
-			csd->read_partial = 0;
-			csd->write_misalign = 0;
-			csd->read_misalign = 0;
-			csd->r2w_factor = 4; /* Unused */
-			csd->write_blkbits = 9;
-			csd->write_partial = 0;
-			break;
-		default:
-			printk("%s: unrecognised CSD structure version %d\n",
-				mmc_hostname(card->host), csd_struct);
-			mmc_card_set_bad(card);
-			return;
-		}
-	} else {
-		/*
-		 * We only understand CSD structure v1.1 and v1.2.
-		 * v1.2 has extra information in bits 15, 11 and 10.
-		 */
-		csd_struct = UNSTUFF_BITS(resp, 126, 2);
-		if (csd_struct != 1 && csd_struct != 2) {
-			printk("%s: unrecognised CSD structure version %d\n",
-				mmc_hostname(card->host), csd_struct);
-			mmc_card_set_bad(card);
-			return;
-		}
-
-		csd->mmca_vsn	 = UNSTUFF_BITS(resp, 122, 4);
-		m = UNSTUFF_BITS(resp, 115, 4);
-		e = UNSTUFF_BITS(resp, 112, 3);
-		csd->tacc_ns	 = (tacc_exp[e] * tacc_mant[m] + 9) / 10;
-		csd->tacc_clks	 = UNSTUFF_BITS(resp, 104, 8) * 100;
-
-		m = UNSTUFF_BITS(resp, 99, 4);
-		e = UNSTUFF_BITS(resp, 96, 3);
-		csd->max_dtr	  = tran_exp[e] * tran_mant[m];
-		csd->cmdclass	  = UNSTUFF_BITS(resp, 84, 12);
-
-		e = UNSTUFF_BITS(resp, 47, 3);
-		m = UNSTUFF_BITS(resp, 62, 12);
-		csd->capacity	  = (1 + m) << (e + 2);
-
-		csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4);
-		csd->read_partial = UNSTUFF_BITS(resp, 79, 1);
-		csd->write_misalign = UNSTUFF_BITS(resp, 78, 1);
-		csd->read_misalign = UNSTUFF_BITS(resp, 77, 1);
-		csd->r2w_factor = UNSTUFF_BITS(resp, 26, 3);
-		csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4);
-		csd->write_partial = UNSTUFF_BITS(resp, 21, 1);
-	}
-}
-
-/*
- * Given a 64-bit response, decode to our card SCR structure.
- */
-static void mmc_decode_scr(struct mmc_card *card)
-{
-	struct sd_scr *scr = &card->scr;
-	unsigned int scr_struct;
-	u32 resp[4];
-
-	BUG_ON(!mmc_card_sd(card));
-
-	resp[3] = card->raw_scr[1];
-	resp[2] = card->raw_scr[0];
-
-	scr_struct = UNSTUFF_BITS(resp, 60, 4);
-	if (scr_struct != 0) {
-		printk("%s: unrecognised SCR structure version %d\n",
-			mmc_hostname(card->host), scr_struct);
-		mmc_card_set_bad(card);
-		return;
-	}
-
-	scr->sda_vsn = UNSTUFF_BITS(resp, 56, 4);
-	scr->bus_widths = UNSTUFF_BITS(resp, 48, 4);
-}
-
-/*
- * Locate a MMC card on this MMC host given a raw CID.
- */
-static struct mmc_card *mmc_find_card(struct mmc_host *host, u32 *raw_cid)
-{
-	struct mmc_card *card;
-
-	list_for_each_entry(card, &host->cards, node) {
-		if (memcmp(card->raw_cid, raw_cid, sizeof(card->raw_cid)) == 0)
-			return card;
-	}
-	return NULL;
-}
-
-/*
- * Allocate a new MMC card, and assign a unique RCA.
- */
-static struct mmc_card *
-mmc_alloc_card(struct mmc_host *host, u32 *raw_cid, unsigned int *frca)
-{
-	struct mmc_card *card, *c;
-	unsigned int rca = *frca;
-
-	card = kmalloc(sizeof(struct mmc_card), GFP_KERNEL);
-	if (!card)
-		return ERR_PTR(-ENOMEM);
-
-	mmc_init_card(card, host);
-	memcpy(card->raw_cid, raw_cid, sizeof(card->raw_cid));
-
- again:
-	list_for_each_entry(c, &host->cards, node)
-		if (c->rca == rca) {
-			rca++;
-			goto again;
-		}
-
-	card->rca = rca;
-
-	*frca = rca;
-
-	return card;
-}
-
-/*
- * Tell attached cards to go to IDLE state
- */
-static void mmc_idle_cards(struct mmc_host *host)
-{
-	struct mmc_command cmd;
-
-	host->ios.chip_select = MMC_CS_HIGH;
-	mmc_set_ios(host);
-
-	mmc_delay(1);
-
-	cmd.opcode = MMC_GO_IDLE_STATE;
-	cmd.arg = 0;
-	cmd.flags = MMC_RSP_NONE | MMC_CMD_BC;
-
-	mmc_wait_for_cmd(host, &cmd, 0);
-
-	mmc_delay(1);
-
-	host->ios.chip_select = MMC_CS_DONTCARE;
-	mmc_set_ios(host);
-
-	mmc_delay(1);
-}
-
-/*
- * Apply power to the MMC stack.  This is a two-stage process.
- * First, we enable power to the card without the clock running.
- * We then wait a bit for the power to stabilise.  Finally,
- * enable the bus drivers and clock to the card.
- *
- * We must _NOT_ enable the clock prior to power stablising.
- *
- * If a host does all the power sequencing itself, ignore the
- * initial MMC_POWER_UP stage.
- */
-static void mmc_power_up(struct mmc_host *host)
-{
-	int bit = fls(host->ocr_avail) - 1;
-
-	host->ios.vdd = bit;
-	host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN;
-	host->ios.chip_select = MMC_CS_DONTCARE;
-	host->ios.power_mode = MMC_POWER_UP;
-	host->ios.bus_width = MMC_BUS_WIDTH_1;
-	host->ios.timing = MMC_TIMING_LEGACY;
-	mmc_set_ios(host);
-
-	mmc_delay(1);
-
-	host->ios.clock = host->f_min;
-	host->ios.power_mode = MMC_POWER_ON;
-	mmc_set_ios(host);
-
-	mmc_delay(2);
-}
-
-static void mmc_power_off(struct mmc_host *host)
-{
-	host->ios.clock = 0;
-	host->ios.vdd = 0;
-	host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN;
-	host->ios.chip_select = MMC_CS_DONTCARE;
-	host->ios.power_mode = MMC_POWER_OFF;
-	host->ios.bus_width = MMC_BUS_WIDTH_1;
-	host->ios.timing = MMC_TIMING_LEGACY;
-	mmc_set_ios(host);
-}
-
-static int mmc_send_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr)
-{
-	struct mmc_command cmd;
-	int i, err = 0;
-
-	cmd.opcode = MMC_SEND_OP_COND;
-	cmd.arg = ocr;
-	cmd.flags = MMC_RSP_R3 | MMC_CMD_BCR;
-
-	for (i = 100; i; i--) {
-		err = mmc_wait_for_cmd(host, &cmd, 0);
-		if (err != MMC_ERR_NONE)
-			break;
-
-		if (cmd.resp[0] & MMC_CARD_BUSY || ocr == 0)
-			break;
-
-		err = MMC_ERR_TIMEOUT;
-
-		mmc_delay(10);
-	}
-
-	if (rocr)
-		*rocr = cmd.resp[0];
-
-	return err;
-}
-
-static int mmc_send_app_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr)
-{
-	struct mmc_command cmd;
-	int i, err = 0;
-
-	cmd.opcode = SD_APP_OP_COND;
-	cmd.arg = ocr;
-	cmd.flags = MMC_RSP_R3 | MMC_CMD_BCR;
-
-	for (i = 100; i; i--) {
-		err = mmc_wait_for_app_cmd(host, 0, &cmd, CMD_RETRIES);
-		if (err != MMC_ERR_NONE)
-			break;
-
-		if (cmd.resp[0] & MMC_CARD_BUSY || ocr == 0)
-			break;
-
-		err = MMC_ERR_TIMEOUT;
-
-		mmc_delay(10);
-	}
-
-	if (rocr)
-		*rocr = cmd.resp[0];
-
-	return err;
-}
-
-static int mmc_send_if_cond(struct mmc_host *host, u32 ocr, int *rsd2)
-{
-	struct mmc_command cmd;
-	int err, sd2;
-	static const u8 test_pattern = 0xAA;
-
-	/*
-	* To support SD 2.0 cards, we must always invoke SD_SEND_IF_COND
-	* before SD_APP_OP_COND. This command will harmlessly fail for
-	* SD 1.0 cards.
-	*/
-	cmd.opcode = SD_SEND_IF_COND;
-	cmd.arg = ((ocr & 0xFF8000) != 0) << 8 | test_pattern;
-	cmd.flags = MMC_RSP_R7 | MMC_CMD_BCR;
-
-	err = mmc_wait_for_cmd(host, &cmd, 0);
-	if (err == MMC_ERR_NONE) {
-		if ((cmd.resp[0] & 0xFF) == test_pattern) {
-			sd2 = 1;
-		} else {
-			sd2 = 0;
-			err = MMC_ERR_FAILED;
-		}
-	} else {
-		/*
-		 * Treat errors as SD 1.0 card.
-		 */
-		sd2 = 0;
-		err = MMC_ERR_NONE;
-	}
-	if (rsd2)
-		*rsd2 = sd2;
-	return err;
-}
-
-/*
- * Discover cards by requesting their CID.  If this command
- * times out, it is not an error; there are no further cards
- * to be discovered.  Add new cards to the list.
- *
- * Create a mmc_card entry for each discovered card, assigning
- * it an RCA, and save the raw CID for decoding later.
- */
-static void mmc_discover_cards(struct mmc_host *host)
-{
-	struct mmc_card *card;
-	unsigned int first_rca = 1, err;
-
-	while (1) {
-		struct mmc_command cmd;
-
-		cmd.opcode = MMC_ALL_SEND_CID;
-		cmd.arg = 0;
-		cmd.flags = MMC_RSP_R2 | MMC_CMD_BCR;
-
-		err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
-		if (err == MMC_ERR_TIMEOUT) {
-			err = MMC_ERR_NONE;
-			break;
-		}
-		if (err != MMC_ERR_NONE) {
-			printk(KERN_ERR "%s: error requesting CID: %d\n",
-				mmc_hostname(host), err);
-			break;
-		}
-
-		card = mmc_find_card(host, cmd.resp);
-		if (!card) {
-			card = mmc_alloc_card(host, cmd.resp, &first_rca);
-			if (IS_ERR(card)) {
-				err = PTR_ERR(card);
-				break;
-			}
-			list_add(&card->node, &host->cards);
-		}
-
-		card->state &= ~MMC_STATE_DEAD;
-
-		if (host->mode == MMC_MODE_SD) {
-			mmc_card_set_sd(card);
-
-			cmd.opcode = SD_SEND_RELATIVE_ADDR;
-			cmd.arg = 0;
-			cmd.flags = MMC_RSP_R6 | MMC_CMD_BCR;
-
-			err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
-			if (err != MMC_ERR_NONE)
-				mmc_card_set_dead(card);
-			else {
-				card->rca = cmd.resp[0] >> 16;
-
-				if (!host->ops->get_ro) {
-					printk(KERN_WARNING "%s: host does not "
-						"support reading read-only "
-						"switch. assuming write-enable.\n",
-						mmc_hostname(host));
-				} else {
-					if (host->ops->get_ro(host))
-						mmc_card_set_readonly(card);
-				}
-			}
-		} else {
-			cmd.opcode = MMC_SET_RELATIVE_ADDR;
-			cmd.arg = card->rca << 16;
-			cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
-
-			err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
-			if (err != MMC_ERR_NONE)
-				mmc_card_set_dead(card);
-		}
-	}
-}
-
-static void mmc_read_csds(struct mmc_host *host)
-{
-	struct mmc_card *card;
-
-	list_for_each_entry(card, &host->cards, node) {
-		struct mmc_command cmd;
-		int err;
-
-		if (card->state & (MMC_STATE_DEAD|MMC_STATE_PRESENT))
-			continue;
-
-		cmd.opcode = MMC_SEND_CSD;
-		cmd.arg = card->rca << 16;
-		cmd.flags = MMC_RSP_R2 | MMC_CMD_AC;
-
-		err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
-		if (err != MMC_ERR_NONE) {
-			mmc_card_set_dead(card);
-			continue;
-		}
-
-		memcpy(card->raw_csd, cmd.resp, sizeof(card->raw_csd));
-
-		mmc_decode_csd(card);
-		mmc_decode_cid(card);
-	}
-}
-
-static void mmc_process_ext_csds(struct mmc_host *host)
-{
-	int err;
-	struct mmc_card *card;
-
-	struct mmc_request mrq;
-	struct mmc_command cmd;
-	struct mmc_data data;
-
-	struct scatterlist sg;
-
-	/*
-	 * As the ext_csd is so large and mostly unused, we don't store the
-	 * raw block in mmc_card.
-	 */
-	u8 *ext_csd;
-	ext_csd = kmalloc(512, GFP_KERNEL);
-	if (!ext_csd) {
-		printk("%s: could not allocate a buffer to receive the ext_csd."
-		       "mmc v4 cards will be treated as v3.\n",
-			mmc_hostname(host));
-		return;
-	}
-
-	list_for_each_entry(card, &host->cards, node) {
-		if (card->state & (MMC_STATE_DEAD|MMC_STATE_PRESENT))
-			continue;
-		if (mmc_card_sd(card))
-			continue;
-		if (card->csd.mmca_vsn < CSD_SPEC_VER_4)
-			continue;
-
-		err = mmc_select_card(host, card);
-		if (err != MMC_ERR_NONE) {
-			mmc_card_set_dead(card);
-			continue;
-		}
-
-		memset(&cmd, 0, sizeof(struct mmc_command));
-
-		cmd.opcode = MMC_SEND_EXT_CSD;
-		cmd.arg = 0;
-		cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
-
-		memset(&data, 0, sizeof(struct mmc_data));
-
-		mmc_set_data_timeout(&data, card, 0);
-
-		data.blksz = 512;
-		data.blocks = 1;
-		data.flags = MMC_DATA_READ;
-		data.sg = &sg;
-		data.sg_len = 1;
-
-		memset(&mrq, 0, sizeof(struct mmc_request));
-
-		mrq.cmd = &cmd;
-		mrq.data = &data;
-
-		sg_init_one(&sg, ext_csd, 512);
-
-		mmc_wait_for_req(host, &mrq);
-
-		if (cmd.error != MMC_ERR_NONE || data.error != MMC_ERR_NONE) {
-			printk("%s: unable to read EXT_CSD, performance "
-				"might suffer.\n", mmc_hostname(card->host));
-			continue;
-		}
-
-		switch (ext_csd[EXT_CSD_CARD_TYPE]) {
-		case EXT_CSD_CARD_TYPE_52 | EXT_CSD_CARD_TYPE_26:
-			card->ext_csd.hs_max_dtr = 52000000;
-			break;
-		case EXT_CSD_CARD_TYPE_26:
-			card->ext_csd.hs_max_dtr = 26000000;
-			break;
-		default:
-			/* MMC v4 spec says this cannot happen */
-			printk("%s: card is mmc v4 but doesn't support "
-			       "any high-speed modes.\n",
-				mmc_hostname(card->host));
-			continue;
-		}
-
-		if (host->caps & MMC_CAP_MMC_HIGHSPEED) {
-			/* Activate highspeed support. */
-			cmd.opcode = MMC_SWITCH;
-			cmd.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
-				  (EXT_CSD_HS_TIMING << 16) |
-				  (1 << 8) |
-				  EXT_CSD_CMD_SET_NORMAL;
-			cmd.flags = MMC_RSP_R1B | MMC_CMD_AC;
-
-			err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
-			if (err != MMC_ERR_NONE) {
-				printk("%s: failed to switch card to mmc v4 "
-				       "high-speed mode.\n",
-				       mmc_hostname(card->host));
-				continue;
-			}
-
-			mmc_card_set_highspeed(card);
-
-			host->ios.timing = MMC_TIMING_SD_HS;
-			mmc_set_ios(host);
-		}
-
-		/* Check for host support for wide-bus modes. */
-		if (host->caps & MMC_CAP_4_BIT_DATA) {
-			/* Activate 4-bit support. */
-			cmd.opcode = MMC_SWITCH;
-			cmd.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
-				  (EXT_CSD_BUS_WIDTH << 16) |
-				  (EXT_CSD_BUS_WIDTH_4 << 8) |
-				  EXT_CSD_CMD_SET_NORMAL;
-			cmd.flags = MMC_RSP_R1B | MMC_CMD_AC;
-
-			err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
-			if (err != MMC_ERR_NONE) {
-				printk("%s: failed to switch card to "
-				       "mmc v4 4-bit bus mode.\n",
-				       mmc_hostname(card->host));
-				continue;
-			}
-
-			host->ios.bus_width = MMC_BUS_WIDTH_4;
-			mmc_set_ios(host);
-		}
-	}
-
-	kfree(ext_csd);
-
-	mmc_deselect_cards(host);
-}
-
-static void mmc_read_scrs(struct mmc_host *host)
-{
-	int err;
-	struct mmc_card *card;
-	struct mmc_request mrq;
-	struct mmc_command cmd;
-	struct mmc_data data;
-	struct scatterlist sg;
-
-	list_for_each_entry(card, &host->cards, node) {
-		if (card->state & (MMC_STATE_DEAD|MMC_STATE_PRESENT))
-			continue;
-		if (!mmc_card_sd(card))
-			continue;
-
-		err = mmc_select_card(host, card);
-		if (err != MMC_ERR_NONE) {
-			mmc_card_set_dead(card);
-			continue;
-		}
-
-		memset(&cmd, 0, sizeof(struct mmc_command));
-
-		cmd.opcode = MMC_APP_CMD;
-		cmd.arg = card->rca << 16;
-		cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
-
-		err = mmc_wait_for_cmd(host, &cmd, 0);
-		if ((err != MMC_ERR_NONE) || !(cmd.resp[0] & R1_APP_CMD)) {
-			mmc_card_set_dead(card);
-			continue;
-		}
-
-		memset(&cmd, 0, sizeof(struct mmc_command));
-
-		cmd.opcode = SD_APP_SEND_SCR;
-		cmd.arg = 0;
-		cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
-
-		memset(&data, 0, sizeof(struct mmc_data));
-
-		mmc_set_data_timeout(&data, card, 0);
-
-		data.blksz = 1 << 3;
-		data.blocks = 1;
-		data.flags = MMC_DATA_READ;
-		data.sg = &sg;
-		data.sg_len = 1;
-
-		memset(&mrq, 0, sizeof(struct mmc_request));
-
-		mrq.cmd = &cmd;
-		mrq.data = &data;
-
-		sg_init_one(&sg, (u8*)card->raw_scr, 8);
-
-		mmc_wait_for_req(host, &mrq);
-
-		if (cmd.error != MMC_ERR_NONE || data.error != MMC_ERR_NONE) {
-			mmc_card_set_dead(card);
-			continue;
-		}
-
-		card->raw_scr[0] = ntohl(card->raw_scr[0]);
-		card->raw_scr[1] = ntohl(card->raw_scr[1]);
-
-		mmc_decode_scr(card);
-	}
-
-	mmc_deselect_cards(host);
-}
-
-static void mmc_read_switch_caps(struct mmc_host *host)
-{
-	int err;
-	struct mmc_card *card;
-	struct mmc_request mrq;
-	struct mmc_command cmd;
-	struct mmc_data data;
-	unsigned char *status;
-	struct scatterlist sg;
-
-	if (!(host->caps & MMC_CAP_SD_HIGHSPEED))
-		return;
-
-	status = kmalloc(64, GFP_KERNEL);
-	if (!status) {
-		printk(KERN_WARNING "%s: Unable to allocate buffer for "
-			"reading switch capabilities.\n",
-			mmc_hostname(host));
-		return;
-	}
-
-	list_for_each_entry(card, &host->cards, node) {
-		if (card->state & (MMC_STATE_DEAD|MMC_STATE_PRESENT))
-			continue;
-		if (!mmc_card_sd(card))
-			continue;
-		if (card->scr.sda_vsn < SCR_SPEC_VER_1)
-			continue;
-
-		err = mmc_select_card(host, card);
-		if (err != MMC_ERR_NONE) {
-			mmc_card_set_dead(card);
-			continue;
-		}
-
-		memset(&cmd, 0, sizeof(struct mmc_command));
-
-		cmd.opcode = SD_SWITCH;
-		cmd.arg = 0x00FFFFF1;
-		cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
-
-		memset(&data, 0, sizeof(struct mmc_data));
-
-		mmc_set_data_timeout(&data, card, 0);
-
-		data.blksz = 64;
-		data.blocks = 1;
-		data.flags = MMC_DATA_READ;
-		data.sg = &sg;
-		data.sg_len = 1;
-
-		memset(&mrq, 0, sizeof(struct mmc_request));
-
-		mrq.cmd = &cmd;
-		mrq.data = &data;
-
-		sg_init_one(&sg, status, 64);
-
-		mmc_wait_for_req(host, &mrq);
-
-		if (cmd.error != MMC_ERR_NONE || data.error != MMC_ERR_NONE) {
-			printk("%s: unable to read switch capabilities, "
-				"performance might suffer.\n",
-				mmc_hostname(card->host));
-			continue;
-		}
-
-		if (status[13] & 0x02)
-			card->sw_caps.hs_max_dtr = 50000000;
-
-		memset(&cmd, 0, sizeof(struct mmc_command));
-
-		cmd.opcode = SD_SWITCH;
-		cmd.arg = 0x80FFFFF1;
-		cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
-
-		memset(&data, 0, sizeof(struct mmc_data));
-
-		mmc_set_data_timeout(&data, card, 0);
-
-		data.blksz = 64;
-		data.blocks = 1;
-		data.flags = MMC_DATA_READ;
-		data.sg = &sg;
-		data.sg_len = 1;
-
-		memset(&mrq, 0, sizeof(struct mmc_request));
-
-		mrq.cmd = &cmd;
-		mrq.data = &data;
-
-		sg_init_one(&sg, status, 64);
-
-		mmc_wait_for_req(host, &mrq);
-
-		if (cmd.error != MMC_ERR_NONE || data.error != MMC_ERR_NONE ||
-			(status[16] & 0xF) != 1) {
-			printk(KERN_WARNING "%s: Problem switching card "
-				"into high-speed mode!\n",
-				mmc_hostname(host));
-			continue;
-		}
-
-		mmc_card_set_highspeed(card);
-
-		host->ios.timing = MMC_TIMING_SD_HS;
-		mmc_set_ios(host);
-	}
-
-	kfree(status);
-
-	mmc_deselect_cards(host);
-}
-
-static unsigned int mmc_calculate_clock(struct mmc_host *host)
-{
-	struct mmc_card *card;
-	unsigned int max_dtr = host->f_max;
-
-	list_for_each_entry(card, &host->cards, node)
-		if (!mmc_card_dead(card)) {
-			if (mmc_card_highspeed(card) && mmc_card_sd(card)) {
-				if (max_dtr > card->sw_caps.hs_max_dtr)
-					max_dtr = card->sw_caps.hs_max_dtr;
-			} else if (mmc_card_highspeed(card) && !mmc_card_sd(card)) {
-				if (max_dtr > card->ext_csd.hs_max_dtr)
-					max_dtr = card->ext_csd.hs_max_dtr;
-			} else if (max_dtr > card->csd.max_dtr) {
-				max_dtr = card->csd.max_dtr;
-			}
-		}
-
-	pr_debug("%s: selected %d.%03dMHz transfer rate\n",
-		 mmc_hostname(host),
-		 max_dtr / 1000000, (max_dtr / 1000) % 1000);
-
-	return max_dtr;
-}
-
-/*
- * Check whether cards we already know about are still present.
- * We do this by requesting status, and checking whether a card
- * responds.
- *
- * A request for status does not cause a state change in data
- * transfer mode.
- */
-static void mmc_check_cards(struct mmc_host *host)
-{
-	struct list_head *l, *n;
-
-	mmc_deselect_cards(host);
-
-	list_for_each_safe(l, n, &host->cards) {
-		struct mmc_card *card = mmc_list_to_card(l);
-		struct mmc_command cmd;
-		int err;
-
-		cmd.opcode = MMC_SEND_STATUS;
-		cmd.arg = card->rca << 16;
-		cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
-
-		err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
-		if (err == MMC_ERR_NONE)
-			continue;
-
-		mmc_card_set_dead(card);
-	}
-}
-
-static void mmc_setup(struct mmc_host *host)
-{
-	if (host->ios.power_mode != MMC_POWER_ON) {
-		int err;
-		u32 ocr;
-
-		host->mode = MMC_MODE_SD;
-
-		mmc_power_up(host);
-		mmc_idle_cards(host);
-
-		err = mmc_send_if_cond(host, host->ocr_avail, NULL);
-		if (err != MMC_ERR_NONE) {
-			return;
-		}
-		err = mmc_send_app_op_cond(host, 0, &ocr);
-
-		/*
-		 * If we fail to detect any SD cards then try
-		 * searching for MMC cards.
-		 */
-		if (err != MMC_ERR_NONE) {
-			host->mode = MMC_MODE_MMC;
-
-			err = mmc_send_op_cond(host, 0, &ocr);
-			if (err != MMC_ERR_NONE)
-				return;
-		}
-
-		host->ocr = mmc_select_voltage(host, ocr);
-
-		/*
-		 * Since we're changing the OCR value, we seem to
-		 * need to tell some cards to go back to the idle
-		 * state.  We wait 1ms to give cards time to
-		 * respond.
-		 */
-		if (host->ocr)
-			mmc_idle_cards(host);
-	} else {
-		host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN;
-		host->ios.clock = host->f_min;
-		mmc_set_ios(host);
-
-		/*
-		 * We should remember the OCR mask from the existing
-		 * cards, and detect the new cards OCR mask, combine
-		 * the two and re-select the VDD.  However, if we do
-		 * change VDD, we should do an idle, and then do a
-		 * full re-initialisation.  We would need to notify
-		 * drivers so that they can re-setup the cards as
-		 * well, while keeping their queues at bay.
-		 *
-		 * For the moment, we take the easy way out - if the
-		 * new cards don't like our currently selected VDD,
-		 * they drop off the bus.
-		 */
-	}
-
-	if (host->ocr == 0)
-		return;
-
-	/*
-	 * Send the selected OCR multiple times... until the cards
-	 * all get the idea that they should be ready for CMD2.
-	 * (My SanDisk card seems to need this.)
-	 */
-	if (host->mode == MMC_MODE_SD) {
-		int err, sd2;
-		err = mmc_send_if_cond(host, host->ocr, &sd2);
-		if (err == MMC_ERR_NONE) {
-			/*
-			* If SD_SEND_IF_COND indicates an SD 2.0
-			* compliant card and we should set bit 30
-			* of the ocr to indicate that we can handle
-			* block-addressed SDHC cards.
-			*/
-			mmc_send_app_op_cond(host, host->ocr | (sd2 << 30), NULL);
-		}
-	} else {
-		mmc_send_op_cond(host, host->ocr, NULL);
-	}
-
-	mmc_discover_cards(host);
-
-	/*
-	 * Ok, now switch to push-pull mode.
-	 */
-	host->ios.bus_mode = MMC_BUSMODE_PUSHPULL;
-	mmc_set_ios(host);
-
-	mmc_read_csds(host);
-
-	if (host->mode == MMC_MODE_SD) {
-		mmc_read_scrs(host);
-		mmc_read_switch_caps(host);
-	} else
-		mmc_process_ext_csds(host);
-}
-
-
-/**
- *	mmc_detect_change - process change of state on a MMC socket
- *	@host: host which changed state.
- *	@delay: optional delay to wait before detection (jiffies)
- *
- *	All we know is that card(s) have been inserted or removed
- *	from the socket(s).  We don't know which socket or cards.
- */
-void mmc_detect_change(struct mmc_host *host, unsigned long delay)
-{
-	mmc_schedule_delayed_work(&host->detect, delay);
-}
-
-EXPORT_SYMBOL(mmc_detect_change);
-
-
-static void mmc_rescan(struct work_struct *work)
-{
-	struct mmc_host *host =
-		container_of(work, struct mmc_host, detect.work);
-	struct list_head *l, *n;
-	unsigned char power_mode;
-
-	mmc_claim_host(host);
-
-	/*
-	 * Check for removed cards and newly inserted ones. We check for
-	 * removed cards first so we can intelligently re-select the VDD.
-	 */
-	power_mode = host->ios.power_mode;
-	if (power_mode == MMC_POWER_ON)
-		mmc_check_cards(host);
-
-	mmc_setup(host);
-
-	/*
-	 * Some broken cards process CMD1 even in stand-by state. There is
-	 * no reply, but an ILLEGAL_COMMAND error is cached and returned
-	 * after next command. We poll for card status here to clear any
-	 * possibly pending error.
-	 */
-	if (power_mode == MMC_POWER_ON)
-		mmc_check_cards(host);
-
-	if (!list_empty(&host->cards)) {
-		/*
-		 * (Re-)calculate the fastest clock rate which the
-		 * attached cards and the host support.
-		 */
-		host->ios.clock = mmc_calculate_clock(host);
-		mmc_set_ios(host);
-	}
-
-	mmc_release_host(host);
-
-	list_for_each_safe(l, n, &host->cards) {
-		struct mmc_card *card = mmc_list_to_card(l);
-
-		/*
-		 * If this is a new and good card, register it.
-		 */
-		if (!mmc_card_present(card) && !mmc_card_dead(card)) {
-			if (mmc_register_card(card))
-				mmc_card_set_dead(card);
-			else
-				mmc_card_set_present(card);
-		}
-
-		/*
-		 * If this card is dead, destroy it.
-		 */
-		if (mmc_card_dead(card)) {
-			list_del(&card->node);
-			mmc_remove_card(card);
-		}
-	}
-
-	/*
-	 * If we discover that there are no cards on the
-	 * bus, turn off the clock and power down.
-	 */
-	if (list_empty(&host->cards))
-		mmc_power_off(host);
-}
-
-
-/**
- *	mmc_alloc_host - initialise the per-host structure.
- *	@extra: sizeof private data structure
- *	@dev: pointer to host device model structure
- *
- *	Initialise the per-host structure.
- */
-struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
-{
-	struct mmc_host *host;
-
-	host = mmc_alloc_host_sysfs(extra, dev);
-	if (host) {
-		spin_lock_init(&host->lock);
-		init_waitqueue_head(&host->wq);
-		INIT_LIST_HEAD(&host->cards);
-		INIT_DELAYED_WORK(&host->detect, mmc_rescan);
-
-		/*
-		 * By default, hosts do not support SGIO or large requests.
-		 * They have to set these according to their abilities.
-		 */
-		host->max_hw_segs = 1;
-		host->max_phys_segs = 1;
-		host->max_seg_size = PAGE_CACHE_SIZE;
-
-		host->max_req_size = PAGE_CACHE_SIZE;
-		host->max_blk_size = 512;
-		host->max_blk_count = PAGE_CACHE_SIZE / 512;
-	}
-
-	return host;
-}
-
-EXPORT_SYMBOL(mmc_alloc_host);
-
-/**
- *	mmc_add_host - initialise host hardware
- *	@host: mmc host
- */
-int mmc_add_host(struct mmc_host *host)
-{
-	int ret;
-
-	ret = mmc_add_host_sysfs(host);
-	if (ret == 0) {
-		mmc_power_off(host);
-		mmc_detect_change(host, 0);
-	}
-
-	return ret;
-}
-
-EXPORT_SYMBOL(mmc_add_host);
-
-/**
- *	mmc_remove_host - remove host hardware
- *	@host: mmc host
- *
- *	Unregister and remove all cards associated with this host,
- *	and power down the MMC bus.
- */
-void mmc_remove_host(struct mmc_host *host)
-{
-	struct list_head *l, *n;
-
-	list_for_each_safe(l, n, &host->cards) {
-		struct mmc_card *card = mmc_list_to_card(l);
-
-		mmc_remove_card(card);
-	}
-
-	mmc_power_off(host);
-	mmc_remove_host_sysfs(host);
-}
-
-EXPORT_SYMBOL(mmc_remove_host);
-
-/**
- *	mmc_free_host - free the host structure
- *	@host: mmc host
- *
- *	Free the host once all references to it have been dropped.
- */
-void mmc_free_host(struct mmc_host *host)
-{
-	mmc_flush_scheduled_work();
-	mmc_free_host_sysfs(host);
-}
-
-EXPORT_SYMBOL(mmc_free_host);
-
-#ifdef CONFIG_PM
-
-/**
- *	mmc_suspend_host - suspend a host
- *	@host: mmc host
- *	@state: suspend mode (PM_SUSPEND_xxx)
- */
-int mmc_suspend_host(struct mmc_host *host, pm_message_t state)
-{
-	mmc_claim_host(host);
-	mmc_deselect_cards(host);
-	mmc_power_off(host);
-	mmc_release_host(host);
-
-	return 0;
-}
-
-EXPORT_SYMBOL(mmc_suspend_host);
-
-/**
- *	mmc_resume_host - resume a previously suspended host
- *	@host: mmc host
- */
-int mmc_resume_host(struct mmc_host *host)
-{
-	mmc_rescan(&host->detect.work);
-
-	return 0;
-}
-
-EXPORT_SYMBOL(mmc_resume_host);
-
-#endif
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/mmc/tifm_sd.c b/drivers/mmc/tifm_sd.c
deleted file mode 100644
index 0581d09..0000000
--- a/drivers/mmc/tifm_sd.c
+++ /dev/null
@@ -1,987 +0,0 @@
-/*
- *  tifm_sd.c - TI FlashMedia driver
- *
- *  Copyright (C) 2006 Alex Dubov <oakad@yahoo.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- */
-
-
-#include <linux/tifm.h>
-#include <linux/mmc/protocol.h>
-#include <linux/mmc/host.h>
-#include <linux/highmem.h>
-#include <asm/io.h>
-
-#define DRIVER_NAME "tifm_sd"
-#define DRIVER_VERSION "0.7"
-
-static int no_dma = 0;
-static int fixed_timeout = 0;
-module_param(no_dma, bool, 0644);
-module_param(fixed_timeout, bool, 0644);
-
-/* Constants here are mostly from OMAP5912 datasheet */
-#define TIFM_MMCSD_RESET      0x0002
-#define TIFM_MMCSD_CLKMASK    0x03ff
-#define TIFM_MMCSD_POWER      0x0800
-#define TIFM_MMCSD_4BBUS      0x8000
-#define TIFM_MMCSD_RXDE       0x8000   /* rx dma enable */
-#define TIFM_MMCSD_TXDE       0x0080   /* tx dma enable */
-#define TIFM_MMCSD_BUFINT     0x0c00   /* set bits: AE, AF */
-#define TIFM_MMCSD_DPE        0x0020   /* data timeout counted in kilocycles */
-#define TIFM_MMCSD_INAB       0x0080   /* abort / initialize command */
-#define TIFM_MMCSD_READ       0x8000
-
-#define TIFM_MMCSD_DATAMASK   0x401d   /* set bits: CERR, EOFB, BRS, CB, EOC */
-#define TIFM_MMCSD_ERRMASK    0x01e0   /* set bits: CCRC, CTO, DCRC, DTO */
-#define TIFM_MMCSD_EOC        0x0001   /* end of command phase  */
-#define TIFM_MMCSD_CB         0x0004   /* card enter busy state */
-#define TIFM_MMCSD_BRS        0x0008   /* block received/sent   */
-#define TIFM_MMCSD_EOFB       0x0010   /* card exit busy state  */
-#define TIFM_MMCSD_DTO        0x0020   /* data time-out         */
-#define TIFM_MMCSD_DCRC       0x0040   /* data crc error        */
-#define TIFM_MMCSD_CTO        0x0080   /* command time-out      */
-#define TIFM_MMCSD_CCRC       0x0100   /* command crc error     */
-#define TIFM_MMCSD_AF         0x0400   /* fifo almost full      */
-#define TIFM_MMCSD_AE         0x0800   /* fifo almost empty     */
-#define TIFM_MMCSD_CERR       0x4000   /* card status error     */
-
-#define TIFM_MMCSD_FIFO_SIZE  0x0020
-
-#define TIFM_MMCSD_RSP_R0     0x0000
-#define TIFM_MMCSD_RSP_R1     0x0100
-#define TIFM_MMCSD_RSP_R2     0x0200
-#define TIFM_MMCSD_RSP_R3     0x0300
-#define TIFM_MMCSD_RSP_R4     0x0400
-#define TIFM_MMCSD_RSP_R5     0x0500
-#define TIFM_MMCSD_RSP_R6     0x0600
-
-#define TIFM_MMCSD_RSP_BUSY   0x0800
-
-#define TIFM_MMCSD_CMD_BC     0x0000
-#define TIFM_MMCSD_CMD_BCR    0x1000
-#define TIFM_MMCSD_CMD_AC     0x2000
-#define TIFM_MMCSD_CMD_ADTC   0x3000
-
-typedef enum {
-	IDLE = 0,
-	CMD,    /* main command ended                   */
-	BRS,    /* block transfer finished              */
-	SCMD,   /* stop command ended                   */
-	CARD,   /* card left busy state                 */
-	FIFO,   /* FIFO operation completed (uncertain) */
-	READY
-} card_state_t;
-
-enum {
-	FIFO_RDY   = 0x0001,     /* hardware dependent value */
-	EJECT      = 0x0004,
-	EJECT_DONE = 0x0008,
-	CARD_BUSY  = 0x0010,
-	OPENDRAIN  = 0x0040,     /* hardware dependent value */
-	CARD_EVENT = 0x0100,     /* hardware dependent value */
-	CARD_RO    = 0x0200,     /* hardware dependent value */
-	FIFO_EVENT = 0x10000 };  /* hardware dependent value */
-
-struct tifm_sd {
-	struct tifm_dev     *dev;
-
-	unsigned int        flags;
-	card_state_t        state;
-	unsigned int        clk_freq;
-	unsigned int        clk_div;
-	unsigned long       timeout_jiffies;
-
-	struct tasklet_struct finish_tasklet;
-	struct timer_list     timer;
-	struct mmc_request    *req;
-	wait_queue_head_t     notify;
-
-	size_t                written_blocks;
-	size_t                buffer_size;
-	size_t                buffer_pos;
-
-};
-
-static char* tifm_sd_data_buffer(struct mmc_data *data)
-{
-	return page_address(data->sg->page) + data->sg->offset;
-}
-
-static int tifm_sd_transfer_data(struct tifm_dev *sock, struct tifm_sd *host,
-				 unsigned int host_status)
-{
-	struct mmc_command *cmd = host->req->cmd;
-	unsigned int t_val = 0, cnt = 0;
-	char *buffer;
-
-	if (host_status & TIFM_MMCSD_BRS) {
-		/* in non-dma rx mode BRS fires when fifo is still not empty */
-		if (no_dma && (cmd->data->flags & MMC_DATA_READ)) {
-			buffer = tifm_sd_data_buffer(host->req->data);
-			while (host->buffer_size > host->buffer_pos) {
-				t_val = readl(sock->addr + SOCK_MMCSD_DATA);
-				buffer[host->buffer_pos++] = t_val & 0xff;
-				buffer[host->buffer_pos++] =
-							(t_val >> 8) & 0xff;
-			}
-		}
-		return 1;
-	} else if (no_dma) {
-		buffer = tifm_sd_data_buffer(host->req->data);
-		if ((cmd->data->flags & MMC_DATA_READ) &&
-				(host_status & TIFM_MMCSD_AF)) {
-			for (cnt = 0; cnt < TIFM_MMCSD_FIFO_SIZE; cnt++) {
-				t_val = readl(sock->addr + SOCK_MMCSD_DATA);
-				if (host->buffer_size > host->buffer_pos) {
-					buffer[host->buffer_pos++] =
-							t_val & 0xff;
-					buffer[host->buffer_pos++] =
-							(t_val >> 8) & 0xff;
-				}
-			}
-		} else if ((cmd->data->flags & MMC_DATA_WRITE)
-			   && (host_status & TIFM_MMCSD_AE)) {
-			for (cnt = 0; cnt < TIFM_MMCSD_FIFO_SIZE; cnt++) {
-				if (host->buffer_size > host->buffer_pos) {
-					t_val = buffer[host->buffer_pos++]
-						& 0x00ff;
-					t_val |= ((buffer[host->buffer_pos++])
-						  << 8) & 0xff00;
-					writel(t_val,
-					       sock->addr + SOCK_MMCSD_DATA);
-				}
-			}
-		}
-	}
-	return 0;
-}
-
-static unsigned int tifm_sd_op_flags(struct mmc_command *cmd)
-{
-	unsigned int rc = 0;
-
-	switch (mmc_resp_type(cmd)) {
-	case MMC_RSP_NONE:
-		rc |= TIFM_MMCSD_RSP_R0;
-		break;
-	case MMC_RSP_R1B:
-		rc |= TIFM_MMCSD_RSP_BUSY; // deliberate fall-through
-	case MMC_RSP_R1:
-		rc |= TIFM_MMCSD_RSP_R1;
-		break;
-	case MMC_RSP_R2:
-		rc |= TIFM_MMCSD_RSP_R2;
-		break;
-	case MMC_RSP_R3:
-		rc |= TIFM_MMCSD_RSP_R3;
-		break;
-	default:
-		BUG();
-	}
-
-	switch (mmc_cmd_type(cmd)) {
-	case MMC_CMD_BC:
-		rc |= TIFM_MMCSD_CMD_BC;
-		break;
-	case MMC_CMD_BCR:
-		rc |= TIFM_MMCSD_CMD_BCR;
-		break;
-	case MMC_CMD_AC:
-		rc |= TIFM_MMCSD_CMD_AC;
-		break;
-	case MMC_CMD_ADTC:
-		rc |= TIFM_MMCSD_CMD_ADTC;
-		break;
-	default:
-		BUG();
-	}
-	return rc;
-}
-
-static void tifm_sd_exec(struct tifm_sd *host, struct mmc_command *cmd)
-{
-	struct tifm_dev *sock = host->dev;
-	unsigned int cmd_mask = tifm_sd_op_flags(cmd) |
-				(host->flags & OPENDRAIN);
-
-	if (cmd->data && (cmd->data->flags & MMC_DATA_READ))
-		cmd_mask |= TIFM_MMCSD_READ;
-
-	dev_dbg(&sock->dev, "executing opcode 0x%x, arg: 0x%x, mask: 0x%x\n",
-		cmd->opcode, cmd->arg, cmd_mask);
-
-	writel((cmd->arg >> 16) & 0xffff, sock->addr + SOCK_MMCSD_ARG_HIGH);
-	writel(cmd->arg & 0xffff, sock->addr + SOCK_MMCSD_ARG_LOW);
-	writel(cmd->opcode | cmd_mask, sock->addr + SOCK_MMCSD_COMMAND);
-}
-
-static void tifm_sd_fetch_resp(struct mmc_command *cmd, struct tifm_dev *sock)
-{
-	cmd->resp[0] = (readl(sock->addr + SOCK_MMCSD_RESPONSE + 0x1c) << 16)
-		       | readl(sock->addr + SOCK_MMCSD_RESPONSE + 0x18);
-	cmd->resp[1] = (readl(sock->addr + SOCK_MMCSD_RESPONSE + 0x14) << 16)
-		       | readl(sock->addr + SOCK_MMCSD_RESPONSE + 0x10);
-	cmd->resp[2] = (readl(sock->addr + SOCK_MMCSD_RESPONSE + 0x0c) << 16)
-		       | readl(sock->addr + SOCK_MMCSD_RESPONSE + 0x08);
-	cmd->resp[3] = (readl(sock->addr + SOCK_MMCSD_RESPONSE + 0x04) << 16)
-		       | readl(sock->addr + SOCK_MMCSD_RESPONSE + 0x00);
-}
-
-static void tifm_sd_process_cmd(struct tifm_dev *sock, struct tifm_sd *host,
-				       unsigned int host_status)
-{
-	struct mmc_command *cmd = host->req->cmd;
-
-change_state:
-	switch (host->state) {
-	case IDLE:
-		return;
-	case CMD:
-		if (host_status & (TIFM_MMCSD_EOC | TIFM_MMCSD_CERR)) {
-			tifm_sd_fetch_resp(cmd, sock);
-			if (cmd->data) {
-				host->state = BRS;
-			} else {
-				host->state = READY;
-			}
-			goto change_state;
-		}
-		break;
-	case BRS:
-		if (tifm_sd_transfer_data(sock, host, host_status)) {
-			if (cmd->data->flags & MMC_DATA_WRITE) {
-				host->state = CARD;
-			} else {
-				if (no_dma) {
-					if (host->req->stop) {
-						tifm_sd_exec(host, host->req->stop);
-						host->state = SCMD;
-					} else {
-						host->state = READY;
-					}
-				} else {
-					host->state = FIFO;
-				}
-			}
-			goto change_state;
-		}
-		break;
-	case SCMD:
-		if (host_status & TIFM_MMCSD_EOC) {
-			tifm_sd_fetch_resp(host->req->stop, sock);
-			host->state = READY;
-			goto change_state;
-		}
-		break;
-	case CARD:
-		dev_dbg(&sock->dev, "waiting for CARD, have %zd blocks\n",
-			host->written_blocks);
-		if (!(host->flags & CARD_BUSY)
-		    && (host->written_blocks == cmd->data->blocks)) {
-			if (no_dma) {
-				if (host->req->stop) {
-					tifm_sd_exec(host, host->req->stop);
-					host->state = SCMD;
-				} else {
-					host->state = READY;
-				}
-			} else {
-				host->state = FIFO;
-			}
-			goto change_state;
-		}
-		break;
-	case FIFO:
-		if (host->flags & FIFO_RDY) {
-			host->flags &= ~FIFO_RDY;
-			if (host->req->stop) {
-				tifm_sd_exec(host, host->req->stop);
-				host->state = SCMD;
-			} else {
-				host->state = READY;
-			}
-			goto change_state;
-		}
-		break;
-	case READY:
-		tasklet_schedule(&host->finish_tasklet);
-		return;
-	}
-
-}
-
-/* Called from interrupt handler */
-static void tifm_sd_signal_irq(struct tifm_dev *sock,
-			       unsigned int sock_irq_status)
-{
-	struct tifm_sd *host;
-	unsigned int host_status = 0, fifo_status = 0;
-	int error_code = 0;
-
-	spin_lock(&sock->lock);
-	host = mmc_priv((struct mmc_host*)tifm_get_drvdata(sock));
-
-	if (sock_irq_status & FIFO_EVENT) {
-		fifo_status = readl(sock->addr + SOCK_DMA_FIFO_STATUS);
-		writel(fifo_status, sock->addr + SOCK_DMA_FIFO_STATUS);
-
-		host->flags |= fifo_status & FIFO_RDY;
-	}
-
-	if (sock_irq_status & CARD_EVENT) {
-		host_status = readl(sock->addr + SOCK_MMCSD_STATUS);
-		writel(host_status, sock->addr + SOCK_MMCSD_STATUS);
-
-		if (!host->req)
-			goto done;
-
-		if (host_status & TIFM_MMCSD_ERRMASK) {
-			if (host_status & (TIFM_MMCSD_CTO | TIFM_MMCSD_DTO))
-				error_code = MMC_ERR_TIMEOUT;
-			else if (host_status
-				 & (TIFM_MMCSD_CCRC | TIFM_MMCSD_DCRC))
-				error_code = MMC_ERR_BADCRC;
-
-			writel(TIFM_FIFO_INT_SETALL,
-			       sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR);
-			writel(TIFM_DMA_RESET, sock->addr + SOCK_DMA_CONTROL);
-
-			if (host->req->stop) {
-				if (host->state == SCMD) {
-					host->req->stop->error = error_code;
-				} else if (host->state == BRS
-					   || host->state == CARD
-					   || host->state == FIFO) {
-					host->req->cmd->error = error_code;
-					tifm_sd_exec(host, host->req->stop);
-					host->state = SCMD;
-					goto done;
-				} else {
-					host->req->cmd->error = error_code;
-				}
-			} else {
-				host->req->cmd->error = error_code;
-			}
-			host->state = READY;
-		}
-
-		if (host_status & TIFM_MMCSD_CB)
-			host->flags |= CARD_BUSY;
-		if ((host_status & TIFM_MMCSD_EOFB)
-		    && (host->flags & CARD_BUSY)) {
-			host->written_blocks++;
-			host->flags &= ~CARD_BUSY;
-		}
-        }
-
-	if (host->req)
-		tifm_sd_process_cmd(sock, host, host_status);
-done:
-	dev_dbg(&sock->dev, "host_status %x, fifo_status %x\n",
-		host_status, fifo_status);
-	spin_unlock(&sock->lock);
-}
-
-static void tifm_sd_prepare_data(struct tifm_sd *host, struct mmc_command *cmd)
-{
-	struct tifm_dev *sock = host->dev;
-	unsigned int dest_cnt;
-
-	/* DMA style IO */
-	dev_dbg(&sock->dev, "setting dma for %d blocks\n",
-		cmd->data->blocks);
-	writel(TIFM_FIFO_INT_SETALL,
-	       sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR);
-	writel(ilog2(cmd->data->blksz) - 2,
-	       sock->addr + SOCK_FIFO_PAGE_SIZE);
-	writel(TIFM_FIFO_ENABLE, sock->addr + SOCK_FIFO_CONTROL);
-	writel(TIFM_FIFO_INTMASK, sock->addr + SOCK_DMA_FIFO_INT_ENABLE_SET);
-
-	dest_cnt = (cmd->data->blocks) << 8;
-
-	writel(sg_dma_address(cmd->data->sg), sock->addr + SOCK_DMA_ADDRESS);
-
-	writel(cmd->data->blocks - 1, sock->addr + SOCK_MMCSD_NUM_BLOCKS);
-	writel(cmd->data->blksz - 1, sock->addr + SOCK_MMCSD_BLOCK_LEN);
-
-	if (cmd->data->flags & MMC_DATA_WRITE) {
-		writel(TIFM_MMCSD_TXDE, sock->addr + SOCK_MMCSD_BUFFER_CONFIG);
-		writel(dest_cnt | TIFM_DMA_TX | TIFM_DMA_EN,
-		       sock->addr + SOCK_DMA_CONTROL);
-	} else {
-		writel(TIFM_MMCSD_RXDE, sock->addr + SOCK_MMCSD_BUFFER_CONFIG);
-		writel(dest_cnt | TIFM_DMA_EN, sock->addr + SOCK_DMA_CONTROL);
-	}
-}
-
-static void tifm_sd_set_data_timeout(struct tifm_sd *host,
-				     struct mmc_data *data)
-{
-	struct tifm_dev *sock = host->dev;
-	unsigned int data_timeout = data->timeout_clks;
-
-	if (fixed_timeout)
-		return;
-
-	data_timeout += data->timeout_ns /
-			((1000000000UL / host->clk_freq) * host->clk_div);
-
-	if (data_timeout < 0xffff) {
-		writel(data_timeout, sock->addr + SOCK_MMCSD_DATA_TO);
-		writel((~TIFM_MMCSD_DPE)
-		       & readl(sock->addr + SOCK_MMCSD_SDIO_MODE_CONFIG),
-		       sock->addr + SOCK_MMCSD_SDIO_MODE_CONFIG);
-	} else {
-		data_timeout = (data_timeout >> 10) + 1;
-		if (data_timeout > 0xffff)
-			data_timeout = 0;	/* set to unlimited */
-		writel(data_timeout, sock->addr + SOCK_MMCSD_DATA_TO);
-		writel(TIFM_MMCSD_DPE
-		       | readl(sock->addr + SOCK_MMCSD_SDIO_MODE_CONFIG),
-		       sock->addr + SOCK_MMCSD_SDIO_MODE_CONFIG);
-	}
-}
-
-static void tifm_sd_request(struct mmc_host *mmc, struct mmc_request *mrq)
-{
-	struct tifm_sd *host = mmc_priv(mmc);
-	struct tifm_dev *sock = host->dev;
-	unsigned long flags;
-	int sg_count = 0;
-	struct mmc_data *r_data = mrq->cmd->data;
-
-	spin_lock_irqsave(&sock->lock, flags);
-	if (host->flags & EJECT) {
-		spin_unlock_irqrestore(&sock->lock, flags);
-		goto err_out;
-	}
-
-	if (host->req) {
-		printk(KERN_ERR DRIVER_NAME ": unfinished request detected\n");
-		spin_unlock_irqrestore(&sock->lock, flags);
-		goto err_out;
-	}
-
-	if (r_data) {
-		tifm_sd_set_data_timeout(host, r_data);
-
-		sg_count = tifm_map_sg(sock, r_data->sg, r_data->sg_len,
-				       mrq->cmd->flags & MMC_DATA_WRITE
-				       ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE);
-		if (sg_count != 1) {
-			printk(KERN_ERR DRIVER_NAME
-				": scatterlist map failed\n");
-			spin_unlock_irqrestore(&sock->lock, flags);
-			goto err_out;
-		}
-
-		host->written_blocks = 0;
-		host->flags &= ~CARD_BUSY;
-		tifm_sd_prepare_data(host, mrq->cmd);
-	}
-
-	host->req = mrq;
-	mod_timer(&host->timer, jiffies + host->timeout_jiffies);
-	host->state = CMD;
-	writel(TIFM_CTRL_LED | readl(sock->addr + SOCK_CONTROL),
-	       sock->addr + SOCK_CONTROL);
-	tifm_sd_exec(host, mrq->cmd);
-	spin_unlock_irqrestore(&sock->lock, flags);
-	return;
-
-err_out:
-	if (sg_count > 0)
-		tifm_unmap_sg(sock, r_data->sg, r_data->sg_len,
-			      (r_data->flags & MMC_DATA_WRITE)
-			      ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE);
-
-	mrq->cmd->error = MMC_ERR_TIMEOUT;
-	mmc_request_done(mmc, mrq);
-}
-
-static void tifm_sd_end_cmd(unsigned long data)
-{
-	struct tifm_sd *host = (struct tifm_sd*)data;
-	struct tifm_dev *sock = host->dev;
-	struct mmc_host *mmc = tifm_get_drvdata(sock);
-	struct mmc_request *mrq;
-	struct mmc_data *r_data = NULL;
-	unsigned long flags;
-
-	spin_lock_irqsave(&sock->lock, flags);
-
-	del_timer(&host->timer);
-	mrq = host->req;
-	host->req = NULL;
-	host->state = IDLE;
-
-	if (!mrq) {
-		printk(KERN_ERR DRIVER_NAME ": no request to complete?\n");
-		spin_unlock_irqrestore(&sock->lock, flags);
-		return;
-	}
-
-	r_data = mrq->cmd->data;
-	if (r_data) {
-		if (r_data->flags & MMC_DATA_WRITE) {
-			r_data->bytes_xfered = host->written_blocks
-					       * r_data->blksz;
-		} else {
-			r_data->bytes_xfered = r_data->blocks -
-				readl(sock->addr + SOCK_MMCSD_NUM_BLOCKS) - 1;
-			r_data->bytes_xfered *= r_data->blksz;
-			r_data->bytes_xfered += r_data->blksz -
-				readl(sock->addr + SOCK_MMCSD_BLOCK_LEN) + 1;
-		}
-		tifm_unmap_sg(sock, r_data->sg, r_data->sg_len,
-			      (r_data->flags & MMC_DATA_WRITE)
-			      ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE);
-	}
-
-	writel((~TIFM_CTRL_LED) & readl(sock->addr + SOCK_CONTROL),
-	       sock->addr + SOCK_CONTROL);
-
-	spin_unlock_irqrestore(&sock->lock, flags);
-	mmc_request_done(mmc, mrq);
-}
-
-static void tifm_sd_request_nodma(struct mmc_host *mmc, struct mmc_request *mrq)
-{
-	struct tifm_sd *host = mmc_priv(mmc);
-	struct tifm_dev *sock = host->dev;
-	unsigned long flags;
-	struct mmc_data *r_data = mrq->cmd->data;
-
-	spin_lock_irqsave(&sock->lock, flags);
-	if (host->flags & EJECT) {
-		spin_unlock_irqrestore(&sock->lock, flags);
-		goto err_out;
-	}
-
-	if (host->req) {
-		printk(KERN_ERR DRIVER_NAME ": unfinished request detected\n");
-		spin_unlock_irqrestore(&sock->lock, flags);
-		goto err_out;
-	}
-
-	if (r_data) {
-		tifm_sd_set_data_timeout(host, r_data);
-
-		host->buffer_size = mrq->cmd->data->blocks
-				    * mrq->cmd->data->blksz;
-
-		writel(TIFM_MMCSD_BUFINT
-		       | readl(sock->addr + SOCK_MMCSD_INT_ENABLE),
-		       sock->addr + SOCK_MMCSD_INT_ENABLE);
-		writel(((TIFM_MMCSD_FIFO_SIZE - 1) << 8)
-		       | (TIFM_MMCSD_FIFO_SIZE - 1),
-		       sock->addr + SOCK_MMCSD_BUFFER_CONFIG);
-
-		host->written_blocks = 0;
-		host->flags &= ~CARD_BUSY;
-		host->buffer_pos = 0;
-		writel(r_data->blocks - 1, sock->addr + SOCK_MMCSD_NUM_BLOCKS);
-		writel(r_data->blksz - 1, sock->addr + SOCK_MMCSD_BLOCK_LEN);
-	}
-
-	host->req = mrq;
-	mod_timer(&host->timer, jiffies + host->timeout_jiffies);
-	host->state = CMD;
-	writel(TIFM_CTRL_LED | readl(sock->addr + SOCK_CONTROL),
-	       sock->addr + SOCK_CONTROL);
-	tifm_sd_exec(host, mrq->cmd);
-	spin_unlock_irqrestore(&sock->lock, flags);
-	return;
-
-err_out:
-	mrq->cmd->error = MMC_ERR_TIMEOUT;
-	mmc_request_done(mmc, mrq);
-}
-
-static void tifm_sd_end_cmd_nodma(unsigned long data)
-{
-	struct tifm_sd *host = (struct tifm_sd*)data;
-	struct tifm_dev *sock = host->dev;
-	struct mmc_host *mmc = tifm_get_drvdata(sock);
-	struct mmc_request *mrq;
-	struct mmc_data *r_data = NULL;
-	unsigned long flags;
-
-	spin_lock_irqsave(&sock->lock, flags);
-
-	del_timer(&host->timer);
-	mrq = host->req;
-	host->req = NULL;
-	host->state = IDLE;
-
-	if (!mrq) {
-		printk(KERN_ERR DRIVER_NAME ": no request to complete?\n");
-		spin_unlock_irqrestore(&sock->lock, flags);
-		return;
-	}
-
-	r_data = mrq->cmd->data;
-	if (r_data) {
-		writel((~TIFM_MMCSD_BUFINT) &
-			readl(sock->addr + SOCK_MMCSD_INT_ENABLE),
-			sock->addr + SOCK_MMCSD_INT_ENABLE);
-
-		if (r_data->flags & MMC_DATA_WRITE) {
-			r_data->bytes_xfered = host->written_blocks
-					       * r_data->blksz;
-		} else {
-			r_data->bytes_xfered = r_data->blocks -
-				readl(sock->addr + SOCK_MMCSD_NUM_BLOCKS) - 1;
-			r_data->bytes_xfered *= r_data->blksz;
-			r_data->bytes_xfered += r_data->blksz -
-				readl(sock->addr + SOCK_MMCSD_BLOCK_LEN) + 1;
-		}
-		host->buffer_pos = 0;
-		host->buffer_size = 0;
-	}
-
-	writel((~TIFM_CTRL_LED) & readl(sock->addr + SOCK_CONTROL),
-	       sock->addr + SOCK_CONTROL);
-
-	spin_unlock_irqrestore(&sock->lock, flags);
-
-	mmc_request_done(mmc, mrq);
-}
-
-static void tifm_sd_terminate(struct tifm_sd *host)
-{
-	struct tifm_dev *sock = host->dev;
-	unsigned long flags;
-
-	writel(0, sock->addr + SOCK_MMCSD_INT_ENABLE);
-	mmiowb();
-	spin_lock_irqsave(&sock->lock, flags);
-	host->flags |= EJECT;
-	if (host->req) {
-		writel(TIFM_FIFO_INT_SETALL,
-		       sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR);
-		writel(0, sock->addr + SOCK_DMA_FIFO_INT_ENABLE_SET);
-		tasklet_schedule(&host->finish_tasklet);
-	}
-	spin_unlock_irqrestore(&sock->lock, flags);
-}
-
-static void tifm_sd_abort(unsigned long data)
-{
-	struct tifm_sd *host = (struct tifm_sd*)data;
-
-	printk(KERN_ERR DRIVER_NAME
-	       ": card failed to respond for a long period of time");
-
-	tifm_sd_terminate(host);
-	tifm_eject(host->dev);
-}
-
-static void tifm_sd_ios(struct mmc_host *mmc, struct mmc_ios *ios)
-{
-	struct tifm_sd *host = mmc_priv(mmc);
-	struct tifm_dev *sock = host->dev;
-	unsigned int clk_div1, clk_div2;
-	unsigned long flags;
-
-	spin_lock_irqsave(&sock->lock, flags);
-
-	dev_dbg(&sock->dev, "Setting bus width %d, power %d\n", ios->bus_width,
-		ios->power_mode);
-	if (ios->bus_width == MMC_BUS_WIDTH_4) {
-		writel(TIFM_MMCSD_4BBUS | readl(sock->addr + SOCK_MMCSD_CONFIG),
-		       sock->addr + SOCK_MMCSD_CONFIG);
-	} else {
-		writel((~TIFM_MMCSD_4BBUS)
-		       & readl(sock->addr + SOCK_MMCSD_CONFIG),
-		       sock->addr + SOCK_MMCSD_CONFIG);
-	}
-
-	if (ios->clock) {
-		clk_div1 = 20000000 / ios->clock;
-		if (!clk_div1)
-			clk_div1 = 1;
-
-		clk_div2 = 24000000 / ios->clock;
-		if (!clk_div2)
-			clk_div2 = 1;
-
-		if ((20000000 / clk_div1) > ios->clock)
-			clk_div1++;
-		if ((24000000 / clk_div2) > ios->clock)
-			clk_div2++;
-		if ((20000000 / clk_div1) > (24000000 / clk_div2)) {
-			host->clk_freq = 20000000;
-			host->clk_div = clk_div1;
-			writel((~TIFM_CTRL_FAST_CLK)
-			       & readl(sock->addr + SOCK_CONTROL),
-			       sock->addr + SOCK_CONTROL);
-		} else {
-			host->clk_freq = 24000000;
-			host->clk_div = clk_div2;
-			writel(TIFM_CTRL_FAST_CLK
-			       | readl(sock->addr + SOCK_CONTROL),
-			       sock->addr + SOCK_CONTROL);
-		}
-	} else {
-		host->clk_div = 0;
-	}
-	host->clk_div &= TIFM_MMCSD_CLKMASK;
-	writel(host->clk_div
-	       | ((~TIFM_MMCSD_CLKMASK)
-		  & readl(sock->addr + SOCK_MMCSD_CONFIG)),
-	       sock->addr + SOCK_MMCSD_CONFIG);
-
-	if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN)
-		host->flags |= OPENDRAIN;
-	else
-		host->flags &= ~OPENDRAIN;
-
-	/* chip_select : maybe later */
-	//vdd
-	//power is set before probe / after remove
-	//I believe, power_off when already marked for eject is sufficient to
-	// allow removal.
-	if ((host->flags & EJECT) && ios->power_mode == MMC_POWER_OFF) {
-		host->flags |= EJECT_DONE;
-		wake_up_all(&host->notify);
-	}
-
-	spin_unlock_irqrestore(&sock->lock, flags);
-}
-
-static int tifm_sd_ro(struct mmc_host *mmc)
-{
-	int rc;
-	struct tifm_sd *host = mmc_priv(mmc);
-	struct tifm_dev *sock = host->dev;
-	unsigned long flags;
-
-	spin_lock_irqsave(&sock->lock, flags);
-
-	host->flags |= (CARD_RO & readl(sock->addr + SOCK_PRESENT_STATE));
-	rc = (host->flags & CARD_RO) ? 1 : 0;
-
-	spin_unlock_irqrestore(&sock->lock, flags);
-	return rc;
-}
-
-static struct mmc_host_ops tifm_sd_ops = {
-	.request = tifm_sd_request,
-	.set_ios = tifm_sd_ios,
-	.get_ro  = tifm_sd_ro
-};
-
-static int tifm_sd_initialize_host(struct tifm_sd *host)
-{
-	int rc;
-	unsigned int host_status = 0;
-	struct tifm_dev *sock = host->dev;
-
-	writel(0, sock->addr + SOCK_MMCSD_INT_ENABLE);
-	mmiowb();
-	host->clk_div = 61;
-	host->clk_freq = 20000000;
-	writel(TIFM_MMCSD_RESET, sock->addr + SOCK_MMCSD_SYSTEM_CONTROL);
-	writel(host->clk_div | TIFM_MMCSD_POWER,
-	       sock->addr + SOCK_MMCSD_CONFIG);
-
-	/* wait up to 0.51 sec for reset */
-	for (rc = 2; rc <= 256; rc <<= 1) {
-		if (1 & readl(sock->addr + SOCK_MMCSD_SYSTEM_STATUS)) {
-			rc = 0;
-			break;
-		}
-		msleep(rc);
-	}
-
-	if (rc) {
-		printk(KERN_ERR DRIVER_NAME
-		       ": controller failed to reset\n");
-		return -ENODEV;
-	}
-
-	writel(0, sock->addr + SOCK_MMCSD_NUM_BLOCKS);
-	writel(host->clk_div | TIFM_MMCSD_POWER,
-	       sock->addr + SOCK_MMCSD_CONFIG);
-	writel(TIFM_MMCSD_RXDE, sock->addr + SOCK_MMCSD_BUFFER_CONFIG);
-
-	// command timeout fixed to 64 clocks for now
-	writel(64, sock->addr + SOCK_MMCSD_COMMAND_TO);
-	writel(TIFM_MMCSD_INAB, sock->addr + SOCK_MMCSD_COMMAND);
-
-	/* INAB should take much less than reset */
-	for (rc = 1; rc <= 16; rc <<= 1) {
-		host_status = readl(sock->addr + SOCK_MMCSD_STATUS);
-		writel(host_status, sock->addr + SOCK_MMCSD_STATUS);
-		if (!(host_status & TIFM_MMCSD_ERRMASK)
-		    && (host_status & TIFM_MMCSD_EOC)) {
-			rc = 0;
-			break;
-		}
-		msleep(rc);
-	}
-
-	if (rc) {
-		printk(KERN_ERR DRIVER_NAME
-		       ": card not ready - probe failed on initialization\n");
-		return -ENODEV;
-	}
-
-	writel(TIFM_MMCSD_DATAMASK | TIFM_MMCSD_ERRMASK,
-	       sock->addr + SOCK_MMCSD_INT_ENABLE);
-	mmiowb();
-
-	return 0;
-}
-
-static int tifm_sd_probe(struct tifm_dev *sock)
-{
-	struct mmc_host *mmc;
-	struct tifm_sd *host;
-	int rc = -EIO;
-
-	if (!(TIFM_SOCK_STATE_OCCUPIED
-	      & readl(sock->addr + SOCK_PRESENT_STATE))) {
-		printk(KERN_WARNING DRIVER_NAME ": card gone, unexpectedly\n");
-		return rc;
-	}
-
-	mmc = mmc_alloc_host(sizeof(struct tifm_sd), &sock->dev);
-	if (!mmc)
-		return -ENOMEM;
-
-	host = mmc_priv(mmc);
-	tifm_set_drvdata(sock, mmc);
-	host->dev = sock;
-	host->timeout_jiffies = msecs_to_jiffies(1000);
-
-	init_waitqueue_head(&host->notify);
-	tasklet_init(&host->finish_tasklet,
-		     no_dma ? tifm_sd_end_cmd_nodma : tifm_sd_end_cmd,
-		     (unsigned long)host);
-	setup_timer(&host->timer, tifm_sd_abort, (unsigned long)host);
-
-	tifm_sd_ops.request = no_dma ? tifm_sd_request_nodma : tifm_sd_request;
-	mmc->ops = &tifm_sd_ops;
-	mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
-	mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_MULTIWRITE;
-	mmc->f_min = 20000000 / 60;
-	mmc->f_max = 24000000;
-	mmc->max_hw_segs = 1;
-	mmc->max_phys_segs = 1;
-	// limited by DMA counter - it's safer to stick with
-	// block counter has 11 bits though
-	mmc->max_blk_count = 256;
-	// 2k maximum hw block length
-	mmc->max_blk_size = 2048;
-	mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count;
-	mmc->max_seg_size = mmc->max_req_size;
-	sock->signal_irq = tifm_sd_signal_irq;
-	rc = tifm_sd_initialize_host(host);
-
-	if (!rc)
-		rc = mmc_add_host(mmc);
-	if (rc)
-		goto out_free_mmc;
-
-	return 0;
-out_free_mmc:
-	mmc_free_host(mmc);
-	return rc;
-}
-
-static void tifm_sd_remove(struct tifm_dev *sock)
-{
-	struct mmc_host *mmc = tifm_get_drvdata(sock);
-	struct tifm_sd *host = mmc_priv(mmc);
-
-	del_timer_sync(&host->timer);
-	tifm_sd_terminate(host);
-	wait_event_timeout(host->notify, host->flags & EJECT_DONE,
-			   host->timeout_jiffies);
-	tasklet_kill(&host->finish_tasklet);
-	mmc_remove_host(mmc);
-
-	/* The meaning of the bit majority in this constant is unknown. */
-	writel(0xfff8 & readl(sock->addr + SOCK_CONTROL),
-	       sock->addr + SOCK_CONTROL);
-
-	tifm_set_drvdata(sock, NULL);
-	mmc_free_host(mmc);
-}
-
-#ifdef CONFIG_PM
-
-static int tifm_sd_suspend(struct tifm_dev *sock, pm_message_t state)
-{
-	struct mmc_host *mmc = tifm_get_drvdata(sock);
-	int rc;
-
-	rc = mmc_suspend_host(mmc, state);
-	/* The meaning of the bit majority in this constant is unknown. */
-	writel(0xfff8 & readl(sock->addr + SOCK_CONTROL),
-	       sock->addr + SOCK_CONTROL);
-	return rc;
-}
-
-static int tifm_sd_resume(struct tifm_dev *sock)
-{
-	struct mmc_host *mmc = tifm_get_drvdata(sock);
-	struct tifm_sd *host = mmc_priv(mmc);
-
-	if (sock->media_id != FM_SD
-	    || tifm_sd_initialize_host(host)) {
-		tifm_eject(sock);
-		return 0;
-	} else {
-		return mmc_resume_host(mmc);
-	}
-}
-
-#else
-
-#define tifm_sd_suspend NULL
-#define tifm_sd_resume NULL
-
-#endif /* CONFIG_PM */
-
-static tifm_media_id tifm_sd_id_tbl[] = {
-	FM_SD, 0
-};
-
-static struct tifm_driver tifm_sd_driver = {
-	.driver = {
-		.name  = DRIVER_NAME,
-		.owner = THIS_MODULE
-	},
-	.id_table = tifm_sd_id_tbl,
-	.probe    = tifm_sd_probe,
-	.remove   = tifm_sd_remove,
-	.suspend  = tifm_sd_suspend,
-	.resume   = tifm_sd_resume
-};
-
-static int __init tifm_sd_init(void)
-{
-	return tifm_register_driver(&tifm_sd_driver);
-}
-
-static void __exit tifm_sd_exit(void)
-{
-	tifm_unregister_driver(&tifm_sd_driver);
-}
-
-MODULE_AUTHOR("Alex Dubov");
-MODULE_DESCRIPTION("TI FlashMedia SD driver");
-MODULE_LICENSE("GPL");
-MODULE_DEVICE_TABLE(tifm, tifm_sd_id_tbl);
-MODULE_VERSION(DRIVER_VERSION);
-
-module_init(tifm_sd_init);
-module_exit(tifm_sd_exit);
diff --git a/drivers/mtd/devices/doc2000.c b/drivers/mtd/devices/doc2000.c
index 8a0c4de..c73e96b 100644
--- a/drivers/mtd/devices/doc2000.c
+++ b/drivers/mtd/devices/doc2000.c
@@ -13,7 +13,6 @@
 #include <asm/io.h>
 #include <asm/uaccess.h>
 #include <linux/miscdevice.h>
-#include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/sched.h>
diff --git a/drivers/mtd/devices/doc2001.c b/drivers/mtd/devices/doc2001.c
index 6f368ae..6413efc 100644
--- a/drivers/mtd/devices/doc2001.c
+++ b/drivers/mtd/devices/doc2001.c
@@ -13,7 +13,6 @@
 #include <asm/io.h>
 #include <asm/uaccess.h>
 #include <linux/miscdevice.h>
-#include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/init.h>
diff --git a/drivers/mtd/devices/doc2001plus.c b/drivers/mtd/devices/doc2001plus.c
index 88ba82d..2b30b58 100644
--- a/drivers/mtd/devices/doc2001plus.c
+++ b/drivers/mtd/devices/doc2001plus.c
@@ -17,7 +17,6 @@
 #include <asm/io.h>
 #include <asm/uaccess.h>
 #include <linux/miscdevice.h>
-#include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/init.h>
diff --git a/drivers/mtd/devices/docecc.c b/drivers/mtd/devices/docecc.c
index 52b5d63..fd8a8da 100644
--- a/drivers/mtd/devices/docecc.c
+++ b/drivers/mtd/devices/docecc.c
@@ -29,7 +29,6 @@
 #include <asm/io.h>
 #include <asm/uaccess.h>
 #include <linux/miscdevice.h>
-#include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/init.h>
diff --git a/drivers/mtd/inftlmount.c b/drivers/mtd/inftlmount.c
index acf3ba2..ecac0e4 100644
--- a/drivers/mtd/inftlmount.c
+++ b/drivers/mtd/inftlmount.c
@@ -31,7 +31,6 @@
 #include <asm/io.h>
 #include <asm/uaccess.h>
 #include <linux/miscdevice.h>
-#include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/init.h>
diff --git a/drivers/mtd/nand/cs553x_nand.c b/drivers/mtd/nand/cs553x_nand.c
index 8296305..89deff0 100644
--- a/drivers/mtd/nand/cs553x_nand.c
+++ b/drivers/mtd/nand/cs553x_nand.c
@@ -20,7 +20,6 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/delay.h>
-#include <linux/pci.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.h>
 #include <linux/mtd/nand_ecc.h>
diff --git a/drivers/mtd/nftlcore.c b/drivers/mtd/nftlcore.c
index e6ef7d7..0c9ce19 100644
--- a/drivers/mtd/nftlcore.c
+++ b/drivers/mtd/nftlcore.c
@@ -17,7 +17,6 @@
 #include <asm/io.h>
 #include <asm/uaccess.h>
 #include <linux/miscdevice.h>
-#include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/init.h>
diff --git a/drivers/net/7990.c b/drivers/net/7990.c
index d396f99..0877fc3 100644
--- a/drivers/net/7990.c
+++ b/drivers/net/7990.c
@@ -565,9 +565,9 @@
         ib->btx_ring [entry].length = (-len) | 0xf000;
         ib->btx_ring [entry].misc = 0;
 
-    	if (skb->len < ETH_ZLEN)
-    		memset((char *)&ib->tx_buf[entry][0], 0, ETH_ZLEN);
-        skb_copy_from_linear_data(skb, &ib->tx_buf[entry][0], skblen);
+	if (skb->len < ETH_ZLEN)
+		memset((void *)&ib->tx_buf[entry][0], 0, ETH_ZLEN);
+        skb_copy_from_linear_data(skb, (void *)&ib->tx_buf[entry][0], skblen);
 
         /* Now, give the packet to the lance */
         ib->btx_ring [entry].tmd1_bits = (LE_T1_POK|LE_T1_OWN);
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index dcdad21..69dba62 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -311,7 +311,7 @@
 
 config MAC89x0
 	tristate "Macintosh CS89x0 based ethernet cards"
-	depends on NET_ETHERNET && MAC && BROKEN
+	depends on NET_ETHERNET && MAC
 	---help---
 	  Support for CS89x0 chipset based Ethernet cards.  If you have a
 	  Nubus or LC-PDS network (Ethernet) card of this type, say Y and
@@ -337,8 +337,8 @@
 	  be called macsonic.
 
 config MACMACE
-	bool "Macintosh (AV) onboard MACE ethernet (EXPERIMENTAL)"
-	depends on NET_ETHERNET && MAC && EXPERIMENTAL
+	bool "Macintosh (AV) onboard MACE ethernet"
+	depends on NET_ETHERNET && MAC
 	select CRC32
 	help
 	  Support for the onboard AMD 79C940 MACE Ethernet controller used in
diff --git a/drivers/net/Space.c b/drivers/net/Space.c
index dd8ed45..1c3e293 100644
--- a/drivers/net/Space.c
+++ b/drivers/net/Space.c
@@ -83,7 +83,6 @@
 extern struct net_device *mvme147lance_probe(int unit);
 extern struct net_device *tc515_probe(int unit);
 extern struct net_device *lance_probe(int unit);
-extern struct net_device *mace_probe(int unit);
 extern struct net_device *mac8390_probe(int unit);
 extern struct net_device *mac89x0_probe(int unit);
 extern struct net_device *mc32_probe(int unit);
@@ -274,9 +273,6 @@
 #ifdef CONFIG_MVME147_NET	/* MVME147 internal Ethernet */
 	{mvme147lance_probe, 0},
 #endif
-#ifdef CONFIG_MACMACE		/* Mac 68k Quadra AV builtin Ethernet */
-	{mace_probe, 0},
-#endif
 #ifdef CONFIG_MAC8390           /* NuBus NS8390-based cards */
 	{mac8390_probe, 0},
 #endif
diff --git a/drivers/net/a2065.c b/drivers/net/a2065.c
index 1226cbb..81d5a37 100644
--- a/drivers/net/a2065.c
+++ b/drivers/net/a2065.c
@@ -562,7 +562,6 @@
 	volatile struct lance_init_block *ib = lp->init_block;
 	int entry, skblen, len;
 	int status = 0;
-	static int outs;
 	unsigned long flags;
 
 	skblen = skb->len;
@@ -598,17 +597,16 @@
 	ib->btx_ring [entry].length = (-len) | 0xf000;
 	ib->btx_ring [entry].misc = 0;
 
-	skb_copy_from_linear_data(skb, &ib->tx_buf [entry][0], skblen);
+	skb_copy_from_linear_data(skb, (void *)&ib->tx_buf [entry][0], skblen);
 
 	/* Clear the slack of the packet, do I need this? */
 	if (len != skblen)
-		memset ((char *) &ib->tx_buf [entry][skblen], 0, len - skblen);
+		memset ((void *) &ib->tx_buf [entry][skblen], 0, len - skblen);
 
 	/* Now, give the packet to the lance */
 	ib->btx_ring [entry].tmd1_bits = (LE_T1_POK|LE_T1_OWN);
 	lp->tx_new = (lp->tx_new+1) & lp->tx_ring_mod_mask;
-
-	outs++;
+	lp->stats.tx_bytes += skblen;
 
 	if (TX_BUFFS_AVAIL <= 0)
 		netif_stop_queue(dev);
diff --git a/drivers/net/ariadne.c b/drivers/net/ariadne.c
index a0e68e7..a241ae7 100644
--- a/drivers/net/ariadne.c
+++ b/drivers/net/ariadne.c
@@ -677,6 +677,7 @@
 	priv->cur_tx -= TX_RING_SIZE;
 	priv->dirty_tx -= TX_RING_SIZE;
     }
+    priv->stats.tx_bytes += len;
 
     /* Trigger an immediate send poll. */
     lance->RAP = CSR0;		/* PCnet-ISA Controller Status */
diff --git a/drivers/net/atl1/atl1_param.c b/drivers/net/atl1/atl1_param.c
index c407214..bcd0bd89 100644
--- a/drivers/net/atl1/atl1_param.c
+++ b/drivers/net/atl1/atl1_param.c
@@ -22,7 +22,6 @@
  */
 
 #include <linux/types.h>
-#include <linux/pci.h>
 #include <linux/moduleparam.h>
 #include "atl1.h"
 
diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c
index d10fb80..c39ab80 100644
--- a/drivers/net/au1000_eth.c
+++ b/drivers/net/au1000_eth.c
@@ -45,7 +45,6 @@
 #include <linux/bitops.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
-#include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index f98a220..88b33c6 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -1,6 +1,6 @@
 /* bnx2.c: Broadcom NX2 network driver.
  *
- * Copyright (c) 2004, 2005, 2006 Broadcom Corporation
+ * Copyright (c) 2004-2007 Broadcom 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
@@ -54,8 +54,8 @@
 
 #define DRV_MODULE_NAME		"bnx2"
 #define PFX DRV_MODULE_NAME	": "
-#define DRV_MODULE_VERSION	"1.5.8"
-#define DRV_MODULE_RELDATE	"April 24, 2007"
+#define DRV_MODULE_VERSION	"1.5.10"
+#define DRV_MODULE_RELDATE	"May 1, 2007"
 
 #define RUN_AT(x) (jiffies + (x))
 
@@ -84,6 +84,7 @@
 	BCM5708,
 	BCM5708S,
 	BCM5709,
+	BCM5709S,
 } board_t;
 
 /* indexed by board_t, above */
@@ -98,6 +99,7 @@
 	{ "Broadcom NetXtreme II BCM5708 1000Base-T" },
 	{ "Broadcom NetXtreme II BCM5708 1000Base-SX" },
 	{ "Broadcom NetXtreme II BCM5709 1000Base-T" },
+	{ "Broadcom NetXtreme II BCM5709 1000Base-SX" },
 	};
 
 static struct pci_device_id bnx2_pci_tbl[] = {
@@ -117,6 +119,8 @@
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5708S },
 	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5709,
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5709 },
+	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5709S,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5709S },
 	{ 0, }
 };
 
@@ -230,21 +234,29 @@
 static u32
 bnx2_reg_rd_ind(struct bnx2 *bp, u32 offset)
 {
+	u32 val;
+
+	spin_lock_bh(&bp->indirect_lock);
 	REG_WR(bp, BNX2_PCICFG_REG_WINDOW_ADDRESS, offset);
-	return (REG_RD(bp, BNX2_PCICFG_REG_WINDOW));
+	val = REG_RD(bp, BNX2_PCICFG_REG_WINDOW);
+	spin_unlock_bh(&bp->indirect_lock);
+	return val;
 }
 
 static void
 bnx2_reg_wr_ind(struct bnx2 *bp, u32 offset, u32 val)
 {
+	spin_lock_bh(&bp->indirect_lock);
 	REG_WR(bp, BNX2_PCICFG_REG_WINDOW_ADDRESS, offset);
 	REG_WR(bp, BNX2_PCICFG_REG_WINDOW, val);
+	spin_unlock_bh(&bp->indirect_lock);
 }
 
 static void
 bnx2_ctx_wr(struct bnx2 *bp, u32 cid_addr, u32 offset, u32 val)
 {
 	offset += cid_addr;
+	spin_lock_bh(&bp->indirect_lock);
 	if (CHIP_NUM(bp) == CHIP_NUM_5709) {
 		int i;
 
@@ -262,6 +274,7 @@
 		REG_WR(bp, BNX2_CTX_DATA_ADR, offset);
 		REG_WR(bp, BNX2_CTX_DATA, val);
 	}
+	spin_unlock_bh(&bp->indirect_lock);
 }
 
 static int
@@ -572,8 +585,8 @@
 		if (bp->autoneg) {
 			fw_link_status |= BNX2_LINK_STATUS_AN_ENABLED;
 
-			bnx2_read_phy(bp, MII_BMSR, &bmsr);
-			bnx2_read_phy(bp, MII_BMSR, &bmsr);
+			bnx2_read_phy(bp, bp->mii_bmsr, &bmsr);
+			bnx2_read_phy(bp, bp->mii_bmsr, &bmsr);
 
 			if (!(bmsr & BMSR_ANEGCOMPLETE) ||
 			    bp->phy_flags & PHY_PARALLEL_DETECT_FLAG)
@@ -654,8 +667,8 @@
 		return;
 	}
 
-	bnx2_read_phy(bp, MII_ADVERTISE, &local_adv);
-	bnx2_read_phy(bp, MII_LPA, &remote_adv);
+	bnx2_read_phy(bp, bp->mii_adv, &local_adv);
+	bnx2_read_phy(bp, bp->mii_lpa, &remote_adv);
 
 	if (bp->phy_flags & PHY_SERDES_FLAG) {
 		u32 new_local_adv = 0;
@@ -700,6 +713,45 @@
 }
 
 static int
+bnx2_5709s_linkup(struct bnx2 *bp)
+{
+	u32 val, speed;
+
+	bp->link_up = 1;
+
+	bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_GP_STATUS);
+	bnx2_read_phy(bp, MII_BNX2_GP_TOP_AN_STATUS1, &val);
+	bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_COMBO_IEEEB0);
+
+	if ((bp->autoneg & AUTONEG_SPEED) == 0) {
+		bp->line_speed = bp->req_line_speed;
+		bp->duplex = bp->req_duplex;
+		return 0;
+	}
+	speed = val & MII_BNX2_GP_TOP_AN_SPEED_MSK;
+	switch (speed) {
+		case MII_BNX2_GP_TOP_AN_SPEED_10:
+			bp->line_speed = SPEED_10;
+			break;
+		case MII_BNX2_GP_TOP_AN_SPEED_100:
+			bp->line_speed = SPEED_100;
+			break;
+		case MII_BNX2_GP_TOP_AN_SPEED_1G:
+		case MII_BNX2_GP_TOP_AN_SPEED_1GKV:
+			bp->line_speed = SPEED_1000;
+			break;
+		case MII_BNX2_GP_TOP_AN_SPEED_2_5G:
+			bp->line_speed = SPEED_2500;
+			break;
+	}
+	if (val & MII_BNX2_GP_TOP_AN_FD)
+		bp->duplex = DUPLEX_FULL;
+	else
+		bp->duplex = DUPLEX_HALF;
+	return 0;
+}
+
+static int
 bnx2_5708s_linkup(struct bnx2 *bp)
 {
 	u32 val;
@@ -736,7 +788,7 @@
 	bp->link_up = 1;
 	bp->line_speed = SPEED_1000;
 
-	bnx2_read_phy(bp, MII_BMCR, &bmcr);
+	bnx2_read_phy(bp, bp->mii_bmcr, &bmcr);
 	if (bmcr & BMCR_FULLDPLX) {
 		bp->duplex = DUPLEX_FULL;
 	}
@@ -748,8 +800,8 @@
 		return 0;
 	}
 
-	bnx2_read_phy(bp, MII_ADVERTISE, &local_adv);
-	bnx2_read_phy(bp, MII_LPA, &remote_adv);
+	bnx2_read_phy(bp, bp->mii_adv, &local_adv);
+	bnx2_read_phy(bp, bp->mii_lpa, &remote_adv);
 
 	common = local_adv & remote_adv;
 	if (common & (ADVERTISE_1000XHALF | ADVERTISE_1000XFULL)) {
@@ -770,7 +822,7 @@
 {
 	u32 bmcr;
 
-	bnx2_read_phy(bp, MII_BMCR, &bmcr);
+	bnx2_read_phy(bp, bp->mii_bmcr, &bmcr);
 	if (bmcr & BMCR_ANENABLE) {
 		u32 local_adv, remote_adv, common;
 
@@ -787,8 +839,8 @@
 			bp->duplex = DUPLEX_HALF;
 		}
 		else {
-			bnx2_read_phy(bp, MII_ADVERTISE, &local_adv);
-			bnx2_read_phy(bp, MII_LPA, &remote_adv);
+			bnx2_read_phy(bp, bp->mii_adv, &local_adv);
+			bnx2_read_phy(bp, bp->mii_lpa, &remote_adv);
 
 			common = local_adv & remote_adv;
 			if (common & ADVERTISE_100FULL) {
@@ -898,6 +950,145 @@
 	return 0;
 }
 
+static void
+bnx2_enable_bmsr1(struct bnx2 *bp)
+{
+	if ((bp->phy_flags & PHY_SERDES_FLAG) &&
+	    (CHIP_NUM(bp) == CHIP_NUM_5709))
+		bnx2_write_phy(bp, MII_BNX2_BLK_ADDR,
+			       MII_BNX2_BLK_ADDR_GP_STATUS);
+}
+
+static void
+bnx2_disable_bmsr1(struct bnx2 *bp)
+{
+	if ((bp->phy_flags & PHY_SERDES_FLAG) &&
+	    (CHIP_NUM(bp) == CHIP_NUM_5709))
+		bnx2_write_phy(bp, MII_BNX2_BLK_ADDR,
+			       MII_BNX2_BLK_ADDR_COMBO_IEEEB0);
+}
+
+static int
+bnx2_test_and_enable_2g5(struct bnx2 *bp)
+{
+	u32 up1;
+	int ret = 1;
+
+	if (!(bp->phy_flags & PHY_2_5G_CAPABLE_FLAG))
+		return 0;
+
+	if (bp->autoneg & AUTONEG_SPEED)
+		bp->advertising |= ADVERTISED_2500baseX_Full;
+
+	if (CHIP_NUM(bp) == CHIP_NUM_5709)
+		bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_OVER1G);
+
+	bnx2_read_phy(bp, bp->mii_up1, &up1);
+	if (!(up1 & BCM5708S_UP1_2G5)) {
+		up1 |= BCM5708S_UP1_2G5;
+		bnx2_write_phy(bp, bp->mii_up1, up1);
+		ret = 0;
+	}
+
+	if (CHIP_NUM(bp) == CHIP_NUM_5709)
+		bnx2_write_phy(bp, MII_BNX2_BLK_ADDR,
+			       MII_BNX2_BLK_ADDR_COMBO_IEEEB0);
+
+	return ret;
+}
+
+static int
+bnx2_test_and_disable_2g5(struct bnx2 *bp)
+{
+	u32 up1;
+	int ret = 0;
+
+	if (!(bp->phy_flags & PHY_2_5G_CAPABLE_FLAG))
+		return 0;
+
+	if (CHIP_NUM(bp) == CHIP_NUM_5709)
+		bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_OVER1G);
+
+	bnx2_read_phy(bp, bp->mii_up1, &up1);
+	if (up1 & BCM5708S_UP1_2G5) {
+		up1 &= ~BCM5708S_UP1_2G5;
+		bnx2_write_phy(bp, bp->mii_up1, up1);
+		ret = 1;
+	}
+
+	if (CHIP_NUM(bp) == CHIP_NUM_5709)
+		bnx2_write_phy(bp, MII_BNX2_BLK_ADDR,
+			       MII_BNX2_BLK_ADDR_COMBO_IEEEB0);
+
+	return ret;
+}
+
+static void
+bnx2_enable_forced_2g5(struct bnx2 *bp)
+{
+	u32 bmcr;
+
+	if (!(bp->phy_flags & PHY_2_5G_CAPABLE_FLAG))
+		return;
+
+	if (CHIP_NUM(bp) == CHIP_NUM_5709) {
+		u32 val;
+
+		bnx2_write_phy(bp, MII_BNX2_BLK_ADDR,
+			       MII_BNX2_BLK_ADDR_SERDES_DIG);
+		bnx2_read_phy(bp, MII_BNX2_SERDES_DIG_MISC1, &val);
+		val &= ~MII_BNX2_SD_MISC1_FORCE_MSK;
+		val |= MII_BNX2_SD_MISC1_FORCE | MII_BNX2_SD_MISC1_FORCE_2_5G;
+		bnx2_write_phy(bp, MII_BNX2_SERDES_DIG_MISC1, val);
+
+		bnx2_write_phy(bp, MII_BNX2_BLK_ADDR,
+			       MII_BNX2_BLK_ADDR_COMBO_IEEEB0);
+		bnx2_read_phy(bp, bp->mii_bmcr, &bmcr);
+
+	} else if (CHIP_NUM(bp) == CHIP_NUM_5708) {
+		bnx2_read_phy(bp, bp->mii_bmcr, &bmcr);
+		bmcr |= BCM5708S_BMCR_FORCE_2500;
+	}
+
+	if (bp->autoneg & AUTONEG_SPEED) {
+		bmcr &= ~BMCR_ANENABLE;
+		if (bp->req_duplex == DUPLEX_FULL)
+			bmcr |= BMCR_FULLDPLX;
+	}
+	bnx2_write_phy(bp, bp->mii_bmcr, bmcr);
+}
+
+static void
+bnx2_disable_forced_2g5(struct bnx2 *bp)
+{
+	u32 bmcr;
+
+	if (!(bp->phy_flags & PHY_2_5G_CAPABLE_FLAG))
+		return;
+
+	if (CHIP_NUM(bp) == CHIP_NUM_5709) {
+		u32 val;
+
+		bnx2_write_phy(bp, MII_BNX2_BLK_ADDR,
+			       MII_BNX2_BLK_ADDR_SERDES_DIG);
+		bnx2_read_phy(bp, MII_BNX2_SERDES_DIG_MISC1, &val);
+		val &= ~MII_BNX2_SD_MISC1_FORCE;
+		bnx2_write_phy(bp, MII_BNX2_SERDES_DIG_MISC1, val);
+
+		bnx2_write_phy(bp, MII_BNX2_BLK_ADDR,
+			       MII_BNX2_BLK_ADDR_COMBO_IEEEB0);
+		bnx2_read_phy(bp, bp->mii_bmcr, &bmcr);
+
+	} else if (CHIP_NUM(bp) == CHIP_NUM_5708) {
+		bnx2_read_phy(bp, bp->mii_bmcr, &bmcr);
+		bmcr &= ~BCM5708S_BMCR_FORCE_2500;
+	}
+
+	if (bp->autoneg & AUTONEG_SPEED)
+		bmcr |= BMCR_SPEED1000 | BMCR_ANENABLE | BMCR_ANRESTART;
+	bnx2_write_phy(bp, bp->mii_bmcr, bmcr);
+}
+
 static int
 bnx2_set_link(struct bnx2 *bp)
 {
@@ -911,8 +1102,10 @@
 
 	link_up = bp->link_up;
 
-	bnx2_read_phy(bp, MII_BMSR, &bmsr);
-	bnx2_read_phy(bp, MII_BMSR, &bmsr);
+	bnx2_enable_bmsr1(bp);
+	bnx2_read_phy(bp, bp->mii_bmsr1, &bmsr);
+	bnx2_read_phy(bp, bp->mii_bmsr1, &bmsr);
+	bnx2_disable_bmsr1(bp);
 
 	if ((bp->phy_flags & PHY_SERDES_FLAG) &&
 	    (CHIP_NUM(bp) == CHIP_NUM_5706)) {
@@ -933,6 +1126,8 @@
 				bnx2_5706s_linkup(bp);
 			else if (CHIP_NUM(bp) == CHIP_NUM_5708)
 				bnx2_5708s_linkup(bp);
+			else if (CHIP_NUM(bp) == CHIP_NUM_5709)
+				bnx2_5709s_linkup(bp);
 		}
 		else {
 			bnx2_copper_linkup(bp);
@@ -941,17 +1136,9 @@
 	}
 	else {
 		if ((bp->phy_flags & PHY_SERDES_FLAG) &&
-			(bp->autoneg & AUTONEG_SPEED)) {
+		    (bp->autoneg & AUTONEG_SPEED))
+			bnx2_disable_forced_2g5(bp);
 
-			u32 bmcr;
-
-			bnx2_read_phy(bp, MII_BMCR, &bmcr);
-			bmcr &= ~BCM5708S_BMCR_FORCE_2500;
-			if (!(bmcr & BMCR_ANENABLE)) {
-				bnx2_write_phy(bp, MII_BMCR, bmcr |
-					BMCR_ANENABLE);
-			}
-		}
 		bp->phy_flags &= ~PHY_PARALLEL_DETECT_FLAG;
 		bp->link_up = 0;
 	}
@@ -971,13 +1158,13 @@
 	int i;
 	u32 reg;
 
-        bnx2_write_phy(bp, MII_BMCR, BMCR_RESET);
+        bnx2_write_phy(bp, bp->mii_bmcr, BMCR_RESET);
 
 #define PHY_RESET_MAX_WAIT 100
 	for (i = 0; i < PHY_RESET_MAX_WAIT; i++) {
 		udelay(10);
 
-		bnx2_read_phy(bp, MII_BMCR, &reg);
+		bnx2_read_phy(bp, bp->mii_bmcr, &reg);
 		if (!(reg & BMCR_RESET)) {
 			udelay(20);
 			break;
@@ -1026,34 +1213,40 @@
 static int
 bnx2_setup_serdes_phy(struct bnx2 *bp)
 {
-	u32 adv, bmcr, up1;
+	u32 adv, bmcr;
 	u32 new_adv = 0;
 
 	if (!(bp->autoneg & AUTONEG_SPEED)) {
 		u32 new_bmcr;
 		int force_link_down = 0;
 
-		bnx2_read_phy(bp, MII_ADVERTISE, &adv);
+		if (bp->req_line_speed == SPEED_2500) {
+			if (!bnx2_test_and_enable_2g5(bp))
+				force_link_down = 1;
+		} else if (bp->req_line_speed == SPEED_1000) {
+			if (bnx2_test_and_disable_2g5(bp))
+				force_link_down = 1;
+		}
+		bnx2_read_phy(bp, bp->mii_adv, &adv);
 		adv &= ~(ADVERTISE_1000XFULL | ADVERTISE_1000XHALF);
 
-		bnx2_read_phy(bp, MII_BMCR, &bmcr);
-		new_bmcr = bmcr & ~(BMCR_ANENABLE | BCM5708S_BMCR_FORCE_2500);
+		bnx2_read_phy(bp, bp->mii_bmcr, &bmcr);
+		new_bmcr = bmcr & ~BMCR_ANENABLE;
 		new_bmcr |= BMCR_SPEED1000;
-		if (bp->req_line_speed == SPEED_2500) {
-			new_bmcr |= BCM5708S_BMCR_FORCE_2500;
-			bnx2_read_phy(bp, BCM5708S_UP1, &up1);
-			if (!(up1 & BCM5708S_UP1_2G5)) {
-				up1 |= BCM5708S_UP1_2G5;
-				bnx2_write_phy(bp, BCM5708S_UP1, up1);
-				force_link_down = 1;
+
+		if (CHIP_NUM(bp) == CHIP_NUM_5709) {
+			if (bp->req_line_speed == SPEED_2500)
+				bnx2_enable_forced_2g5(bp);
+			else if (bp->req_line_speed == SPEED_1000) {
+				bnx2_disable_forced_2g5(bp);
+				new_bmcr &= ~0x2000;
 			}
+
 		} else if (CHIP_NUM(bp) == CHIP_NUM_5708) {
-			bnx2_read_phy(bp, BCM5708S_UP1, &up1);
-			if (up1 & BCM5708S_UP1_2G5) {
-				up1 &= ~BCM5708S_UP1_2G5;
-				bnx2_write_phy(bp, BCM5708S_UP1, up1);
-				force_link_down = 1;
-			}
+			if (bp->req_line_speed == SPEED_2500)
+				new_bmcr |= BCM5708S_BMCR_FORCE_2500;
+			else
+				new_bmcr = bmcr & ~BCM5708S_BMCR_FORCE_2500;
 		}
 
 		if (bp->req_duplex == DUPLEX_FULL) {
@@ -1067,49 +1260,48 @@
 		if ((new_bmcr != bmcr) || (force_link_down)) {
 			/* Force a link down visible on the other side */
 			if (bp->link_up) {
-				bnx2_write_phy(bp, MII_ADVERTISE, adv &
+				bnx2_write_phy(bp, bp->mii_adv, adv &
 					       ~(ADVERTISE_1000XFULL |
 						 ADVERTISE_1000XHALF));
-				bnx2_write_phy(bp, MII_BMCR, bmcr |
+				bnx2_write_phy(bp, bp->mii_bmcr, bmcr |
 					BMCR_ANRESTART | BMCR_ANENABLE);
 
 				bp->link_up = 0;
 				netif_carrier_off(bp->dev);
-				bnx2_write_phy(bp, MII_BMCR, new_bmcr);
+				bnx2_write_phy(bp, bp->mii_bmcr, new_bmcr);
 				bnx2_report_link(bp);
 			}
-			bnx2_write_phy(bp, MII_ADVERTISE, adv);
-			bnx2_write_phy(bp, MII_BMCR, new_bmcr);
+			bnx2_write_phy(bp, bp->mii_adv, adv);
+			bnx2_write_phy(bp, bp->mii_bmcr, new_bmcr);
+		} else {
+			bnx2_resolve_flow_ctrl(bp);
+			bnx2_set_mac_link(bp);
 		}
 		return 0;
 	}
 
-	if (bp->phy_flags & PHY_2_5G_CAPABLE_FLAG) {
-		bnx2_read_phy(bp, BCM5708S_UP1, &up1);
-		up1 |= BCM5708S_UP1_2G5;
-		bnx2_write_phy(bp, BCM5708S_UP1, up1);
-	}
+	bnx2_test_and_enable_2g5(bp);
 
 	if (bp->advertising & ADVERTISED_1000baseT_Full)
 		new_adv |= ADVERTISE_1000XFULL;
 
 	new_adv |= bnx2_phy_get_pause_adv(bp);
 
-	bnx2_read_phy(bp, MII_ADVERTISE, &adv);
-	bnx2_read_phy(bp, MII_BMCR, &bmcr);
+	bnx2_read_phy(bp, bp->mii_adv, &adv);
+	bnx2_read_phy(bp, bp->mii_bmcr, &bmcr);
 
 	bp->serdes_an_pending = 0;
 	if ((adv != new_adv) || ((bmcr & BMCR_ANENABLE) == 0)) {
 		/* Force a link down visible on the other side */
 		if (bp->link_up) {
-			bnx2_write_phy(bp, MII_BMCR, BMCR_LOOPBACK);
+			bnx2_write_phy(bp, bp->mii_bmcr, BMCR_LOOPBACK);
 			spin_unlock_bh(&bp->phy_lock);
 			msleep(20);
 			spin_lock_bh(&bp->phy_lock);
 		}
 
-		bnx2_write_phy(bp, MII_ADVERTISE, new_adv);
-		bnx2_write_phy(bp, MII_BMCR, bmcr | BMCR_ANRESTART |
+		bnx2_write_phy(bp, bp->mii_adv, new_adv);
+		bnx2_write_phy(bp, bp->mii_bmcr, bmcr | BMCR_ANRESTART |
 			BMCR_ANENABLE);
 		/* Speed up link-up time when the link partner
 		 * does not autonegotiate which is very common
@@ -1122,6 +1314,9 @@
 		bp->current_interval = SERDES_AN_TIMEOUT;
 		bp->serdes_an_pending = 1;
 		mod_timer(&bp->timer, jiffies + bp->current_interval);
+	} else {
+		bnx2_resolve_flow_ctrl(bp);
+		bnx2_set_mac_link(bp);
 	}
 
 	return 0;
@@ -1146,14 +1341,14 @@
 	u32 bmcr;
 	u32 new_bmcr;
 
-	bnx2_read_phy(bp, MII_BMCR, &bmcr);
+	bnx2_read_phy(bp, bp->mii_bmcr, &bmcr);
 
 	if (bp->autoneg & AUTONEG_SPEED) {
 		u32 adv_reg, adv1000_reg;
 		u32 new_adv_reg = 0;
 		u32 new_adv1000_reg = 0;
 
-		bnx2_read_phy(bp, MII_ADVERTISE, &adv_reg);
+		bnx2_read_phy(bp, bp->mii_adv, &adv_reg);
 		adv_reg &= (PHY_ALL_10_100_SPEED | ADVERTISE_PAUSE_CAP |
 			ADVERTISE_PAUSE_ASYM);
 
@@ -1179,9 +1374,9 @@
 			(adv_reg != new_adv_reg) ||
 			((bmcr & BMCR_ANENABLE) == 0)) {
 
-			bnx2_write_phy(bp, MII_ADVERTISE, new_adv_reg);
+			bnx2_write_phy(bp, bp->mii_adv, new_adv_reg);
 			bnx2_write_phy(bp, MII_CTRL1000, new_adv1000_reg);
-			bnx2_write_phy(bp, MII_BMCR, BMCR_ANRESTART |
+			bnx2_write_phy(bp, bp->mii_bmcr, BMCR_ANRESTART |
 				BMCR_ANENABLE);
 		}
 		else if (bp->link_up) {
@@ -1204,21 +1399,21 @@
 	if (new_bmcr != bmcr) {
 		u32 bmsr;
 
-		bnx2_read_phy(bp, MII_BMSR, &bmsr);
-		bnx2_read_phy(bp, MII_BMSR, &bmsr);
+		bnx2_read_phy(bp, bp->mii_bmsr, &bmsr);
+		bnx2_read_phy(bp, bp->mii_bmsr, &bmsr);
 
 		if (bmsr & BMSR_LSTATUS) {
 			/* Force link down */
-			bnx2_write_phy(bp, MII_BMCR, BMCR_LOOPBACK);
+			bnx2_write_phy(bp, bp->mii_bmcr, BMCR_LOOPBACK);
 			spin_unlock_bh(&bp->phy_lock);
 			msleep(50);
 			spin_lock_bh(&bp->phy_lock);
 
-			bnx2_read_phy(bp, MII_BMSR, &bmsr);
-			bnx2_read_phy(bp, MII_BMSR, &bmsr);
+			bnx2_read_phy(bp, bp->mii_bmsr, &bmsr);
+			bnx2_read_phy(bp, bp->mii_bmsr, &bmsr);
 		}
 
-		bnx2_write_phy(bp, MII_BMCR, new_bmcr);
+		bnx2_write_phy(bp, bp->mii_bmcr, new_bmcr);
 
 		/* Normally, the new speed is setup after the link has
 		 * gone down and up again. In some cases, link will not go
@@ -1230,6 +1425,9 @@
 			bnx2_resolve_flow_ctrl(bp);
 			bnx2_set_mac_link(bp);
 		}
+	} else {
+		bnx2_resolve_flow_ctrl(bp);
+		bnx2_set_mac_link(bp);
 	}
 	return 0;
 }
@@ -1249,10 +1447,63 @@
 }
 
 static int
+bnx2_init_5709s_phy(struct bnx2 *bp)
+{
+	u32 val;
+
+	bp->mii_bmcr = MII_BMCR + 0x10;
+	bp->mii_bmsr = MII_BMSR + 0x10;
+	bp->mii_bmsr1 = MII_BNX2_GP_TOP_AN_STATUS1;
+	bp->mii_adv = MII_ADVERTISE + 0x10;
+	bp->mii_lpa = MII_LPA + 0x10;
+	bp->mii_up1 = MII_BNX2_OVER1G_UP1;
+
+	bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_AER);
+	bnx2_write_phy(bp, MII_BNX2_AER_AER, MII_BNX2_AER_AER_AN_MMD);
+
+	bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_COMBO_IEEEB0);
+	bnx2_reset_phy(bp);
+
+	bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_SERDES_DIG);
+
+	bnx2_read_phy(bp, MII_BNX2_SERDES_DIG_1000XCTL1, &val);
+	val &= ~MII_BNX2_SD_1000XCTL1_AUTODET;
+	val |= MII_BNX2_SD_1000XCTL1_FIBER;
+	bnx2_write_phy(bp, MII_BNX2_SERDES_DIG_1000XCTL1, val);
+
+	bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_OVER1G);
+	bnx2_read_phy(bp, MII_BNX2_OVER1G_UP1, &val);
+	if (bp->phy_flags & PHY_2_5G_CAPABLE_FLAG)
+		val |= BCM5708S_UP1_2G5;
+	else
+		val &= ~BCM5708S_UP1_2G5;
+	bnx2_write_phy(bp, MII_BNX2_OVER1G_UP1, val);
+
+	bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_BAM_NXTPG);
+	bnx2_read_phy(bp, MII_BNX2_BAM_NXTPG_CTL, &val);
+	val |= MII_BNX2_NXTPG_CTL_T2 | MII_BNX2_NXTPG_CTL_BAM;
+	bnx2_write_phy(bp, MII_BNX2_BAM_NXTPG_CTL, val);
+
+	bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_CL73_USERB0);
+
+	val = MII_BNX2_CL73_BAM_EN | MII_BNX2_CL73_BAM_STA_MGR_EN |
+	      MII_BNX2_CL73_BAM_NP_AFT_BP_EN;
+	bnx2_write_phy(bp, MII_BNX2_CL73_BAM_CTL1, val);
+
+	bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_COMBO_IEEEB0);
+
+	return 0;
+}
+
+static int
 bnx2_init_5708s_phy(struct bnx2 *bp)
 {
 	u32 val;
 
+	bnx2_reset_phy(bp);
+
+	bp->mii_up1 = BCM5708S_UP1;
+
 	bnx2_write_phy(bp, BCM5708S_BLK_ADDR, BCM5708S_BLK_ADDR_DIG3);
 	bnx2_write_phy(bp, BCM5708S_DIG_3_0, BCM5708S_DIG_3_0_USE_IEEE);
 	bnx2_write_phy(bp, BCM5708S_BLK_ADDR, BCM5708S_BLK_ADDR_DIG);
@@ -1305,6 +1556,8 @@
 static int
 bnx2_init_5706s_phy(struct bnx2 *bp)
 {
+	bnx2_reset_phy(bp);
+
 	bp->phy_flags &= ~PHY_PARALLEL_DETECT_FLAG;
 
 	if (CHIP_NUM(bp) == CHIP_NUM_5706)
@@ -1342,6 +1595,8 @@
 {
 	u32 val;
 
+	bnx2_reset_phy(bp);
+
 	if (bp->phy_flags & PHY_CRC_FIX_FLAG) {
 		bnx2_write_phy(bp, 0x18, 0x0c00);
 		bnx2_write_phy(bp, 0x17, 0x000a);
@@ -1396,9 +1651,13 @@
 	bp->phy_flags &= ~PHY_INT_MODE_MASK_FLAG;
 	bp->phy_flags |= PHY_INT_MODE_LINK_READY_FLAG;
 
-        REG_WR(bp, BNX2_EMAC_ATTENTION_ENA, BNX2_EMAC_ATTENTION_ENA_LINK);
+	bp->mii_bmcr = MII_BMCR;
+	bp->mii_bmsr = MII_BMSR;
+	bp->mii_bmsr1 = MII_BMSR;
+	bp->mii_adv = MII_ADVERTISE;
+	bp->mii_lpa = MII_LPA;
 
-	bnx2_reset_phy(bp);
+        REG_WR(bp, BNX2_EMAC_ATTENTION_ENA, BNX2_EMAC_ATTENTION_ENA_LINK);
 
 	bnx2_read_phy(bp, MII_PHYSID1, &val);
 	bp->phy_id = val << 16;
@@ -1410,6 +1669,8 @@
 			rc = bnx2_init_5706s_phy(bp);
 		else if (CHIP_NUM(bp) == CHIP_NUM_5708)
 			rc = bnx2_init_5708s_phy(bp);
+		else if (CHIP_NUM(bp) == CHIP_NUM_5709)
+			rc = bnx2_init_5709s_phy(bp);
 	}
 	else {
 		rc = bnx2_init_copper_phy(bp);
@@ -1442,7 +1703,7 @@
 	int rc, i;
 
 	spin_lock_bh(&bp->phy_lock);
-	rc = bnx2_write_phy(bp, MII_BMCR, BMCR_LOOPBACK | BMCR_FULLDPLX |
+	rc = bnx2_write_phy(bp, bp->mii_bmcr, BMCR_LOOPBACK | BMCR_FULLDPLX |
 			    BMCR_SPEED1000);
 	spin_unlock_bh(&bp->phy_lock);
 	if (rc)
@@ -1681,25 +1942,33 @@
 	return 0;
 }
 
+static int
+bnx2_phy_event_is_set(struct bnx2 *bp, u32 event)
+{
+	struct status_block *sblk = bp->status_blk;
+	u32 new_link_state, old_link_state;
+	int is_set = 1;
+
+	new_link_state = sblk->status_attn_bits & event;
+	old_link_state = sblk->status_attn_bits_ack & event;
+	if (new_link_state != old_link_state) {
+		if (new_link_state)
+			REG_WR(bp, BNX2_PCICFG_STATUS_BIT_SET_CMD, event);
+		else
+			REG_WR(bp, BNX2_PCICFG_STATUS_BIT_CLEAR_CMD, event);
+	} else
+		is_set = 0;
+
+	return is_set;
+}
+
 static void
 bnx2_phy_int(struct bnx2 *bp)
 {
-	u32 new_link_state, old_link_state;
-
-	new_link_state = bp->status_blk->status_attn_bits &
-		STATUS_ATTN_BITS_LINK_STATE;
-	old_link_state = bp->status_blk->status_attn_bits_ack &
-		STATUS_ATTN_BITS_LINK_STATE;
-	if (new_link_state != old_link_state) {
-		if (new_link_state) {
-			REG_WR(bp, BNX2_PCICFG_STATUS_BIT_SET_CMD,
-				STATUS_ATTN_BITS_LINK_STATE);
-		}
-		else {
-			REG_WR(bp, BNX2_PCICFG_STATUS_BIT_CLEAR_CMD,
-				STATUS_ATTN_BITS_LINK_STATE);
-		}
+	if (bnx2_phy_event_is_set(bp, STATUS_ATTN_BITS_LINK_STATE)) {
+		spin_lock(&bp->phy_lock);
 		bnx2_set_link(bp);
+		spin_unlock(&bp->phy_lock);
 	}
 }
 
@@ -1993,6 +2262,23 @@
 }
 
 static irqreturn_t
+bnx2_msi_1shot(int irq, void *dev_instance)
+{
+	struct net_device *dev = dev_instance;
+	struct bnx2 *bp = netdev_priv(dev);
+
+	prefetch(bp->status_blk);
+
+	/* Return here if interrupt is disabled. */
+	if (unlikely(atomic_read(&bp->intr_sem) != 0))
+		return IRQ_HANDLED;
+
+	netif_rx_schedule(dev);
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t
 bnx2_interrupt(int irq, void *dev_instance)
 {
 	struct net_device *dev = dev_instance;
@@ -2022,6 +2308,8 @@
 	return IRQ_HANDLED;
 }
 
+#define STATUS_ATTN_EVENTS	STATUS_ATTN_BITS_LINK_STATE
+
 static inline int
 bnx2_has_work(struct bnx2 *bp)
 {
@@ -2031,8 +2319,8 @@
 	    (sblk->status_tx_quick_consumer_index0 != bp->hw_tx_cons))
 		return 1;
 
-	if ((sblk->status_attn_bits & STATUS_ATTN_BITS_LINK_STATE) !=
-	    (sblk->status_attn_bits_ack & STATUS_ATTN_BITS_LINK_STATE))
+	if ((sblk->status_attn_bits & STATUS_ATTN_EVENTS) !=
+	    (sblk->status_attn_bits_ack & STATUS_ATTN_EVENTS))
 		return 1;
 
 	return 0;
@@ -2042,15 +2330,14 @@
 bnx2_poll(struct net_device *dev, int *budget)
 {
 	struct bnx2 *bp = netdev_priv(dev);
+	struct status_block *sblk = bp->status_blk;
+	u32 status_attn_bits = sblk->status_attn_bits;
+	u32 status_attn_bits_ack = sblk->status_attn_bits_ack;
 
-	if ((bp->status_blk->status_attn_bits &
-		STATUS_ATTN_BITS_LINK_STATE) !=
-		(bp->status_blk->status_attn_bits_ack &
-		STATUS_ATTN_BITS_LINK_STATE)) {
+	if ((status_attn_bits & STATUS_ATTN_EVENTS) !=
+	    (status_attn_bits_ack & STATUS_ATTN_EVENTS)) {
 
-		spin_lock(&bp->phy_lock);
 		bnx2_phy_int(bp);
-		spin_unlock(&bp->phy_lock);
 
 		/* This is needed to take care of transient status
 		 * during link changes.
@@ -3489,17 +3776,21 @@
 	REG_WR(bp, BNX2_HC_STAT_COLLECT_TICKS, 0xbb8);  /* 3ms */
 
 	if (CHIP_ID(bp) == CHIP_ID_5706_A1)
-		REG_WR(bp, BNX2_HC_CONFIG, BNX2_HC_CONFIG_COLLECT_STATS);
+		val = BNX2_HC_CONFIG_COLLECT_STATS;
 	else {
-		REG_WR(bp, BNX2_HC_CONFIG, BNX2_HC_CONFIG_RX_TMR_MODE |
-		       BNX2_HC_CONFIG_TX_TMR_MODE |
-		       BNX2_HC_CONFIG_COLLECT_STATS);
+		val = BNX2_HC_CONFIG_RX_TMR_MODE | BNX2_HC_CONFIG_TX_TMR_MODE |
+		      BNX2_HC_CONFIG_COLLECT_STATS;
 	}
 
+	if (bp->flags & ONE_SHOT_MSI_FLAG)
+		val |= BNX2_HC_CONFIG_ONE_SHOT;
+
+	REG_WR(bp, BNX2_HC_CONFIG, val);
+
 	/* Clear internal stats counters. */
 	REG_WR(bp, BNX2_HC_COMMAND, BNX2_HC_COMMAND_CLR_STAT_NOW);
 
-	REG_WR(bp, BNX2_HC_ATTN_BITS_ENABLE, STATUS_ATTN_BITS_LINK_STATE);
+	REG_WR(bp, BNX2_HC_ATTN_BITS_ENABLE, STATUS_ATTN_EVENTS);
 
 	if (REG_RD_IND(bp, bp->shmem_base + BNX2_PORT_FEATURE) &
 	    BNX2_PORT_FEATURE_ASF_ENABLED)
@@ -3763,10 +4054,11 @@
 bnx2_test_registers(struct bnx2 *bp)
 {
 	int ret;
-	int i;
+	int i, is_5709;
 	static const struct {
 		u16   offset;
 		u16   flags;
+#define BNX2_FL_NOT_5709	1
 		u32   rw_mask;
 		u32   ro_mask;
 	} reg_tbl[] = {
@@ -3774,26 +4066,26 @@
 		{ 0x0090, 0, 0xffffffff, 0x00000000 },
 		{ 0x0094, 0, 0x00000000, 0x00000000 },
 
-		{ 0x0404, 0, 0x00003f00, 0x00000000 },
-		{ 0x0418, 0, 0x00000000, 0xffffffff },
-		{ 0x041c, 0, 0x00000000, 0xffffffff },
-		{ 0x0420, 0, 0x00000000, 0x80ffffff },
-		{ 0x0424, 0, 0x00000000, 0x00000000 },
-		{ 0x0428, 0, 0x00000000, 0x00000001 },
-		{ 0x0450, 0, 0x00000000, 0x0000ffff },
-		{ 0x0454, 0, 0x00000000, 0xffffffff },
-		{ 0x0458, 0, 0x00000000, 0xffffffff },
+		{ 0x0404, BNX2_FL_NOT_5709, 0x00003f00, 0x00000000 },
+		{ 0x0418, BNX2_FL_NOT_5709, 0x00000000, 0xffffffff },
+		{ 0x041c, BNX2_FL_NOT_5709, 0x00000000, 0xffffffff },
+		{ 0x0420, BNX2_FL_NOT_5709, 0x00000000, 0x80ffffff },
+		{ 0x0424, BNX2_FL_NOT_5709, 0x00000000, 0x00000000 },
+		{ 0x0428, BNX2_FL_NOT_5709, 0x00000000, 0x00000001 },
+		{ 0x0450, BNX2_FL_NOT_5709, 0x00000000, 0x0000ffff },
+		{ 0x0454, BNX2_FL_NOT_5709, 0x00000000, 0xffffffff },
+		{ 0x0458, BNX2_FL_NOT_5709, 0x00000000, 0xffffffff },
 
-		{ 0x0808, 0, 0x00000000, 0xffffffff },
-		{ 0x0854, 0, 0x00000000, 0xffffffff },
-		{ 0x0868, 0, 0x00000000, 0x77777777 },
-		{ 0x086c, 0, 0x00000000, 0x77777777 },
-		{ 0x0870, 0, 0x00000000, 0x77777777 },
-		{ 0x0874, 0, 0x00000000, 0x77777777 },
+		{ 0x0808, BNX2_FL_NOT_5709, 0x00000000, 0xffffffff },
+		{ 0x0854, BNX2_FL_NOT_5709, 0x00000000, 0xffffffff },
+		{ 0x0868, BNX2_FL_NOT_5709, 0x00000000, 0x77777777 },
+		{ 0x086c, BNX2_FL_NOT_5709, 0x00000000, 0x77777777 },
+		{ 0x0870, BNX2_FL_NOT_5709, 0x00000000, 0x77777777 },
+		{ 0x0874, BNX2_FL_NOT_5709, 0x00000000, 0x77777777 },
 
-		{ 0x0c00, 0, 0x00000000, 0x00000001 },
-		{ 0x0c04, 0, 0x00000000, 0x03ff0001 },
-		{ 0x0c08, 0, 0x0f0ff073, 0x00000000 },
+		{ 0x0c00, BNX2_FL_NOT_5709, 0x00000000, 0x00000001 },
+		{ 0x0c04, BNX2_FL_NOT_5709, 0x00000000, 0x03ff0001 },
+		{ 0x0c08, BNX2_FL_NOT_5709,  0x0f0ff073, 0x00000000 },
 
 		{ 0x1000, 0, 0x00000000, 0x00000001 },
 		{ 0x1004, 0, 0x00000000, 0x000f0001 },
@@ -3840,7 +4132,6 @@
 
 		{ 0x5004, 0, 0x00000000, 0x0000007f },
 		{ 0x5008, 0, 0x0f0007ff, 0x00000000 },
-		{ 0x500c, 0, 0xf800f800, 0x07ff07ff },
 
 		{ 0x5c00, 0, 0x00000000, 0x00000001 },
 		{ 0x5c04, 0, 0x00000000, 0x0003000f },
@@ -3880,8 +4171,16 @@
 	};
 
 	ret = 0;
+	is_5709 = 0;
+	if (CHIP_NUM(bp) == CHIP_NUM_5709)
+		is_5709 = 1;
+
 	for (i = 0; reg_tbl[i].offset != 0xffff; i++) {
 		u32 offset, rw_mask, ro_mask, save_val, val;
+		u16 flags = reg_tbl[i].flags;
+
+		if (is_5709 && (flags & BNX2_FL_NOT_5709))
+			continue;
 
 		offset = (u32) reg_tbl[i].offset;
 		rw_mask = reg_tbl[i].rw_mask;
@@ -3950,10 +4249,10 @@
 {
 	int ret = 0;
 	int i;
-	static const struct {
+	static struct mem_entry {
 		u32   offset;
 		u32   len;
-	} mem_tbl[] = {
+	} mem_tbl_5706[] = {
 		{ 0x60000,  0x4000 },
 		{ 0xa0000,  0x3000 },
 		{ 0xe0000,  0x4000 },
@@ -3961,7 +4260,21 @@
 		{ 0x1a0000, 0x4000 },
 		{ 0x160000, 0x4000 },
 		{ 0xffffffff, 0    },
+	},
+	mem_tbl_5709[] = {
+		{ 0x60000,  0x4000 },
+		{ 0xa0000,  0x3000 },
+		{ 0xe0000,  0x4000 },
+		{ 0x120000, 0x4000 },
+		{ 0x1a0000, 0x4000 },
+		{ 0xffffffff, 0    },
 	};
+	struct mem_entry *mem_tbl;
+
+	if (CHIP_NUM(bp) == CHIP_NUM_5709)
+		mem_tbl = mem_tbl_5709;
+	else
+		mem_tbl = mem_tbl_5706;
 
 	for (i = 0; mem_tbl[i].offset != 0xffffffff; i++) {
 		if ((ret = bnx2_do_mem_test(bp, mem_tbl[i].offset,
@@ -4163,8 +4476,10 @@
 	u32 bmsr;
 
 	spin_lock_bh(&bp->phy_lock);
-	bnx2_read_phy(bp, MII_BMSR, &bmsr);
-	bnx2_read_phy(bp, MII_BMSR, &bmsr);
+	bnx2_enable_bmsr1(bp);
+	bnx2_read_phy(bp, bp->mii_bmsr1, &bmsr);
+	bnx2_read_phy(bp, bp->mii_bmsr1, &bmsr);
+	bnx2_disable_bmsr1(bp);
 	spin_unlock_bh(&bp->phy_lock);
 
 	if (bmsr & BMSR_LSTATUS) {
@@ -4214,7 +4529,7 @@
 
 		bp->current_interval = bp->timer_interval;
 
-		bnx2_read_phy(bp, MII_BMCR, &bmcr);
+		bnx2_read_phy(bp, bp->mii_bmcr, &bmcr);
 
 		if (bmcr & BMCR_ANENABLE) {
 			u32 phy1, phy2;
@@ -4232,7 +4547,7 @@
 
 				bmcr &= ~BMCR_ANENABLE;
 				bmcr |= BMCR_SPEED1000 | BMCR_FULLDPLX;
-				bnx2_write_phy(bp, MII_BMCR, bmcr);
+				bnx2_write_phy(bp, bp->mii_bmcr, bmcr);
 				bp->phy_flags |= PHY_PARALLEL_DETECT_FLAG;
 			}
 		}
@@ -4246,9 +4561,9 @@
 		if (phy2 & 0x20) {
 			u32 bmcr;
 
-			bnx2_read_phy(bp, MII_BMCR, &bmcr);
+			bnx2_read_phy(bp, bp->mii_bmcr, &bmcr);
 			bmcr |= BMCR_ANENABLE;
-			bnx2_write_phy(bp, MII_BMCR, bmcr);
+			bnx2_write_phy(bp, bp->mii_bmcr, bmcr);
 
 			bp->phy_flags &= ~PHY_PARALLEL_DETECT_FLAG;
 		}
@@ -4272,17 +4587,12 @@
 	else if ((bp->link_up == 0) && (bp->autoneg & AUTONEG_SPEED)) {
 		u32 bmcr;
 
-		bnx2_read_phy(bp, MII_BMCR, &bmcr);
-
+		bnx2_read_phy(bp, bp->mii_bmcr, &bmcr);
 		if (bmcr & BMCR_ANENABLE) {
-			bmcr &= ~BMCR_ANENABLE;
-			bmcr |= BMCR_FULLDPLX | BCM5708S_BMCR_FORCE_2500;
-			bnx2_write_phy(bp, MII_BMCR, bmcr);
+			bnx2_enable_forced_2g5(bp);
 			bp->current_interval = SERDES_FORCED_TIMEOUT;
 		} else {
-			bmcr &= ~(BMCR_FULLDPLX | BCM5708S_BMCR_FORCE_2500);
-			bmcr |= BMCR_ANENABLE;
-			bnx2_write_phy(bp, MII_BMCR, bmcr);
+			bnx2_disable_forced_2g5(bp);
 			bp->serdes_an_pending = 2;
 			bp->current_interval = bp->timer_interval;
 		}
@@ -4313,7 +4623,7 @@
 	if (bp->phy_flags & PHY_SERDES_FLAG) {
 		if (CHIP_NUM(bp) == CHIP_NUM_5706)
 			bnx2_5706_serdes_timer(bp);
-		else if (CHIP_NUM(bp) == CHIP_NUM_5708)
+		else
 			bnx2_5708_serdes_timer(bp);
 	}
 
@@ -4321,6 +4631,38 @@
 	mod_timer(&bp->timer, jiffies + bp->current_interval);
 }
 
+static int
+bnx2_request_irq(struct bnx2 *bp)
+{
+	struct net_device *dev = bp->dev;
+	int rc = 0;
+
+	if (bp->flags & USING_MSI_FLAG) {
+		irq_handler_t	fn = bnx2_msi;
+
+		if (bp->flags & ONE_SHOT_MSI_FLAG)
+			fn = bnx2_msi_1shot;
+
+		rc = request_irq(bp->pdev->irq, fn, 0, dev->name, dev);
+	} else
+		rc = request_irq(bp->pdev->irq, bnx2_interrupt,
+				 IRQF_SHARED, dev->name, dev);
+	return rc;
+}
+
+static void
+bnx2_free_irq(struct bnx2 *bp)
+{
+	struct net_device *dev = bp->dev;
+
+	if (bp->flags & USING_MSI_FLAG) {
+		free_irq(bp->pdev->irq, dev);
+		pci_disable_msi(bp->pdev);
+		bp->flags &= ~(USING_MSI_FLAG | ONE_SHOT_MSI_FLAG);
+	} else
+		free_irq(bp->pdev->irq, dev);
+}
+
 /* Called with rtnl_lock */
 static int
 bnx2_open(struct net_device *dev)
@@ -4328,6 +4670,8 @@
 	struct bnx2 *bp = netdev_priv(dev);
 	int rc;
 
+	netif_carrier_off(dev);
+
 	bnx2_set_power_state(bp, PCI_D0);
 	bnx2_disable_int(bp);
 
@@ -4335,24 +4679,15 @@
 	if (rc)
 		return rc;
 
-	if ((CHIP_ID(bp) != CHIP_ID_5706_A0) &&
-		(CHIP_ID(bp) != CHIP_ID_5706_A1) &&
-		!disable_msi) {
-
+	if ((bp->flags & MSI_CAP_FLAG) && !disable_msi) {
 		if (pci_enable_msi(bp->pdev) == 0) {
 			bp->flags |= USING_MSI_FLAG;
-			rc = request_irq(bp->pdev->irq, bnx2_msi, 0, dev->name,
-					dev);
-		}
-		else {
-			rc = request_irq(bp->pdev->irq, bnx2_interrupt,
-					IRQF_SHARED, dev->name, dev);
+			if (CHIP_NUM(bp) == CHIP_NUM_5709)
+				bp->flags |= ONE_SHOT_MSI_FLAG;
 		}
 	}
-	else {
-		rc = request_irq(bp->pdev->irq, bnx2_interrupt, IRQF_SHARED,
-				dev->name, dev);
-	}
+	rc = bnx2_request_irq(bp);
+
 	if (rc) {
 		bnx2_free_mem(bp);
 		return rc;
@@ -4361,11 +4696,7 @@
 	rc = bnx2_init_nic(bp);
 
 	if (rc) {
-		free_irq(bp->pdev->irq, dev);
-		if (bp->flags & USING_MSI_FLAG) {
-			pci_disable_msi(bp->pdev);
-			bp->flags &= ~USING_MSI_FLAG;
-		}
+		bnx2_free_irq(bp);
 		bnx2_free_skbs(bp);
 		bnx2_free_mem(bp);
 		return rc;
@@ -4389,16 +4720,13 @@
 			       bp->dev->name);
 
 			bnx2_disable_int(bp);
-			free_irq(bp->pdev->irq, dev);
-			pci_disable_msi(bp->pdev);
-			bp->flags &= ~USING_MSI_FLAG;
+			bnx2_free_irq(bp);
 
 			rc = bnx2_init_nic(bp);
 
-			if (!rc) {
-				rc = request_irq(bp->pdev->irq, bnx2_interrupt,
-					IRQF_SHARED, dev->name, dev);
-			}
+			if (!rc)
+				rc = bnx2_request_irq(bp);
+
 			if (rc) {
 				bnx2_free_skbs(bp);
 				bnx2_free_mem(bp);
@@ -4508,40 +4836,53 @@
 		vlan_tag_flags |=
 			(TX_BD_FLAGS_VLAN_TAG | (vlan_tx_tag_get(skb) << 16));
 	}
-	if ((mss = skb_shinfo(skb)->gso_size) &&
-		(skb->len > (bp->dev->mtu + ETH_HLEN))) {
+	if ((mss = skb_shinfo(skb)->gso_size)) {
 		u32 tcp_opt_len, ip_tcp_len;
 		struct iphdr *iph;
 
-		if (skb_header_cloned(skb) &&
-		    pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) {
-			dev_kfree_skb(skb);
-			return NETDEV_TX_OK;
-		}
-
 		vlan_tag_flags |= TX_BD_FLAGS_SW_LSO;
 
-		tcp_opt_len = 0;
-		if (tcp_hdr(skb)->doff > 5)
-			tcp_opt_len = tcp_optlen(skb);
+		tcp_opt_len = tcp_optlen(skb);
 
-		ip_tcp_len = ip_hdrlen(skb) + sizeof(struct tcphdr);
+		if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6) {
+			u32 tcp_off = skb_transport_offset(skb) -
+				      sizeof(struct ipv6hdr) - ETH_HLEN;
 
-		iph = ip_hdr(skb);
-		iph->check = 0;
-		iph->tot_len = htons(mss + ip_tcp_len + tcp_opt_len);
-		tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr,
-							 iph->daddr, 0,
-							 IPPROTO_TCP, 0);
-		if (tcp_opt_len || (iph->ihl > 5)) {
-			vlan_tag_flags |= ((iph->ihl - 5) +
-					   (tcp_opt_len >> 2)) << 8;
+			vlan_tag_flags |= ((tcp_opt_len >> 2) << 8) |
+					  TX_BD_FLAGS_SW_FLAGS;
+			if (likely(tcp_off == 0))
+				vlan_tag_flags &= ~TX_BD_FLAGS_TCP6_OFF0_MSK;
+			else {
+				tcp_off >>= 3;
+				vlan_tag_flags |= ((tcp_off & 0x3) <<
+						   TX_BD_FLAGS_TCP6_OFF0_SHL) |
+						  ((tcp_off & 0x10) <<
+						   TX_BD_FLAGS_TCP6_OFF4_SHL);
+				mss |= (tcp_off & 0xc) << TX_BD_TCP6_OFF2_SHL;
+			}
+		} else {
+			if (skb_header_cloned(skb) &&
+			    pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) {
+				dev_kfree_skb(skb);
+				return NETDEV_TX_OK;
+			}
+
+			ip_tcp_len = ip_hdrlen(skb) + sizeof(struct tcphdr);
+
+			iph = ip_hdr(skb);
+			iph->check = 0;
+			iph->tot_len = htons(mss + ip_tcp_len + tcp_opt_len);
+			tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr,
+								 iph->daddr, 0,
+								 IPPROTO_TCP,
+								 0);
+			if (tcp_opt_len || (iph->ihl > 5)) {
+				vlan_tag_flags |= ((iph->ihl - 5) +
+						   (tcp_opt_len >> 2)) << 8;
+			}
 		}
-	}
-	else
-	{
+	} else
 		mss = 0;
-	}
 
 	mapping = pci_map_single(bp->pdev, skb->data, len, PCI_DMA_TODEVICE);
 
@@ -4622,11 +4963,7 @@
 	else
 		reset_code = BNX2_DRV_MSG_CODE_SUSPEND_NO_WOL;
 	bnx2_reset_chip(bp, reset_code);
-	free_irq(bp->pdev->irq, dev);
-	if (bp->flags & USING_MSI_FLAG) {
-		pci_disable_msi(bp->pdev);
-		bp->flags &= ~USING_MSI_FLAG;
-	}
+	bnx2_free_irq(bp);
 	bnx2_free_skbs(bp);
 	bnx2_free_mem(bp);
 	bp->link_up = 0;
@@ -4735,6 +5072,8 @@
 	if (bp->phy_flags & PHY_SERDES_FLAG) {
 		cmd->supported |= SUPPORTED_1000baseT_Full |
 			SUPPORTED_FIBRE;
+		if (bp->phy_flags & PHY_2_5G_CAPABLE_FLAG)
+			cmd->supported |= SUPPORTED_2500baseX_Full;
 
 		cmd->port = PORT_FIBRE;
 	}
@@ -4798,8 +5137,10 @@
 
 			advertising = cmd->advertising;
 
-		}
-		else if (cmd->advertising == ADVERTISED_1000baseT_Full) {
+		} else if (cmd->advertising == ADVERTISED_2500baseX_Full) {
+			if (!(bp->phy_flags & PHY_2_5G_CAPABLE_FLAG))
+				return -EINVAL;
+		} else if (cmd->advertising == ADVERTISED_1000baseT_Full) {
 			advertising = cmd->advertising;
 		}
 		else if (cmd->advertising == ADVERTISED_1000baseT_Half) {
@@ -4975,7 +5316,7 @@
 
 	/* Force a link down visible on the other side */
 	if (bp->phy_flags & PHY_SERDES_FLAG) {
-		bnx2_write_phy(bp, MII_BMCR, BMCR_LOOPBACK);
+		bnx2_write_phy(bp, bp->mii_bmcr, BMCR_LOOPBACK);
 		spin_unlock_bh(&bp->phy_lock);
 
 		msleep(20);
@@ -4987,9 +5328,9 @@
 		mod_timer(&bp->timer, jiffies + bp->current_interval);
 	}
 
-	bnx2_read_phy(bp, MII_BMCR, &bmcr);
+	bnx2_read_phy(bp, bp->mii_bmcr, &bmcr);
 	bmcr &= ~BMCR_LOOPBACK;
-	bnx2_write_phy(bp, MII_BMCR, bmcr | BMCR_ANRESTART | BMCR_ANENABLE);
+	bnx2_write_phy(bp, bp->mii_bmcr, bmcr | BMCR_ANRESTART | BMCR_ANENABLE);
 
 	spin_unlock_bh(&bp->phy_lock);
 
@@ -5209,10 +5550,15 @@
 static int
 bnx2_set_tso(struct net_device *dev, u32 data)
 {
-	if (data)
+	struct bnx2 *bp = netdev_priv(dev);
+
+	if (data) {
 		dev->features |= NETIF_F_TSO | NETIF_F_TSO_ECN;
-	else
-		dev->features &= ~(NETIF_F_TSO | NETIF_F_TSO_ECN);
+		if (CHIP_NUM(bp) == CHIP_NUM_5709)
+			dev->features |= NETIF_F_TSO6;
+	} else
+		dev->features &= ~(NETIF_F_TSO | NETIF_F_TSO6 |
+				   NETIF_F_TSO_ECN);
 	return 0;
 }
 
@@ -5510,6 +5856,17 @@
 	return 0;
 }
 
+static int
+bnx2_set_tx_csum(struct net_device *dev, u32 data)
+{
+	struct bnx2 *bp = netdev_priv(dev);
+
+	if (CHIP_NUM(bp) == CHIP_NUM_5709)
+		return (ethtool_op_set_tx_hw_csum(dev, data));
+	else
+		return (ethtool_op_set_tx_csum(dev, data));
+}
+
 static const struct ethtool_ops bnx2_ethtool_ops = {
 	.get_settings		= bnx2_get_settings,
 	.set_settings		= bnx2_set_settings,
@@ -5532,7 +5889,7 @@
 	.get_rx_csum		= bnx2_get_rx_csum,
 	.set_rx_csum		= bnx2_set_rx_csum,
 	.get_tx_csum		= ethtool_op_get_tx_csum,
-	.set_tx_csum		= ethtool_op_set_tx_csum,
+	.set_tx_csum		= bnx2_set_tx_csum,
 	.get_sg			= ethtool_op_get_sg,
 	.set_sg			= ethtool_op_set_sg,
 	.get_tso		= ethtool_op_get_tso,
@@ -5562,6 +5919,9 @@
 	case SIOCGMIIREG: {
 		u32 mii_regval;
 
+		if (!netif_running(dev))
+			return -EAGAIN;
+
 		spin_lock_bh(&bp->phy_lock);
 		err = bnx2_read_phy(bp, data->reg_num & 0x1f, &mii_regval);
 		spin_unlock_bh(&bp->phy_lock);
@@ -5575,6 +5935,9 @@
 		if (!capable(CAP_NET_ADMIN))
 			return -EPERM;
 
+		if (!netif_running(dev))
+			return -EAGAIN;
+
 		spin_lock_bh(&bp->phy_lock);
 		err = bnx2_write_phy(bp, data->reg_num & 0x1f, data->val_in);
 		spin_unlock_bh(&bp->phy_lock);
@@ -5676,108 +6039,11 @@
 	}
 }
 
-static int __devinit
-bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
+static void __devinit
+bnx2_get_pci_speed(struct bnx2 *bp)
 {
-	struct bnx2 *bp;
-	unsigned long mem_len;
-	int rc;
 	u32 reg;
 
-	SET_MODULE_OWNER(dev);
-	SET_NETDEV_DEV(dev, &pdev->dev);
-	bp = netdev_priv(dev);
-
-	bp->flags = 0;
-	bp->phy_flags = 0;
-
-	/* enable device (incl. PCI PM wakeup), and bus-mastering */
-	rc = pci_enable_device(pdev);
-	if (rc) {
-		dev_err(&pdev->dev, "Cannot enable PCI device, aborting.");
-		goto err_out;
-	}
-
-	if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
-		dev_err(&pdev->dev,
-			"Cannot find PCI device base address, aborting.\n");
-		rc = -ENODEV;
-		goto err_out_disable;
-	}
-
-	rc = pci_request_regions(pdev, DRV_MODULE_NAME);
-	if (rc) {
-		dev_err(&pdev->dev, "Cannot obtain PCI resources, aborting.\n");
-		goto err_out_disable;
-	}
-
-	pci_set_master(pdev);
-
-	bp->pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM);
-	if (bp->pm_cap == 0) {
-		dev_err(&pdev->dev,
-			"Cannot find power management capability, aborting.\n");
-		rc = -EIO;
-		goto err_out_release;
-	}
-
-	if (pci_set_dma_mask(pdev, DMA_64BIT_MASK) == 0) {
-		bp->flags |= USING_DAC_FLAG;
-		if (pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK) != 0) {
-			dev_err(&pdev->dev,
-				"pci_set_consistent_dma_mask failed, aborting.\n");
-			rc = -EIO;
-			goto err_out_release;
-		}
-	}
-	else if (pci_set_dma_mask(pdev, DMA_32BIT_MASK) != 0) {
-		dev_err(&pdev->dev, "System does not support DMA, aborting.\n");
-		rc = -EIO;
-		goto err_out_release;
-	}
-
-	bp->dev = dev;
-	bp->pdev = pdev;
-
-	spin_lock_init(&bp->phy_lock);
-	INIT_WORK(&bp->reset_task, bnx2_reset_task);
-
-	dev->base_addr = dev->mem_start = pci_resource_start(pdev, 0);
-	mem_len = MB_GET_CID_ADDR(TX_TSS_CID + 1);
-	dev->mem_end = dev->mem_start + mem_len;
-	dev->irq = pdev->irq;
-
-	bp->regview = ioremap_nocache(dev->base_addr, mem_len);
-
-	if (!bp->regview) {
-		dev_err(&pdev->dev, "Cannot map register space, aborting.\n");
-		rc = -ENOMEM;
-		goto err_out_release;
-	}
-
-	/* Configure byte swap and enable write to the reg_window registers.
-	 * Rely on CPU to do target byte swapping on big endian systems
-	 * The chip's target access swapping will not swap all accesses
-	 */
-	pci_write_config_dword(bp->pdev, BNX2_PCICFG_MISC_CONFIG,
-			       BNX2_PCICFG_MISC_CONFIG_REG_WINDOW_ENA |
-			       BNX2_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP);
-
-	bnx2_set_power_state(bp, PCI_D0);
-
-	bp->chip_id = REG_RD(bp, BNX2_MISC_ID);
-
-	if (CHIP_NUM(bp) != CHIP_NUM_5709) {
-		bp->pcix_cap = pci_find_capability(pdev, PCI_CAP_ID_PCIX);
-		if (bp->pcix_cap == 0) {
-			dev_err(&pdev->dev,
-				"Cannot find PCIX capability, aborting.\n");
-			rc = -EIO;
-			goto err_out_unmap;
-		}
-	}
-
-	/* Get bus information. */
 	reg = REG_RD(bp, BNX2_PCICFG_MISC_STATUS);
 	if (reg & BNX2_PCICFG_MISC_STATUS_PCIX_DET) {
 		u32 clkreg;
@@ -5823,6 +6089,132 @@
 	if (reg & BNX2_PCICFG_MISC_STATUS_32BIT_DET)
 		bp->flags |= PCI_32BIT_FLAG;
 
+}
+
+static int __devinit
+bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
+{
+	struct bnx2 *bp;
+	unsigned long mem_len;
+	int rc;
+	u32 reg;
+	u64 dma_mask, persist_dma_mask;
+
+	SET_MODULE_OWNER(dev);
+	SET_NETDEV_DEV(dev, &pdev->dev);
+	bp = netdev_priv(dev);
+
+	bp->flags = 0;
+	bp->phy_flags = 0;
+
+	/* enable device (incl. PCI PM wakeup), and bus-mastering */
+	rc = pci_enable_device(pdev);
+	if (rc) {
+		dev_err(&pdev->dev, "Cannot enable PCI device, aborting.");
+		goto err_out;
+	}
+
+	if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
+		dev_err(&pdev->dev,
+			"Cannot find PCI device base address, aborting.\n");
+		rc = -ENODEV;
+		goto err_out_disable;
+	}
+
+	rc = pci_request_regions(pdev, DRV_MODULE_NAME);
+	if (rc) {
+		dev_err(&pdev->dev, "Cannot obtain PCI resources, aborting.\n");
+		goto err_out_disable;
+	}
+
+	pci_set_master(pdev);
+
+	bp->pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM);
+	if (bp->pm_cap == 0) {
+		dev_err(&pdev->dev,
+			"Cannot find power management capability, aborting.\n");
+		rc = -EIO;
+		goto err_out_release;
+	}
+
+	bp->dev = dev;
+	bp->pdev = pdev;
+
+	spin_lock_init(&bp->phy_lock);
+	spin_lock_init(&bp->indirect_lock);
+	INIT_WORK(&bp->reset_task, bnx2_reset_task);
+
+	dev->base_addr = dev->mem_start = pci_resource_start(pdev, 0);
+	mem_len = MB_GET_CID_ADDR(TX_TSS_CID + 1);
+	dev->mem_end = dev->mem_start + mem_len;
+	dev->irq = pdev->irq;
+
+	bp->regview = ioremap_nocache(dev->base_addr, mem_len);
+
+	if (!bp->regview) {
+		dev_err(&pdev->dev, "Cannot map register space, aborting.\n");
+		rc = -ENOMEM;
+		goto err_out_release;
+	}
+
+	/* Configure byte swap and enable write to the reg_window registers.
+	 * Rely on CPU to do target byte swapping on big endian systems
+	 * The chip's target access swapping will not swap all accesses
+	 */
+	pci_write_config_dword(bp->pdev, BNX2_PCICFG_MISC_CONFIG,
+			       BNX2_PCICFG_MISC_CONFIG_REG_WINDOW_ENA |
+			       BNX2_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP);
+
+	bnx2_set_power_state(bp, PCI_D0);
+
+	bp->chip_id = REG_RD(bp, BNX2_MISC_ID);
+
+	if (CHIP_NUM(bp) == CHIP_NUM_5709) {
+		if (pci_find_capability(pdev, PCI_CAP_ID_EXP) == 0) {
+			dev_err(&pdev->dev,
+				"Cannot find PCIE capability, aborting.\n");
+			rc = -EIO;
+			goto err_out_unmap;
+		}
+		bp->flags |= PCIE_FLAG;
+	} else {
+		bp->pcix_cap = pci_find_capability(pdev, PCI_CAP_ID_PCIX);
+		if (bp->pcix_cap == 0) {
+			dev_err(&pdev->dev,
+				"Cannot find PCIX capability, aborting.\n");
+			rc = -EIO;
+			goto err_out_unmap;
+		}
+	}
+
+	if (CHIP_ID(bp) != CHIP_ID_5706_A0 && CHIP_ID(bp) != CHIP_ID_5706_A1) {
+		if (pci_find_capability(pdev, PCI_CAP_ID_MSI))
+			bp->flags |= MSI_CAP_FLAG;
+	}
+
+	/* 5708 cannot support DMA addresses > 40-bit.  */
+	if (CHIP_NUM(bp) == CHIP_NUM_5708)
+		persist_dma_mask = dma_mask = DMA_40BIT_MASK;
+	else
+		persist_dma_mask = dma_mask = DMA_64BIT_MASK;
+
+	/* Configure DMA attributes. */
+	if (pci_set_dma_mask(pdev, dma_mask) == 0) {
+		dev->features |= NETIF_F_HIGHDMA;
+		rc = pci_set_consistent_dma_mask(pdev, persist_dma_mask);
+		if (rc) {
+			dev_err(&pdev->dev,
+				"pci_set_consistent_dma_mask failed, aborting.\n");
+			goto err_out_unmap;
+		}
+	} else if ((rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK)) != 0) {
+		dev_err(&pdev->dev, "System does not support DMA, aborting.\n");
+		goto err_out_unmap;
+	}
+
+	if (!(bp->flags & PCIE_FLAG))
+		bnx2_get_pci_speed(bp);
+
 	/* 5706A0 may falsely detect SERR and PERR. */
 	if (CHIP_ID(bp) == CHIP_ID_5706_A0) {
 		reg = REG_RD(bp, PCI_COMMAND);
@@ -6005,6 +6397,26 @@
 	return rc;
 }
 
+static char * __devinit
+bnx2_bus_string(struct bnx2 *bp, char *str)
+{
+	char *s = str;
+
+	if (bp->flags & PCIE_FLAG) {
+		s += sprintf(s, "PCI Express");
+	} else {
+		s += sprintf(s, "PCI");
+		if (bp->flags & PCIX_FLAG)
+			s += sprintf(s, "-X");
+		if (bp->flags & PCI_32BIT_FLAG)
+			s += sprintf(s, " 32-bit");
+		else
+			s += sprintf(s, " 64-bit");
+		s += sprintf(s, " %dMHz", bp->bus_speed_mhz);
+	}
+	return str;
+}
+
 static int __devinit
 bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
@@ -6012,6 +6424,7 @@
 	struct net_device *dev = NULL;
 	struct bnx2 *bp;
 	int rc, i;
+	char str[40];
 
 	if (version_printed++ == 0)
 		printk(KERN_INFO "%s", version);
@@ -6052,6 +6465,23 @@
 	dev->poll_controller = poll_bnx2;
 #endif
 
+	pci_set_drvdata(pdev, dev);
+
+	memcpy(dev->dev_addr, bp->mac_addr, 6);
+	memcpy(dev->perm_addr, bp->mac_addr, 6);
+	bp->name = board_info[ent->driver_data].name;
+
+	if (CHIP_NUM(bp) == CHIP_NUM_5709)
+		dev->features |= NETIF_F_HW_CSUM | NETIF_F_SG;
+	else
+		dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
+#ifdef BCM_VLAN
+	dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
+#endif
+	dev->features |= NETIF_F_TSO | NETIF_F_TSO_ECN;
+	if (CHIP_NUM(bp) == CHIP_NUM_5709)
+		dev->features |= NETIF_F_TSO6;
+
 	if ((rc = register_netdev(dev))) {
 		dev_err(&pdev->dev, "Cannot register net device\n");
 		if (bp->regview)
@@ -6063,20 +6493,13 @@
 		return rc;
 	}
 
-	pci_set_drvdata(pdev, dev);
-
-	memcpy(dev->dev_addr, bp->mac_addr, 6);
-	memcpy(dev->perm_addr, bp->mac_addr, 6);
-	bp->name = board_info[ent->driver_data].name,
-	printk(KERN_INFO "%s: %s (%c%d) PCI%s %s %dMHz found at mem %lx, "
+	printk(KERN_INFO "%s: %s (%c%d) %s found at mem %lx, "
 		"IRQ %d, ",
 		dev->name,
 		bp->name,
 		((CHIP_ID(bp) & 0xf000) >> 12) + 'A',
 		((CHIP_ID(bp) & 0x0ff0) >> 4),
-		((bp->flags & PCIX_FLAG) ? "-X" : ""),
-		((bp->flags & PCI_32BIT_FLAG) ? "32-bit" : "64-bit"),
-		bp->bus_speed_mhz,
+		bnx2_bus_string(bp, str),
 		dev->base_addr,
 		bp->pdev->irq);
 
@@ -6085,17 +6508,6 @@
 		printk("%2.2x", dev->dev_addr[i]);
 	printk("\n");
 
-	dev->features |= NETIF_F_SG;
-	if (bp->flags & USING_DAC_FLAG)
-		dev->features |= NETIF_F_HIGHDMA;
-	dev->features |= NETIF_F_IP_CSUM;
-#ifdef BCM_VLAN
-	dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
-#endif
-	dev->features |= NETIF_F_TSO | NETIF_F_TSO_ECN;
-
-	netif_carrier_off(bp->dev);
-
 	return 0;
 }
 
@@ -6140,6 +6552,7 @@
 		reset_code = BNX2_DRV_MSG_CODE_SUSPEND_NO_WOL;
 	bnx2_reset_chip(bp, reset_code);
 	bnx2_free_skbs(bp);
+	pci_save_state(pdev);
 	bnx2_set_power_state(bp, pci_choose_state(pdev, state));
 	return 0;
 }
@@ -6153,6 +6566,7 @@
 	if (!netif_running(dev))
 		return 0;
 
+	pci_restore_state(pdev);
 	bnx2_set_power_state(bp, PCI_D0);
 	netif_device_attach(dev);
 	bnx2_init_nic(bp);
diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h
index 878eee5..bd6288d 100644
--- a/drivers/net/bnx2.h
+++ b/drivers/net/bnx2.h
@@ -1,6 +1,6 @@
 /* bnx2.h: Broadcom NX2 network driver.
  *
- * Copyright (c) 2004, 2005, 2006 Broadcom Corporation
+ * Copyright (c) 2004-2007 Broadcom 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
@@ -24,8 +24,11 @@
 	u32 tx_bd_haddr_hi;
 	u32 tx_bd_haddr_lo;
 	u32 tx_bd_mss_nbytes;
+		#define TX_BD_TCP6_OFF2_SHL		(14)
 	u32 tx_bd_vlan_tag_flags;
 		#define TX_BD_FLAGS_CONN_FAULT		(1<<0)
+		#define TX_BD_FLAGS_TCP6_OFF0_MSK	(3<<1)
+		#define TX_BD_FLAGS_TCP6_OFF0_SHL	(1)
 		#define TX_BD_FLAGS_TCP_UDP_CKSUM	(1<<1)
 		#define TX_BD_FLAGS_IP_CKSUM		(1<<2)
 		#define TX_BD_FLAGS_VLAN_TAG		(1<<3)
@@ -34,6 +37,7 @@
 		#define TX_BD_FLAGS_END			(1<<6)
 		#define TX_BD_FLAGS_START		(1<<7)
 		#define TX_BD_FLAGS_SW_OPTION_WORD	(0x1f<<8)
+		#define TX_BD_FLAGS_TCP6_OFF4_SHL	(12)
 		#define TX_BD_FLAGS_SW_FLAGS		(1<<13)
 		#define TX_BD_FLAGS_SW_SNAP		(1<<14)
 		#define TX_BD_FLAGS_SW_LSO		(1<<15)
@@ -6292,6 +6296,41 @@
 #define MII_BNX2_DSP_ADDRESS			0x17
 #define MII_BNX2_DSP_EXPAND_REG			 0x0f00
 
+#define MII_BNX2_BLK_ADDR			0x1f
+#define MII_BNX2_BLK_ADDR_IEEE0			 0x0000
+#define MII_BNX2_BLK_ADDR_GP_STATUS		 0x8120
+#define MII_BNX2_GP_TOP_AN_STATUS1		  0x1b
+#define MII_BNX2_GP_TOP_AN_SPEED_MSK		   0x3f00
+#define MII_BNX2_GP_TOP_AN_SPEED_10		   0x0000
+#define MII_BNX2_GP_TOP_AN_SPEED_100		   0x0100
+#define MII_BNX2_GP_TOP_AN_SPEED_1G		   0x0200
+#define MII_BNX2_GP_TOP_AN_SPEED_2_5G		   0x0300
+#define MII_BNX2_GP_TOP_AN_SPEED_1GKV		   0x0d00
+#define MII_BNX2_GP_TOP_AN_FD			   0x8
+#define MII_BNX2_BLK_ADDR_SERDES_DIG		 0x8300
+#define MII_BNX2_SERDES_DIG_1000XCTL1		  0x10
+#define MII_BNX2_SD_1000XCTL1_FIBER		   0x01
+#define MII_BNX2_SD_1000XCTL1_AUTODET		   0x10
+#define MII_BNX2_SERDES_DIG_MISC1		  0x18
+#define MII_BNX2_SD_MISC1_FORCE_MSK		   0xf
+#define MII_BNX2_SD_MISC1_FORCE_2_5G		   0x0
+#define MII_BNX2_SD_MISC1_FORCE			   0x10
+#define MII_BNX2_BLK_ADDR_OVER1G		 0x8320
+#define MII_BNX2_OVER1G_UP1			  0x19
+#define MII_BNX2_BLK_ADDR_BAM_NXTPG		 0x8350
+#define MII_BNX2_BAM_NXTPG_CTL			  0x10
+#define MII_BNX2_NXTPG_CTL_BAM			   0x1
+#define MII_BNX2_NXTPG_CTL_T2			   0x2
+#define MII_BNX2_BLK_ADDR_CL73_USERB0		 0x8370
+#define MII_BNX2_CL73_BAM_CTL1			  0x12
+#define MII_BNX2_CL73_BAM_EN			   0x8000
+#define MII_BNX2_CL73_BAM_STA_MGR_EN		   0x4000
+#define MII_BNX2_CL73_BAM_NP_AFT_BP_EN		   0x2000
+#define MII_BNX2_BLK_ADDR_AER			 0xffd0
+#define MII_BNX2_AER_AER			  0x1e
+#define MII_BNX2_AER_AER_AN_MMD			   0x3800
+#define MII_BNX2_BLK_ADDR_COMBO_IEEEB0		 0xffe0
+
 #define MIN_ETHERNET_PACKET_SIZE	60
 #define MAX_ETHERNET_PACKET_SIZE	1514
 #define MAX_ETHERNET_JUMBO_PACKET_SIZE	9014
@@ -6429,13 +6468,15 @@
 	u32 			last_status_idx;
 
 	u32			flags;
-#define PCIX_FLAG			1
-#define PCI_32BIT_FLAG			2
-#define ONE_TDMA_FLAG			4	/* no longer used */
-#define NO_WOL_FLAG			8
-#define USING_DAC_FLAG			0x10
-#define USING_MSI_FLAG			0x20
-#define ASF_ENABLE_FLAG			0x40
+#define PCIX_FLAG			0x00000001
+#define PCI_32BIT_FLAG			0x00000002
+#define ONE_TDMA_FLAG			0x00000004	/* no longer used */
+#define NO_WOL_FLAG			0x00000008
+#define USING_MSI_FLAG			0x00000020
+#define ASF_ENABLE_FLAG			0x00000040
+#define MSI_CAP_FLAG			0x00000080
+#define ONE_SHOT_MSI_FLAG		0x00000100
+#define PCIE_FLAG			0x00000200
 
 	/* Put tx producer and consumer fields in separate cache lines. */
 
@@ -6484,6 +6525,7 @@
 
 	/* Used to synchronize phy accesses. */
 	spinlock_t		phy_lock;
+	spinlock_t		indirect_lock;
 
 	u32			phy_flags;
 #define PHY_SERDES_FLAG			1
@@ -6495,6 +6537,13 @@
 #define PHY_INT_MODE_LINK_READY_FLAG	0x200
 #define PHY_DIS_EARLY_DAC_FLAG		0x400
 
+	u32			mii_bmcr;
+	u32			mii_bmsr;
+	u32			mii_bmsr1;
+	u32			mii_adv;
+	u32			mii_lpa;
+	u32			mii_up1;
+
 	u32			chip_id;
 	/* chip num:16-31, rev:12-15, metal:4-11, bond_id:0-3 */
 #define CHIP_NUM(bp)			(((bp)->chip_id) & 0xffff0000)
diff --git a/drivers/net/bnx2_fw.h b/drivers/net/bnx2_fw.h
index 21d368f..b49f439 100644
--- a/drivers/net/bnx2_fw.h
+++ b/drivers/net/bnx2_fw.h
@@ -15,680 +15,1071 @@
  */
 
 static u8 bnx2_COM_b06FwText[] = {
-	0x1f, 0x8b, 0x08, 0x08, 0x09, 0x83, 0x41, 0x44, 0x00, 0x03, 0x74, 0x65,
-	0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, 0xec, 0x5b, 0x7d, 0x6c,
-	0x5b, 0xd7, 0x75, 0x3f, 0xef, 0xf1, 0x51, 0x7a, 0x96, 0x68, 0xf9, 0x99,
-	0x7e, 0x96, 0x59, 0x4f, 0xb1, 0x49, 0xf1, 0xc9, 0xd2, 0x62, 0x2d, 0x63,
-	0x34, 0x35, 0xd1, 0x3a, 0x26, 0x66, 0x48, 0xda, 0x71, 0x36, 0x67, 0xa0,
-	0x1d, 0x05, 0x51, 0x51, 0xaf, 0xd0, 0x48, 0xd9, 0xcd, 0xb2, 0x0c, 0x73,
-	0x96, 0xb4, 0x70, 0xbc, 0xb4, 0xa1, 0x25, 0x79, 0xf5, 0x06, 0x45, 0xcf,
-	0xb3, 0x34, 0x39, 0xc0, 0x82, 0x41, 0x10, 0x9d, 0x3a, 0x7f, 0x30, 0xa5,
-	0xed, 0x7c, 0x19, 0xe8, 0x12, 0x29, 0xb2, 0x93, 0xb5, 0x43, 0xd0, 0xa6,
-	0x68, 0xff, 0xe8, 0x8a, 0x6e, 0x30, 0x52, 0x0c, 0xf3, 0x3a, 0xa0, 0x30,
-	0xfa, 0xc7, 0xe6, 0x2d, 0x1f, 0xdc, 0xef, 0xdc, 0x77, 0x1f, 0xf9, 0x48,
-	0x51, 0x96, 0x1c, 0x34, 0x5d, 0xb7, 0x99, 0x80, 0xf0, 0xde, 0xbd, 0xf7,
-	0xbc, 0x7b, 0xcf, 0x3d, 0xdf, 0xe7, 0xdc, 0xab, 0x5f, 0x53, 0xa9, 0x85,
-	0xe4, 0x6f, 0x2d, 0xfe, 0xc2, 0x7f, 0xf4, 0xc7, 0xb9, 0xdb, 0x3e, 0x7d,
-	0x5b, 0x1f, 0x5e, 0x07, 0x54, 0xdd, 0xaf, 0x72, 0xbf, 0x0f, 0x7f, 0x26,
-	0xfe, 0xfa, 0xe4, 0x7b, 0xa3, 0x9f, 0x81, 0xbf, 0x2b, 0x18, 0x1c, 0xfe,
-	0x09, 0x91, 0xb2, 0x0c, 0x8c, 0xf7, 0x57, 0x2e, 0x5f, 0x7f, 0x9c, 0x17,
-	0x0e, 0xaf, 0x62, 0x9e, 0x9b, 0xbf, 0x9b, 0xbf, 0x9b, 0xbf, 0x9b, 0xbf,
-	0x9b, 0xbf, 0x9b, 0xbf, 0x9b, 0xbf, 0xff, 0x3f, 0x3f, 0x9f, 0x13, 0x72,
-	0x88, 0x98, 0x85, 0xff, 0x48, 0x57, 0xe3, 0x89, 0xa1, 0xa4, 0x45, 0xba,
-	0x2f, 0x7e, 0x65, 0x28, 0x67, 0x11, 0x25, 0x8a, 0xdb, 0xc3, 0x29, 0xfa,
-	0xb0, 0x9c, 0x37, 0x35, 0xe2, 0xfe, 0x5b, 0xe2, 0x1f, 0x3c, 0xfd, 0xfa,
-	0x9d, 0x91, 0xab, 0xb3, 0x3e, 0xd2, 0x8d, 0xf8, 0xcb, 0xba, 0xb1, 0x8d,
-	0xf4, 0x0e, 0x7c, 0xf3, 0x5c, 0xf7, 0x7f, 0xa8, 0xd4, 0xe6, 0xce, 0x75,
-	0xa5, 0xfc, 0x7a, 0x37, 0xe5, 0x37, 0xc7, 0x75, 0x52, 0xe3, 0x5d, 0x3f,
-	0x48, 0xfa, 0x8c, 0x61, 0x5f, 0xdc, 0xa0, 0xf9, 0x12, 0x65, 0x0e, 0x4c,
-	0xf0, 0x1a, 0xb1, 0x75, 0xf7, 0x62, 0x2e, 0x2d, 0x3e, 0x3c, 0xf4, 0x67,
-	0xd6, 0xd3, 0x65, 0xd5, 0xb2, 0x7a, 0xe6, 0x28, 0x30, 0xf0, 0x7c, 0x3f,
-	0xc6, 0x8b, 0x91, 0x1e, 0xa2, 0x3b, 0x49, 0xb5, 0xf2, 0x01, 0x9f, 0xa5,
-	0x53, 0xb2, 0x64, 0x51, 0xaa, 0x44, 0xf4, 0x77, 0x45, 0x85, 0x9e, 0xb7,
-	0xda, 0x69, 0xae, 0xf7, 0x83, 0x72, 0x02, 0xb8, 0xbc, 0x6d, 0x0d, 0x0f,
-	0x8d, 0x5b, 0x3c, 0x57, 0x7c, 0x9d, 0x83, 0x6f, 0x6f, 0x5b, 0xce, 0xd2,
-	0x68, 0xb4, 0xc8, 0x7d, 0xbd, 0x2d, 0xdc, 0xe7, 0x8f, 0x3f, 0x1c, 0x7c,
-	0xde, 0x0a, 0xc8, 0xbe, 0x1f, 0xa5, 0x92, 0x98, 0x6f, 0xac, 0xc8, 0xb0,
-	0xcf, 0xde, 0x91, 0xb3, 0x4c, 0xd9, 0x6f, 0xc5, 0x93, 0x56, 0x08, 0xfd,
-	0x1d, 0x72, 0x2c, 0xbd, 0x2e, 0x67, 0x59, 0x72, 0xac, 0x88, 0x6f, 0x7a,
-	0x65, 0xff, 0x3b, 0xa9, 0x9c, 0x15, 0x93, 0xfd, 0x57, 0x93, 0x49, 0xab,
-	0x5f, 0xf6, 0x1f, 0xbe, 0x2b, 0x67, 0xc5, 0x65, 0xff, 0xf7, 0x81, 0x8b,
-	0x41, 0xc7, 0x8a, 0x61, 0xfc, 0x25, 0x30, 0xfe, 0x9a, 0x41, 0x6d, 0x19,
-	0x8c, 0x61, 0xef, 0xb6, 0x4e, 0x97, 0x7d, 0x21, 0x7a, 0xbd, 0xfb, 0x32,
-	0x68, 0x63, 0xd0, 0xd9, 0x12, 0x29, 0x99, 0xee, 0x10, 0x68, 0x62, 0xd2,
-	0xb9, 0x52, 0x2b, 0xf9, 0x4e, 0xfa, 0xb0, 0xe7, 0xcf, 0x51, 0xd6, 0xd4,
-	0x69, 0xfd, 0x8c, 0x42, 0x9d, 0x7d, 0x6b, 0x28, 0x61, 0xe4, 0x29, 0xd5,
-	0x8d, 0x28, 0x6e, 0xd2, 0x24, 0x6d, 0x66, 0x71, 0xbd, 0x8a, 0x1e, 0x95,
-	0x22, 0xa1, 0x2c, 0x28, 0x3c, 0x72, 0xfa, 0x5d, 0x8e, 0x39, 0xb1, 0x26,
-	0xff, 0x85, 0x29, 0x35, 0x71, 0x2b, 0x0d, 0x1b, 0x8c, 0x0f, 0x80, 0x05,
-	0x1f, 0x74, 0x25, 0x79, 0x2a, 0x44, 0xc7, 0xec, 0x80, 0x92, 0x3a, 0x75,
-	0x37, 0x25, 0x63, 0x64, 0xaa, 0xd4, 0x25, 0xbe, 0x2d, 0x14, 0x43, 0x34,
-	0x6e, 0x93, 0x92, 0xb4, 0x99, 0x5e, 0xed, 0x18, 0x6f, 0x13, 0xb0, 0xe8,
-	0xeb, 0xf0, 0x51, 0x97, 0x91, 0x22, 0x9d, 0x71, 0x46, 0x7f, 0x50, 0x49,
-	0x8b, 0x39, 0x44, 0x7f, 0x78, 0x8c, 0x02, 0x74, 0xba, 0x68, 0x4a, 0xd8,
-	0x72, 0x39, 0x19, 0x33, 0x00, 0x07, 0xda, 0xd9, 0x26, 0x0d, 0xe3, 0x39,
-	0x6a, 0xf3, 0xfa, 0x21, 0xc8, 0xcc, 0xb7, 0x87, 0xb2, 0xd3, 0x62, 0xbe,
-	0xb0, 0x2f, 0xce, 0xf3, 0x75, 0x00, 0xee, 0x1d, 0xe0, 0xa5, 0x90, 0x26,
-	0x78, 0x95, 0xa0, 0xec, 0x84, 0x02, 0x79, 0xc2, 0x53, 0xd0, 0x2d, 0x0d,
-	0xfc, 0x35, 0xb2, 0xfa, 0x14, 0xca, 0x59, 0x9b, 0x28, 0x6f, 0xa0, 0x5d,
-	0xbc, 0xa0, 0x26, 0xed, 0x66, 0x4a, 0x69, 0x61, 0xec, 0x5f, 0xc8, 0x0a,
-	0x8d, 0xe1, 0x1b, 0xd5, 0x62, 0x98, 0x9f, 0x61, 0xef, 0xc3, 0x82, 0xfe,
-	0x4d, 0xf1, 0xfd, 0x74, 0x69, 0x22, 0xaf, 0x26, 0x4b, 0xed, 0xe4, 0x9b,
-	0x89, 0x40, 0x9a, 0xc7, 0xd5, 0xd4, 0x19, 0x8d, 0xfc, 0x93, 0x0a, 0x41,
-	0x3e, 0x0c, 0x5f, 0xfc, 0xb8, 0xba, 0xb3, 0x74, 0x41, 0x4d, 0x95, 0xf8,
-	0x1b, 0xc0, 0x16, 0x55, 0xd0, 0x96, 0xdf, 0xb7, 0x83, 0x96, 0x34, 0xac,
-	0xc6, 0x75, 0x3d, 0x51, 0x64, 0x99, 0xe5, 0x6f, 0xc1, 0x0f, 0xec, 0xe5,
-	0x9c, 0x0d, 0xfe, 0x08, 0x7e, 0x85, 0xc1, 0xaf, 0x6f, 0x82, 0x5f, 0xfd,
-	0xe0, 0x53, 0x8c, 0xde, 0x28, 0xf5, 0xd2, 0x6b, 0xa5, 0x1e, 0x7a, 0x15,
-	0x32, 0xf9, 0x4a, 0x29, 0x4c, 0x2f, 0x97, 0x3a, 0xe8, 0xa5, 0x52, 0x88,
-	0xce, 0x0b, 0x1e, 0xa6, 0x21, 0xff, 0x82, 0xaf, 0xfa, 0x26, 0xf0, 0xa4,
-	0x1d, 0x3c, 0x59, 0x0f, 0x79, 0xd9, 0x08, 0xf9, 0x9b, 0xee, 0xd6, 0x69,
-	0xaa, 0x9b, 0x12, 0x41, 0xf4, 0x6f, 0x89, 0x6b, 0x82, 0x4e, 0x1a, 0xc6,
-	0xc7, 0x26, 0xfc, 0x94, 0x32, 0x4e, 0xd3, 0x7b, 0x93, 0x1a, 0x8d, 0x95,
-	0xa6, 0x36, 0x3a, 0x7c, 0xe3, 0xf6, 0x2c, 0x5d, 0x44, 0x5f, 0xca, 0x98,
-	0xa5, 0x4b, 0xdb, 0x54, 0x1a, 0x9d, 0xfe, 0x1b, 0x4a, 0x9e, 0x39, 0x4d,
-	0x3f, 0xfe, 0x3a, 0x51, 0x06, 0x34, 0x51, 0xfb, 0x7e, 0x5a, 0x4e, 0x18,
-	0xa0, 0x45, 0x5f, 0xaf, 0x90, 0x08, 0xb5, 0x8f, 0x79, 0x19, 0x86, 0xae,
-	0x68, 0x4a, 0xca, 0x7e, 0x01, 0xfa, 0xd2, 0xaa, 0x24, 0xa7, 0x88, 0x72,
-	0x53, 0x65, 0xca, 0xc5, 0xfc, 0xf4, 0x98, 0x51, 0xa6, 0x74, 0xac, 0x89,
-	0xbe, 0x68, 0xb4, 0xd3, 0x68, 0xef, 0x6f, 0xf8, 0xdc, 0x5c, 0x65, 0xba,
-	0xd4, 0x8f, 0x77, 0xee, 0x23, 0x9a, 0x12, 0xef, 0x4e, 0x7f, 0xbe, 0xe4,
-	0xa7, 0x84, 0x99, 0x0f, 0x69, 0xf4, 0x8e, 0xcf, 0xc1, 0x29, 0xe1, 0x8e,
-	0x81, 0x57, 0xc3, 0xb0, 0x0f, 0x8e, 0x0c, 0x66, 0x27, 0xd6, 0x5c, 0x4b,
-	0x88, 0x6e, 0xc0, 0x0b, 0xd9, 0xd3, 0x18, 0x8f, 0x61, 0x25, 0x6e, 0x52,
-	0xa7, 0xd0, 0x8d, 0x7e, 0xc0, 0x0c, 0x28, 0xfb, 0x4a, 0xcc, 0x6b, 0xbc,
-	0x17, 0x19, 0xd7, 0xcd, 0x80, 0xd5, 0xf0, 0x4c, 0x48, 0x9c, 0xbd, 0x78,
-	0xf2, 0x5c, 0x8c, 0x27, 0x3f, 0x7f, 0xcf, 0x83, 0xe7, 0xe7, 0x2b, 0xef,
-	0x53, 0x9e, 0xf7, 0x7c, 0xe9, 0x4f, 0x03, 0x0e, 0x7e, 0x4c, 0xcf, 0x01,
-	0x1a, 0x9d, 0x38, 0x2c, 0xd7, 0xc2, 0x7b, 0x91, 0xd7, 0x38, 0x0d, 0x3a,
-	0x09, 0xc8, 0x15, 0xd6, 0x3a, 0xec, 0x59, 0xeb, 0x49, 0xcf, 0x5a, 0x4f,
-	0x7a, 0xd6, 0xca, 0x83, 0xb6, 0xb4, 0x4e, 0xb5, 0xfc, 0xd0, 0x51, 0xee,
-	0x39, 0x8e, 0x39, 0x9f, 0x03, 0x5f, 0xbe, 0x0a, 0x98, 0x38, 0x2d, 0xda,
-	0xa0, 0xc7, 0x94, 0x46, 0x7b, 0x4d, 0x7e, 0x7f, 0xb1, 0xd5, 0xc1, 0x8b,
-	0xdf, 0x2f, 0x48, 0x9c, 0x5a, 0x1d, 0xb8, 0xd2, 0x15, 0xa1, 0xff, 0xf3,
-	0x25, 0xd6, 0x4f, 0x8a, 0xf9, 0x2c, 0x3a, 0x94, 0x8e, 0xb5, 0xd3, 0x98,
-	0xa1, 0xc4, 0x46, 0x7b, 0x9a, 0x99, 0x8e, 0x09, 0xd5, 0x6a, 0x85, 0x0e,
-	0x50, 0x58, 0x65, 0xdb, 0x25, 0xf0, 0x7b, 0x49, 0xe2, 0x61, 0x70, 0x3b,
-	0xa3, 0x5a, 0xc1, 0xba, 0x7e, 0x96, 0xdf, 0x57, 0xf0, 0xce, 0x32, 0x9c,
-	0xd4, 0x9c, 0xb5, 0x5f, 0x45, 0x9b, 0xed, 0xce, 0x66, 0xd9, 0x76, 0xc7,
-	0xff, 0xa0, 0xa9, 0xb6, 0xfd, 0x05, 0xb3, 0xb6, 0xed, 0xea, 0x82, 0xd7,
-	0x66, 0xf1, 0xde, 0xc2, 0xe4, 0xb3, 0x58, 0x8e, 0xfc, 0xc0, 0x35, 0x06,
-	0x3d, 0x6c, 0x96, 0x38, 0x7c, 0x4b, 0xe2, 0x00, 0x5c, 0x01, 0x37, 0x5a,
-	0xe2, 0x6f, 0x04, 0x4b, 0xea, 0xda, 0x4c, 0x43, 0xf7, 0x7d, 0xad, 0x18,
-	0xbf, 0xec, 0xe3, 0x75, 0xdc, 0x27, 0x29, 0x69, 0xe8, 0xc9, 0xd8, 0xb4,
-	0x46, 0xd9, 0xd8, 0x26, 0x21, 0xd7, 0xd9, 0x58, 0xd5, 0x06, 0x8c, 0x4e,
-	0xd4, 0xdb, 0x00, 0xfe, 0x8e, 0x6d, 0x80, 0xa3, 0xfb, 0x63, 0xd3, 0x6c,
-	0x0b, 0x1c, 0xdd, 0x3f, 0x36, 0xc1, 0x36, 0x41, 0xcc, 0x09, 0xfd, 0x67,
-	0x3b, 0xe0, 0xda, 0x00, 0xfe, 0x86, 0x6d, 0x80, 0x0f, 0xf2, 0xcd, 0xf3,
-	0xb9, 0x6b, 0x8f, 0xd7, 0xcd, 0x3b, 0xce, 0xb6, 0x45, 0xd9, 0xd9, 0xcd,
-	0x30, 0xc7, 0xb1, 0x76, 0x80, 0x0a, 0xd3, 0xcc, 0xc3, 0x48, 0xe8, 0x08,
-	0x1d, 0x17, 0x36, 0xef, 0xf4, 0x04, 0x25, 0x0e, 0x9e, 0x18, 0xa0, 0x34,
-	0x6c, 0xc0, 0xdc, 0xc4, 0xb5, 0x32, 0xf8, 0x78, 0x47, 0x13, 0x59, 0xb0,
-	0x75, 0xf0, 0x93, 0xfd, 0x7e, 0xf2, 0xc5, 0xe3, 0x90, 0xb7, 0x98, 0xf0,
-	0x5d, 0xd5, 0x9f, 0xa6, 0xed, 0xaa, 0x69, 0x37, 0xc1, 0x3f, 0x62, 0xde,
-	0xfe, 0x98, 0x90, 0x4d, 0xef, 0x2f, 0x09, 0x1b, 0x94, 0x8c, 0x7d, 0x08,
-	0xf9, 0x75, 0x69, 0xe4, 0xea, 0x1f, 0xdb, 0xfa, 0x2b, 0x1e, 0x1f, 0xb2,
-	0x05, 0x76, 0xdf, 0x84, 0x3c, 0xb9, 0x76, 0x9f, 0xed, 0x71, 0x88, 0x6d,
-	0x26, 0xf4, 0x8d, 0x6d, 0x70, 0x80, 0xd4, 0x19, 0x4d, 0xda, 0x69, 0x5d,
-	0xda, 0xe9, 0x00, 0x6c, 0x34, 0xb7, 0x0d, 0xd9, 0x36, 0x45, 0x1b, 0xf6,
-	0x1a, 0xf6, 0x70, 0x77, 0x3a, 0x35, 0xc1, 0xfe, 0x10, 0xbe, 0x7b, 0x86,
-	0x75, 0xf8, 0xdb, 0x43, 0x23, 0xd3, 0xc2, 0x07, 0xb0, 0xff, 0x80, 0x65,
-	0x66, 0x1b, 0xce, 0xb6, 0x1c, 0xfb, 0x2e, 0x62, 0xdd, 0x8a, 0xad, 0x64,
-	0x39, 0xf1, 0xe2, 0xc5, 0x38, 0xad, 0x21, 0xf5, 0xa4, 0x43, 0x6b, 0x35,
-	0xfe, 0xa8, 0x46, 0x2d, 0x4c, 0x63, 0xc6, 0x7f, 0x2b, 0x70, 0xe6, 0x7d,
-	0xfd, 0x4f, 0xe0, 0xcc, 0xeb, 0xd6, 0xe3, 0x4d, 0x7a, 0x6b, 0xfc, 0xac,
-	0xfe, 0xf0, 0x33, 0xa4, 0x37, 0xc7, 0xcf, 0xd2, 0xbf, 0x58, 0x74, 0x9f,
-	0x0e, 0x3f, 0xdb, 0xad, 0xc0, 0xcf, 0x16, 0xa1, 0xef, 0x53, 0x3a, 0x1d,
-	0x3c, 0x15, 0xc9, 0xfc, 0x2b, 0x45, 0x61, 0x3f, 0x76, 0xd0, 0xc8, 0x94,
-	0x42, 0x7a, 0x17, 0xb5, 0xc3, 0x7f, 0xf4, 0x37, 0x61, 0xfe, 0x5d, 0x44,
-	0x9b, 0x1d, 0xbf, 0xd9, 0x15, 0x1e, 0x05, 0xff, 0xd3, 0x2f, 0x7e, 0x05,
-	0xdf, 0x3c, 0x4d, 0x07, 0xa7, 0x0e, 0x2b, 0x39, 0xfb, 0x08, 0xe0, 0x97,
-	0x83, 0xd5, 0x01, 0x9b, 0x07, 0xec, 0x97, 0x31, 0xef, 0xd3, 0xa4, 0xdf,
-	0x1e, 0x19, 0x48, 0x28, 0xc0, 0xe3, 0x45, 0x01, 0x2f, 0x7d, 0x71, 0x97,
-	0xb1, 0x53, 0xf0, 0x3f, 0x40, 0xef, 0x15, 0x2f, 0x80, 0xbe, 0xbd, 0xf0,
-	0x39, 0x91, 0x67, 0x61, 0x93, 0xe1, 0x8f, 0x22, 0x57, 0x31, 0x2d, 0x7c,
-	0x11, 0x29, 0x0f, 0x76, 0xa7, 0x41, 0xef, 0x38, 0xfc, 0xd3, 0x00, 0xfc,
-	0x53, 0x0c, 0xbe, 0xa9, 0x07, 0x7e, 0xc9, 0x82, 0x5f, 0x0a, 0x83, 0x1f,
-	0x06, 0xcd, 0xc2, 0x47, 0xcd, 0x42, 0xfe, 0xe7, 0x66, 0x48, 0x19, 0x04,
-	0xad, 0xcf, 0xc1, 0x3f, 0x26, 0x63, 0x77, 0x42, 0xcf, 0x22, 0x17, 0x66,
-	0xd5, 0x41, 0xca, 0xc1, 0x9f, 0x77, 0x6e, 0x8b, 0x62, 0xbd, 0x26, 0x4a,
-	0x84, 0x5c, 0x1d, 0xe5, 0xdf, 0x7e, 0x85, 0xac, 0x7f, 0x06, 0xef, 0x22,
-	0x61, 0xa2, 0x3d, 0x94, 0xb5, 0xa3, 0x46, 0xa7, 0xda, 0x03, 0x18, 0x6e,
-	0x87, 0x95, 0x03, 0x53, 0x11, 0x05, 0xfb, 0x03, 0xcd, 0x27, 0x60, 0xeb,
-	0xcb, 0x34, 0x1e, 0x63, 0x3d, 0x29, 0xd3, 0xf3, 0xb1, 0xc8, 0x40, 0x9e,
-	0x5a, 0xe9, 0x98, 0x39, 0x21, 0x7c, 0xbc, 0x16, 0x3f, 0x21, 0x74, 0x2c,
-	0x67, 0xe1, 0x59, 0xec, 0x54, 0xb2, 0x53, 0xbc, 0x7e, 0x14, 0x5a, 0xee,
-	0xc7, 0x93, 0xe7, 0x07, 0xdd, 0xfa, 0x49, 0x39, 0xd8, 0x9d, 0x87, 0x77,
-	0x88, 0x18, 0x8b, 0x58, 0x39, 0x35, 0x11, 0x0d, 0x45, 0x55, 0x8d, 0x86,
-	0x35, 0x85, 0x46, 0x61, 0x6f, 0xd2, 0xb1, 0xff, 0x2c, 0x1f, 0x33, 0x79,
-	0xbc, 0x99, 0xbe, 0x2a, 0xfc, 0x0d, 0xd6, 0x2e, 0x4c, 0x63, 0x5d, 0x3f,
-	0xf8, 0xcb, 0xeb, 0xf2, 0x3c, 0x68, 0xc3, 0xf6, 0x6b, 0x56, 0xe4, 0xd9,
-	0x3c, 0xed, 0x00, 0x6d, 0xd9, 0x66, 0xc1, 0x3e, 0x0c, 0x60, 0xed, 0x5e,
-	0xd8, 0x4f, 0x3c, 0x93, 0xbd, 0x1c, 0x07, 0x05, 0x68, 0xd8, 0x64, 0x79,
-	0xd4, 0xe5, 0x98, 0xe9, 0x19, 0xf3, 0xcb, 0xb1, 0x20, 0xfe, 0xe0, 0x7f,
-	0x4d, 0x96, 0x19, 0x6e, 0x73, 0x4c, 0xc6, 0x34, 0x09, 0xd3, 0xdc, 0x64,
-	0x02, 0x34, 0x8b, 0x9c, 0x4d, 0x10, 0xd3, 0x0c, 0x46, 0x7b, 0x7f, 0x82,
-	0xbe, 0x64, 0xaf, 0xf7, 0x3b, 0xb6, 0xb0, 0x55, 0x49, 0xc1, 0x17, 0xa8,
-	0x56, 0x0b, 0x7c, 0x45, 0x98, 0x5e, 0x15, 0xb0, 0x64, 0xa8, 0xf1, 0x68,
-	0xe8, 0x4b, 0x74, 0xab, 0xb0, 0x11, 0x09, 0xc3, 0x4b, 0xe3, 0xff, 0x52,
-	0xc9, 0x72, 0xbf, 0x69, 0xa5, 0xec, 0x20, 0xf3, 0x89, 0xd7, 0x33, 0x68,
-	0xae, 0xe4, 0xbc, 0xfb, 0x10, 0xa3, 0x16, 0x60, 0x6b, 0xce, 0x4f, 0xaa,
-	0xf4, 0xf8, 0x1d, 0xf0, 0x65, 0xb1, 0x6d, 0x58, 0xcb, 0xc4, 0x78, 0x1e,
-	0x6d, 0x15, 0x6d, 0xe8, 0x99, 0x11, 0x02, 0x8f, 0xb9, 0x9f, 0xe1, 0x4c,
-	0xfc, 0xbd, 0xcf, 0xb1, 0x75, 0x3e, 0xab, 0xde, 0x4a, 0x14, 0x64, 0x7a,
-	0xc5, 0x40, 0x2b, 0xcb, 0x50, 0xd5, 0x6d, 0xc2, 0x5f, 0x3b, 0xb6, 0xc4,
-	0x82, 0x2e, 0xc2, 0xe6, 0xf6, 0x79, 0x75, 0x91, 0xe3, 0x09, 0x57, 0x17,
-	0x23, 0xa1, 0x84, 0x0a, 0x5b, 0xdc, 0xa7, 0xd1, 0x09, 0xd1, 0x56, 0x28,
-	0x31, 0x18, 0x09, 0x2d, 0xa8, 0x1c, 0x4b, 0x33, 0x6c, 0x18, 0xf1, 0x4a,
-	0x40, 0xc2, 0x22, 0x9e, 0xb3, 0xdd, 0x98, 0x30, 0x84, 0x7e, 0x53, 0xf4,
-	0x1f, 0xab, 0xe8, 0xa8, 0x13, 0xff, 0xa9, 0x88, 0x11, 0x0b, 0x88, 0x11,
-	0x53, 0x42, 0x47, 0x8d, 0x04, 0x72, 0x04, 0xd0, 0xdc, 0xd1, 0xcf, 0x42,
-	0x91, 0x71, 0xc9, 0xb1, 0x5c, 0x0e, 0x00, 0x99, 0x13, 0x8e, 0x7d, 0xa4,
-	0x3c, 0xc7, 0x91, 0xa3, 0xea, 0x53, 0x34, 0x5c, 0x60, 0x3f, 0x8e, 0x3f,
-	0x9b, 0x6d, 0x2d, 0xec, 0xa3, 0xf0, 0xc5, 0x51, 0xf0, 0x39, 0x0f, 0x1a,
-	0xac, 0x97, 0x74, 0xdd, 0x4f, 0x07, 0xec, 0x3d, 0xa0, 0x79, 0x9c, 0x46,
-	0x4e, 0x8d, 0xb0, 0xcc, 0xf6, 0x14, 0x28, 0xd2, 0x73, 0x8c, 0xb6, 0x1b,
-	0x73, 0x2c, 0xdf, 0x83, 0xe5, 0x1d, 0xe0, 0x85, 0xd0, 0x51, 0xc8, 0x20,
-	0x65, 0x0b, 0x23, 0xf4, 0x58, 0x89, 0xfb, 0xf2, 0xa0, 0x1d, 0xe2, 0xda,
-	0xfe, 0xfd, 0x52, 0xce, 0x31, 0x9f, 0xe6, 0xce, 0x37, 0x22, 0xe7, 0x63,
-	0x38, 0x86, 0xe1, 0x6f, 0xaa, 0xf3, 0xee, 0x14, 0x3c, 0x8d, 0x18, 0x5d,
-	0x6a, 0x79, 0x87, 0x1f, 0xe3, 0xcf, 0xf7, 0xf3, 0x3b, 0xe6, 0x81, 0xef,
-	0x6f, 0xb6, 0xf6, 0x00, 0x76, 0x10, 0x73, 0xfa, 0xa9, 0xb3, 0xdd, 0xc5,
-	0x37, 0x81, 0xb5, 0xd9, 0xcf, 0x31, 0x9f, 0x1f, 0xa1, 0xec, 0xa9, 0x7c,
-	0x8f, 0x0a, 0x19, 0x9b, 0xcd, 0x28, 0xe4, 0xb7, 0x1e, 0xa6, 0xdc, 0xa9,
-	0xa3, 0x6c, 0x37, 0x40, 0xab, 0x3d, 0xb4, 0x6b, 0x22, 0xd2, 0x73, 0x80,
-	0x34, 0xb1, 0xce, 0x5b, 0x24, 0xe8, 0x1f, 0x9b, 0x15, 0xbe, 0x20, 0x43,
-	0xe9, 0x89, 0xed, 0xa1, 0x4b, 0xe8, 0x1b, 0x1e, 0x8c, 0x84, 0x17, 0xe8,
-	0x09, 0xd0, 0xe5, 0x23, 0xf8, 0x22, 0xab, 0x67, 0x0c, 0x3a, 0x84, 0x9c,
-	0x0a, 0xeb, 0x8f, 0x4a, 0xda, 0xe0, 0xbb, 0xcc, 0x51, 0xd0, 0x8f, 0xf2,
-	0x0e, 0x4d, 0x99, 0x9e, 0x4c, 0xcb, 0xaf, 0xc0, 0xf6, 0x1c, 0x11, 0xb1,
-	0x4b, 0x56, 0xd0, 0xee, 0xd2, 0x06, 0x47, 0x0e, 0x60, 0x8b, 0x30, 0xef,
-	0xe5, 0x41, 0x85, 0xb6, 0x20, 0x4e, 0x3f, 0x24, 0x78, 0xeb, 0xa3, 0x7d,
-	0x66, 0xd4, 0xd8, 0x47, 0xf3, 0x7e, 0x27, 0x56, 0xc0, 0x3c, 0x3d, 0xf7,
-	0x60, 0x0f, 0x90, 0x53, 0xfb, 0xeb, 0xeb, 0xa8, 0x2d, 0x12, 0x4e, 0xa8,
-	0x09, 0xfa, 0x93, 0xd2, 0xdd, 0xe4, 0xe8, 0x77, 0x2b, 0xdb, 0x7e, 0xf0,
-	0xb0, 0xd3, 0x69, 0x5b, 0x78, 0x16, 0x3a, 0xb1, 0x1e, 0xe3, 0xfe, 0xac,
-	0xc0, 0x7d, 0x84, 0xba, 0xa1, 0x6b, 0x22, 0x8f, 0x39, 0x51, 0x8b, 0x17,
-	0xf3, 0xbc, 0x9e, 0xcf, 0x5f, 0xc6, 0x3c, 0xdc, 0xcf, 0x70, 0x78, 0x2f,
-	0x3c, 0x41, 0x23, 0x90, 0xc7, 0x5c, 0x7f, 0x57, 0x68, 0x0c, 0xdf, 0xa4,
-	0x4a, 0x4d, 0x74, 0x54, 0xe3, 0xf1, 0x48, 0x38, 0xaf, 0x1e, 0x42, 0xdc,
-	0xf3, 0xb8, 0xea, 0xb7, 0x7e, 0xe6, 0x67, 0xbf, 0xe3, 0xb7, 0xae, 0x29,
-	0xd5, 0xb9, 0x10, 0x87, 0x8a, 0xdc, 0x60, 0x41, 0x19, 0x2c, 0x5d, 0x52,
-	0x92, 0x85, 0x6b, 0x4a, 0xaa, 0xc4, 0x30, 0x8e, 0xce, 0x67, 0xcf, 0x74,
-	0x82, 0x4e, 0x1f, 0x89, 0xef, 0xe6, 0x7a, 0x8f, 0x50, 0xea, 0xd4, 0xad,
-	0x94, 0x9e, 0xe6, 0xbc, 0x34, 0x02, 0x7c, 0x3f, 0x2a, 0xe7, 0x62, 0x41,
-	0xca, 0x9d, 0xe1, 0x31, 0xb6, 0x5f, 0xd6, 0xd5, 0x45, 0x1f, 0xef, 0x9f,
-	0xf9, 0x6f, 0x52, 0xc1, 0x7e, 0x53, 0xd2, 0x8f, 0xdf, 0x7d, 0x9c, 0x93,
-	0xe1, 0xf7, 0x6f, 0x86, 0xd3, 0xb7, 0x95, 0x16, 0x36, 0xdc, 0xc8, 0x3e,
-	0x57, 0xb3, 0xc7, 0x47, 0x7d, 0x7e, 0x6b, 0x7b, 0x13, 0xb5, 0x84, 0x80,
-	0xc3, 0x4a, 0x7b, 0x64, 0x98, 0x5f, 0x87, 0x1c, 0xb0, 0x4d, 0xd9, 0x0d,
-	0x7e, 0x5a, 0x6c, 0xc3, 0x60, 0x93, 0x76, 0x53, 0xae, 0xc4, 0xb2, 0x1d,
-	0x35, 0x32, 0x90, 0xb1, 0x34, 0x75, 0xb1, 0x1e, 0xb9, 0xba, 0x07, 0xdb,
-	0x9d, 0x87, 0xed, 0x46, 0x3c, 0x64, 0x53, 0xbe, 0x29, 0xce, 0x36, 0xbc,
-	0x0b, 0xb2, 0x85, 0xbe, 0x62, 0x55, 0x17, 0x77, 0x2d, 0xc1, 0x5d, 0x5b,
-	0xc2, 0xa3, 0x02, 0xd5, 0xe2, 0x3f, 0x4b, 0x8c, 0xff, 0x5f, 0x00, 0xff,
-	0xcf, 0x01, 0x7f, 0xc6, 0xa9, 0x31, 0xfe, 0x3b, 0x2b, 0xf8, 0x33, 0x0c,
-	0xfc, 0x1c, 0x64, 0xf1, 0x0d, 0xe8, 0xe2, 0x6b, 0x36, 0x7c, 0x9d, 0x0d,
-	0xff, 0x67, 0xc3, 0xdf, 0xd9, 0xf0, 0x8b, 0x36, 0x7c, 0x1e, 0xf6, 0x74,
-	0x0e, 0x36, 0xe9, 0xac, 0x9d, 0x34, 0x58, 0x9f, 0x92, 0x31, 0xf6, 0x9d,
-	0xbb, 0x65, 0xde, 0x1d, 0x92, 0x71, 0xf7, 0xa7, 0x64, 0x2c, 0x7b, 0x00,
-	0xb1, 0xec, 0x66, 0x1a, 0xed, 0xe1, 0x9c, 0xa4, 0x05, 0xcf, 0x75, 0x78,
-	0x22, 0x6e, 0xed, 0x49, 0x48, 0xbd, 0xfc, 0x0c, 0x62, 0x5c, 0xd8, 0xff,
-	0x1e, 0xe4, 0x37, 0x19, 0xc4, 0x6a, 0x56, 0x1f, 0xc7, 0xe5, 0xb0, 0x65,
-	0xef, 0x37, 0x39, 0x76, 0xfe, 0x2e, 0x19, 0x03, 0xbb, 0xed, 0x56, 0xc0,
-	0xa4, 0xd1, 0xd7, 0x8a, 0x6f, 0x7e, 0x07, 0xb2, 0xdf, 0x86, 0xf6, 0xce,
-	0x3a, 0x18, 0xe4, 0xb3, 0x56, 0x16, 0x7d, 0x11, 0xc0, 0xb4, 0x61, 0x9d,
-	0x0e, 0xb4, 0xf7, 0xa0, 0x7d, 0x8b, 0xb3, 0x8e, 0xf1, 0x2b, 0x68, 0xa7,
-	0xea, 0xbe, 0xd9, 0x8a, 0xbe, 0x4c, 0x5d, 0xdf, 0x9b, 0xe8, 0x4b, 0xa2,
-	0x6f, 0x51, 0x7e, 0x97, 0x47, 0x3b, 0x52, 0x07, 0xb3, 0x88, 0x3e, 0xc6,
-	0xf1, 0x5b, 0x78, 0xde, 0x47, 0xa3, 0x19, 0x8e, 0x03, 0xdc, 0xb1, 0xdc,
-	0x7a, 0x6a, 0xe3, 0xdc, 0xf7, 0x43, 0x21, 0x3b, 0xf3, 0xd2, 0x46, 0xa7,
-	0x27, 0xd8, 0x4f, 0x8c, 0x20, 0xee, 0xe1, 0x71, 0xe1, 0x9c, 0x3c, 0xfd,
-	0x1f, 0x00, 0xf6, 0x61, 0x8c, 0x21, 0x56, 0xb7, 0xcb, 0x4d, 0x8d, 0xc7,
-	0x1f, 0xc5, 0xf8, 0x5f, 0xca, 0x6f, 0x2b, 0x73, 0x03, 0xfe, 0x1b, 0x75,
-	0x7d, 0x6a, 0xb0, 0xb6, 0xbd, 0xd6, 0xf3, 0xbe, 0x4d, 0x5f, 0xfa, 0xfd,
-	0x48, 0x1d, 0xfc, 0xef, 0x6e, 0xa8, 0x6d, 0x3f, 0xc5, 0xdf, 0x20, 0x87,
-	0x70, 0xdb, 0x09, 0xc8, 0x1d, 0xdb, 0xa4, 0xfa, 0x79, 0x3e, 0x6b, 0xd4,
-	0xf6, 0x6d, 0x32, 0x6b, 0xdb, 0x1c, 0x27, 0x31, 0x5c, 0x08, 0xf2, 0xde,
-	0xa1, 0xec, 0xb2, 0x7f, 0x13, 0xe3, 0x61, 0xe5, 0x5e, 0xdb, 0x8b, 0x67,
-	0x48, 0xe6, 0x46, 0xe1, 0x4a, 0xcc, 0x3b, 0x5f, 0x0a, 0x40, 0xae, 0x3e,
-	0x0f, 0x9e, 0x73, 0xdc, 0x53, 0xd5, 0xf1, 0xf7, 0x68, 0x39, 0x1d, 0x67,
-	0x1f, 0xc0, 0x31, 0xfe, 0x36, 0x11, 0x1f, 0xfb, 0xe2, 0x4f, 0x70, 0x0c,
-	0xf6, 0xb4, 0xe3, 0x5b, 0x2c, 0xf8, 0x43, 0xb4, 0x4b, 0x7e, 0xc7, 0x6e,
-	0x22, 0x9f, 0xc8, 0x16, 0xd8, 0x9f, 0xb1, 0x0f, 0x89, 0xc0, 0x4e, 0xb3,
-	0x1f, 0xfd, 0x24, 0x7d, 0xc6, 0x5d, 0xcd, 0x6c, 0xfb, 0x34, 0xeb, 0x05,
-	0xc4, 0x0b, 0x1c, 0xe7, 0xb1, 0xed, 0xc6, 0x7b, 0xd1, 0x8d, 0x57, 0xee,
-	0xd7, 0xc8, 0xaa, 0xfa, 0x11, 0x67, 0x8f, 0x5b, 0x59, 0x37, 0x56, 0xb1,
-	0xef, 0xc6, 0xb6, 0xed, 0xc7, 0x75, 0xb6, 0xe1, 0xb2, 0xb0, 0x0d, 0x0f,
-	0x6a, 0x7e, 0xeb, 0xf7, 0x9b, 0x1d, 0x79, 0x6d, 0x6c, 0x1b, 0xee, 0xad,
-	0xd8, 0x06, 0x57, 0x5e, 0xbd, 0x79, 0xeb, 0x0f, 0xc0, 0x1b, 0x0b, 0xbc,
-	0xa9, 0xaf, 0xd5, 0x70, 0x8e, 0xe2, 0x87, 0x1f, 0xe2, 0x18, 0x91, 0x73,
-	0xd9, 0x18, 0xe5, 0x62, 0x45, 0xc4, 0x6a, 0x91, 0xd9, 0xd9, 0x4a, 0x8e,
-	0xf5, 0x35, 0x69, 0xbb, 0x6b, 0xe2, 0x22, 0x7a, 0xbc, 0x78, 0x09, 0xf8,
-	0x73, 0xbc, 0xa5, 0x49, 0x1b, 0xc1, 0xfd, 0xe3, 0x12, 0x47, 0x7e, 0xe7,
-	0x3a, 0x1e, 0x7c, 0x69, 0xf1, 0x47, 0xe0, 0x15, 0xc7, 0x7d, 0x51, 0x27,
-	0xde, 0xab, 0x89, 0xa9, 0xd7, 0xf8, 0xc9, 0xe2, 0x78, 0x89, 0x61, 0x74,
-	0x19, 0x2f, 0x05, 0x64, 0x5e, 0x63, 0xc8, 0x3c, 0x87, 0x63, 0x6d, 0xae,
-	0xb1, 0xd6, 0xc7, 0x50, 0x0b, 0x43, 0xc1, 0x6d, 0xcc, 0x13, 0x8e, 0xa1,
-	0xda, 0x28, 0x39, 0xe3, 0xc4, 0x50, 0x4e, 0x9d, 0xcd, 0xcd, 0x71, 0x5c,
-	0x5c, 0xd9, 0x0f, 0xef, 0xc0, 0x3e, 0x45, 0x9e, 0x14, 0x74, 0xea, 0x7f,
-	0x1a, 0xec, 0xf6, 0x51, 0xf4, 0x8f, 0xba, 0xfd, 0x9e, 0x5c, 0xc3, 0xc5,
-	0x85, 0x7d, 0xbd, 0x1b, 0xd3, 0xed, 0x96, 0x31, 0x1d, 0x62, 0x18, 0xdb,
-	0xc9, 0xbb, 0xf6, 0x16, 0x33, 0xe8, 0xe3, 0x75, 0x11, 0x1b, 0x12, 0xc7,
-	0x49, 0x90, 0xaf, 0xfd, 0x91, 0x50, 0x58, 0xad, 0xc7, 0xab, 0x75, 0xa1,
-	0x16, 0xaf, 0x41, 0xf1, 0xdd, 0xf8, 0x92, 0xef, 0x48, 0xc4, 0x92, 0xe3,
-	0xf6, 0x10, 0xe8, 0xc5, 0xf8, 0xb9, 0xba, 0xe1, 0xc6, 0xc9, 0x8c, 0xd3,
-	0x3f, 0x82, 0xc6, 0xbb, 0x15, 0xfe, 0x7e, 0xcc, 0xde, 0x2f, 0xe8, 0x96,
-	0x15, 0xb8, 0x0e, 0x7b, 0x70, 0x1d, 0x91, 0xb8, 0xb2, 0x2e, 0xb0, 0x7e,
-	0x78, 0x6b, 0x9a, 0xa6, 0xd8, 0x1b, 0x70, 0x0e, 0xf3, 0xb9, 0xb9, 0x6a,
-	0x2d, 0x0c, 0xf9, 0xb6, 0xc1, 0x1f, 0x02, 0xd7, 0xac, 0x88, 0x43, 0x03,
-	0x0b, 0xf5, 0x34, 0x1c, 0xc7, 0x5a, 0x88, 0xdb, 0x81, 0x8f, 0xcb, 0xf3,
-	0x26, 0x89, 0xcf, 0x37, 0xc5, 0xdc, 0x63, 0xa2, 0x06, 0xea, 0xd3, 0x39,
-	0x77, 0xc9, 0x0a, 0xde, 0x69, 0x92, 0x77, 0x8f, 0x56, 0xf0, 0x73, 0x78,
-	0x1c, 0x90, 0x74, 0xe5, 0xdc, 0x95, 0x75, 0x5a, 0xf0, 0xa7, 0x9d, 0x73,
-	0xd3, 0x41, 0x6a, 0x14, 0x23, 0x2f, 0x0c, 0xa9, 0xdb, 0x1c, 0x3a, 0x3a,
-	0x31, 0xf2, 0xda, 0xba, 0x18, 0xf9, 0xb6, 0x20, 0xc7, 0x5a, 0xc3, 0x50,
-	0x82, 0x79, 0xf8, 0xba, 0x97, 0x6d, 0xc8, 0x36, 0x70, 0x3d, 0x5f, 0x53,
-	0xbb, 0xec, 0x59, 0xa6, 0xd6, 0x1c, 0x20, 0xdf, 0x0c, 0xfb, 0x0e, 0x0b,
-	0x79, 0x06, 0x91, 0x36, 0xc9, 0x3a, 0xcb, 0xbe, 0xbd, 0x1a, 0x67, 0xcf,
-	0x51, 0xa3, 0x18, 0xfb, 0x46, 0xfd, 0xfa, 0x79, 0xbf, 0xdf, 0x3a, 0xac,
-	0x3b, 0x36, 0x73, 0x25, 0xbf, 0xee, 0xc2, 0xed, 0x41, 0x9c, 0xad, 0x50,
-	0x93, 0x55, 0xc0, 0xfe, 0xde, 0xf0, 0x37, 0x5b, 0xae, 0x2e, 0x06, 0x68,
-	0xfd, 0xcc, 0x2d, 0x42, 0x1f, 0x8d, 0xc9, 0xaa, 0x3e, 0x8e, 0x82, 0x37,
-	0x19, 0xa7, 0x06, 0x60, 0xae, 0xa7, 0xeb, 0xd7, 0x0b, 0xc6, 0xed, 0x37,
-	0xfd, 0xaa, 0xe5, 0xca, 0xc0, 0xf5, 0xf2, 0x91, 0x4f, 0xd5, 0xd1, 0xba,
-	0x51, 0x4d, 0xf8, 0x2c, 0xe8, 0x1a, 0x47, 0xde, 0x1d, 0x79, 0x81, 0x10,
-	0x3b, 0x39, 0x79, 0x78, 0x1a, 0xb9, 0x77, 0xe4, 0x02, 0xe7, 0xe3, 0x6e,
-	0x7e, 0xfe, 0x6a, 0x29, 0x72, 0x36, 0x8f, 0x9c, 0x79, 0x1e, 0x39, 0xf9,
-	0xcb, 0xc8, 0xc9, 0xcf, 0x97, 0x7a, 0x41, 0xff, 0x1e, 0x99, 0x8f, 0xb3,
-	0x8e, 0x99, 0x74, 0x11, 0xb9, 0xd3, 0x77, 0x67, 0xd8, 0x46, 0x74, 0xd1,
-	0x3d, 0xc8, 0x35, 0xbe, 0x3f, 0xa9, 0x68, 0x9d, 0x7d, 0x01, 0x5f, 0xc2,
-	0xb8, 0x91, 0x38, 0x71, 0x29, 0x4f, 0x1a, 0xc7, 0x8a, 0x23, 0x4d, 0x7e,
-	0x6b, 0xae, 0x95, 0x5a, 0xf6, 0x2c, 0xcb, 0x93, 0x6a, 0xac, 0xe8, 0xc2,
-	0x19, 0xd4, 0xd9, 0xf7, 0x87, 0x9c, 0xdb, 0xc4, 0x48, 0xe4, 0xd3, 0xeb,
-	0xe8, 0xed, 0x93, 0x65, 0xda, 0x19, 0xbb, 0x56, 0xbe, 0x68, 0xad, 0xa3,
-	0x6c, 0xef, 0x43, 0x32, 0x97, 0x5c, 0x78, 0x28, 0x69, 0xe5, 0x43, 0x3e,
-	0xf7, 0x7c, 0x62, 0x42, 0x47, 0x84, 0xc8, 0xbf, 0x20, 0xcd, 0x0d, 0x20,
-	0x71, 0x6e, 0xd9, 0xfe, 0x02, 0x1f, 0x10, 0xb1, 0x6d, 0x9c, 0x33, 0x03,
-	0xa2, 0xd6, 0xb6, 0xd1, 0xe2, 0x7e, 0x03, 0xfc, 0xbe, 0x8f, 0xe6, 0x90,
-	0x43, 0x14, 0x44, 0x1e, 0xde, 0x0e, 0x78, 0x37, 0x0f, 0xbf, 0x1f, 0xb9,
-	0x01, 0xd3, 0xd8, 0x04, 0xfc, 0x6f, 0x03, 0xc6, 0x6b, 0x43, 0x9f, 0x6b,
-	0x22, 0xf1, 0x3d, 0x8f, 0xb7, 0x13, 0xd7, 0x65, 0xab, 0xf3, 0xf2, 0x9c,
-	0x3c, 0xf6, 0x61, 0xf9, 0xf6, 0xbe, 0x3e, 0xcf, 0xdc, 0x6d, 0x9e, 0xb9,
-	0xef, 0xf0, 0xcc, 0xed, 0xc3, 0xb7, 0x2e, 0x3e, 0x41, 0x7c, 0xeb, 0xae,
-	0xf1, 0xb7, 0x9e, 0x35, 0x5c, 0xdc, 0xdb, 0x3d, 0xb8, 0xbf, 0x8f, 0xf9,
-	0xb9, 0xcf, 0xf4, 0xf4, 0xf1, 0x9a, 0x1b, 0x68, 0x6e, 0xb0, 0x8d, 0x16,
-	0x4f, 0x72, 0x5f, 0xd0, 0x83, 0x0b, 0xe3, 0x17, 0x90, 0x63, 0x6d, 0x74,
-	0xf1, 0x64, 0x8b, 0xc0, 0x9b, 0xfd, 0xf9, 0xc6, 0xca, 0x9a, 0x57, 0xb0,
-	0xa6, 0x3b, 0x97, 0x89, 0x6f, 0x19, 0x96, 0xf1, 0xe3, 0x31, 0xee, 0xe3,
-	0xb1, 0x37, 0xcb, 0x5f, 0x33, 0x82, 0xce, 0x9e, 0x0d, 0xc6, 0xcd, 0xfd,
-	0x56, 0x6b, 0x26, 0x8b, 0xdb, 0x9d, 0x34, 0x1b, 0xd4, 0xc0, 0x37, 0x55,
-	0xfa, 0x28, 0xae, 0x23, 0xa8, 0x4a, 0xb4, 0x8f, 0xf9, 0xbc, 0x4e, 0xd6,
-	0xaf, 0x5b, 0x30, 0x6f, 0xd8, 0xcd, 0xd1, 0x88, 0xe5, 0x38, 0x27, 0xec,
-	0xbe, 0x26, 0xc7, 0xd9, 0xee, 0xb3, 0xdf, 0xc7, 0x53, 0xc8, 0xaa, 0x3c,
-	0xaf, 0x29, 0xed, 0xa0, 0x83, 0x50, 0xcf, 0x8b, 0xb2, 0x9e, 0xb2, 0xe8,
-	0xad, 0x99, 0x18, 0x4e, 0x1c, 0xe3, 0x9c, 0xed, 0xac, 0x85, 0xfe, 0xe0,
-	0xbd, 0x98, 0x00, 0x1e, 0x61, 0x8a, 0xe2, 0xaf, 0x50, 0xca, 0xe3, 0x69,
-	0xe1, 0xa9, 0xe0, 0xc9, 0xf5, 0x0c, 0x1d, 0x4f, 0xe8, 0x18, 0xec, 0x53,
-	0xb4, 0xef, 0x92, 0x93, 0x3f, 0x41, 0x37, 0xde, 0x9e, 0x74, 0xea, 0x51,
-	0x8b, 0xd6, 0x72, 0xf5, 0xa8, 0x3f, 0x67, 0x9e, 0x9c, 0x70, 0xeb, 0x51,
-	0x8b, 0x24, 0xea, 0x51, 0x27, 0x56, 0xa8, 0x47, 0x25, 0x56, 0x5f, 0x8f,
-	0xe2, 0xf9, 0x35, 0xda, 0xd7, 0x4f, 0xca, 0x17, 0x64, 0x3d, 0xea, 0x3d,
-	0x72, 0xea, 0x51, 0x17, 0xa9, 0x71, 0x3d, 0xea, 0x78, 0x5d, 0x3d, 0x2a,
-	0x28, 0xea, 0x51, 0x3c, 0x8f, 0x53, 0x8f, 0x12, 0xed, 0xbe, 0x88, 0xa7,
-	0xee, 0x42, 0xf4, 0xee, 0x64, 0x07, 0x68, 0x66, 0xd0, 0xf7, 0x1a, 0xda,
-	0x34, 0x45, 0xc8, 0xdb, 0x4a, 0x35, 0xd0, 0x07, 0x6e, 0xb8, 0xbe, 0xa2,
-	0xd0, 0x06, 0xcc, 0x9b, 0xec, 0x7b, 0xd8, 0x53, 0x63, 0x61, 0x9a, 0xff,
-	0x62, 0xea, 0x2c, 0x07, 0x45, 0x9d, 0xe5, 0x87, 0x6b, 0xbc, 0x75, 0x96,
-	0x45, 0xba, 0x7e, 0x9d, 0xe5, 0x60, 0x83, 0x3a, 0xcb, 0x5b, 0x54, 0xad,
-	0xb3, 0xbc, 0x45, 0xd5, 0x3a, 0xcb, 0xc1, 0x12, 0xe7, 0xe2, 0x3e, 0x89,
-	0x5f, 0x06, 0xed, 0x41, 0xf1, 0xc7, 0xb5, 0x97, 0xc5, 0xca, 0x1e, 0x7e,
-	0xd9, 0x6a, 0x2f, 0x6c, 0x03, 0x22, 0x17, 0x2e, 0xd7, 0xd4, 0x5e, 0xb8,
-	0x0d, 0x9d, 0xb1, 0xd7, 0x08, 0x19, 0x99, 0x83, 0x7f, 0x5f, 0x9c, 0x0c,
-	0x61, 0xce, 0x0e, 0xf8, 0x8c, 0x0e, 0xe4, 0x06, 0x61, 0xb4, 0x15, 0xda,
-	0x64, 0x0d, 0xa1, 0x8f, 0xc7, 0xd9, 0x0e, 0x43, 0xb7, 0x6c, 0x77, 0x7f,
-	0x0f, 0x48, 0x1a, 0x44, 0x68, 0xb8, 0x9d, 0xf4, 0x20, 0xfb, 0x8e, 0xc9,
-	0x3d, 0x74, 0xc8, 0xde, 0x22, 0xf6, 0xbd, 0xc1, 0xaa, 0x95, 0xb9, 0xc1,
-	0x1b, 0x90, 0xb9, 0xcc, 0xaa, 0x65, 0x8e, 0xe5, 0xcd, 0x39, 0xf7, 0xdd,
-	0x60, 0xf1, 0xfa, 0x1d, 0x02, 0xa7, 0x77, 0x1b, 0xc8, 0xfb, 0x18, 0xec,
-	0x8e, 0x33, 0xbf, 0x2e, 0xd7, 0xab, 0x8f, 0x87, 0x9f, 0x6d, 0x66, 0xff,
-	0xbd, 0x72, 0x3d, 0xb1, 0xde, 0x7f, 0xaf, 0xe4, 0x47, 0x15, 0x61, 0x93,
-	0xb3, 0x25, 0xae, 0xed, 0x7b, 0xf9, 0x33, 0x8f, 0x9c, 0x00, 0x7d, 0x42,
-	0x0f, 0x98, 0xae, 0x41, 0xf0, 0x01, 0xeb, 0xd8, 0x4f, 0xc9, 0x5a, 0x16,
-	0x9e, 0x05, 0x97, 0x7f, 0xad, 0xb0, 0x99, 0xee, 0x18, 0xdb, 0x01, 0x0b,
-	0xfe, 0x8f, 0xeb, 0x28, 0x7c, 0x8e, 0xca, 0xfd, 0x2e, 0x5f, 0xbb, 0x2e,
-	0xbc, 0xa7, 0x72, 0xbb, 0x5c, 0xce, 0x8a, 0x7a, 0x2d, 0xa9, 0x9d, 0x7d,
-	0xd3, 0x2d, 0x6c, 0x6b, 0xb6, 0x58, 0xae, 0xcc, 0x26, 0xf0, 0xce, 0x7c,
-	0x7d, 0x17, 0x36, 0x9c, 0xcf, 0xaa, 0xbf, 0x23, 0x6a, 0x04, 0x73, 0x36,
-	0xdb, 0x6b, 0x8e, 0x41, 0x7f, 0x0b, 0xb2, 0xc4, 0xef, 0x51, 0x71, 0x2e,
-	0x21, 0x6a, 0xf8, 0x83, 0xdc, 0x76, 0xed, 0x4a, 0x94, 0xed, 0x30, 0xf6,
-	0x5c, 0xa5, 0x31, 0xe2, 0x23, 0xc8, 0x0c, 0xc7, 0xb1, 0x0c, 0xe7, 0xc6,
-	0x9e, 0x9a, 0xa7, 0x66, 0xab, 0xcb, 0xb8, 0x88, 0x75, 0x39, 0x00, 0x9a,
-	0xed, 0x10, 0x31, 0xea, 0xb8, 0x5d, 0xa6, 0xea, 0x19, 0x3f, 0xd3, 0xdc,
-	0x39, 0xe7, 0x3f, 0x66, 0x2f, 0x47, 0xfb, 0xcd, 0x37, 0x48, 0x7b, 0x47,
-	0x1f, 0x6b, 0xe9, 0xae, 0x23, 0x7e, 0x71, 0xe9, 0xee, 0xfa, 0xa8, 0x49,
-	0x49, 0x83, 0xa8, 0xac, 0x2b, 0x7e, 0x5a, 0x9e, 0x29, 0xfd, 0x5f, 0xd8,
-	0xaf, 0xe2, 0xd9, 0xaf, 0xab, 0xbb, 0xfb, 0xe4, 0x7e, 0xc3, 0x75, 0xba,
-	0x1b, 0x97, 0x75, 0xb9, 0x5f, 0x84, 0xee, 0xba, 0x7b, 0xe2, 0xb5, 0xb7,
-	0x5c, 0x67, 0xdd, 0x67, 0x48, 0x8d, 0xaf, 0x14, 0x7b, 0xff, 0xb4, 0xf9,
-	0xe3, 0xc5, 0xde, 0x1f, 0x87, 0x9e, 0x5e, 0xbd, 0x65, 0x1a, 0xb6, 0x89,
-	0xb8, 0xc2, 0xd1, 0x1f, 0xd8, 0xe3, 0x82, 0x9f, 0x16, 0x1e, 0xd2, 0xe9,
-	0x9f, 0xee, 0xe4, 0xfa, 0xac, 0x26, 0x73, 0x7c, 0x6e, 0x7f, 0xb1, 0x95,
-	0x63, 0xab, 0x4d, 0xd6, 0x77, 0x44, 0x6e, 0x95, 0x57, 0x4d, 0x8f, 0x1f,
-	0x31, 0x30, 0xce, 0x63, 0x61, 0xba, 0x1c, 0xbc, 0x91, 0xb8, 0xbc, 0xcb,
-	0x58, 0xf4, 0xad, 0x26, 0x2e, 0xbf, 0x55, 0xf7, 0x5b, 0x7f, 0xdd, 0x7a,
-	0xbd, 0x3a, 0x47, 0x35, 0x2e, 0xe7, 0x7c, 0x3e, 0xe8, 0xd4, 0x18, 0x4c,
-	0x8e, 0xcf, 0xd7, 0x4a, 0x9e, 0xf0, 0x3b, 0x72, 0x11, 0x1b, 0x79, 0x08,
-	0x64, 0xfc, 0x55, 0xc8, 0xca, 0x2b, 0x36, 0xf2, 0x0e, 0x1b, 0xf9, 0x88,
-	0x8d, 0xdc, 0xc3, 0x46, 0xee, 0x61, 0xf7, 0xc8, 0x1c, 0x26, 0x23, 0xeb,
-	0x56, 0x7c, 0x46, 0xcb, 0xf9, 0x61, 0x5e, 0xc9, 0xd8, 0xe3, 0x7c, 0x1f,
-	0x41, 0x4d, 0xc6, 0x36, 0xca, 0x78, 0xf0, 0x38, 0xdf, 0x77, 0x28, 0xab,
-	0x71, 0xae, 0x45, 0x91, 0xaa, 0xc6, 0x6f, 0x87, 0x8f, 0xda, 0x0e, 0xbc,
-	0x9a, 0x79, 0xdc, 0xa7, 0xc6, 0x5b, 0x99, 0x76, 0x8a, 0x1a, 0x5f, 0x2b,
-	0xcf, 0x0d, 0x7a, 0x03, 0x0e, 0xfe, 0xdd, 0xdc, 0xd6, 0xd4, 0xf8, 0xdd,
-	0xec, 0xd3, 0xc2, 0xa4, 0xba, 0xfd, 0xb7, 0x07, 0x98, 0xae, 0xa4, 0xde,
-	0x16, 0xe0, 0xb8, 0x76, 0xde, 0xf6, 0x8b, 0x3b, 0x05, 0xc9, 0x18, 0xd7,
-	0xcc, 0xb8, 0x5d, 0xa5, 0xab, 0xba, 0x2c, 0x5d, 0xfd, 0x95, 0xfa, 0x3f,
-	0xd3, 0xd2, 0xc7, 0x70, 0xa2, 0x36, 0xc6, 0x34, 0x75, 0xe7, 0xe3, 0xf3,
-	0x66, 0x5e, 0x47, 0xdc, 0x63, 0xc0, 0xf3, 0x60, 0x33, 0xb5, 0x0d, 0x0e,
-	0xf9, 0x2d, 0xef, 0xba, 0x6c, 0x43, 0x76, 0x90, 0x37, 0xc7, 0x5a, 0x7e,
-	0xcd, 0xa8, 0x38, 0x1b, 0x49, 0xf6, 0x47, 0x85, 0xec, 0xb0, 0xac, 0x69,
-	0xe2, 0xce, 0xd5, 0x47, 0xe2, 0x1e, 0x09, 0xcb, 0x19, 0xcb, 0xf2, 0x78,
-	0x7f, 0x57, 0x58, 0x53, 0x5b, 0xb0, 0x46, 0x98, 0xd2, 0x25, 0x71, 0x56,
-	0x80, 0x7c, 0xe9, 0xdc, 0x3a, 0x6a, 0xfb, 0x07, 0xbd, 0x9a, 0xc7, 0x46,
-	0x9d, 0xb3, 0x7a, 0xbb, 0xde, 0xff, 0x8d, 0x8a, 0x73, 0x65, 0xc7, 0x06,
-	0xb9, 0xe7, 0xc3, 0xab, 0x3b, 0xff, 0xbe, 0xbe, 0x3e, 0xb5, 0xd4, 0xd7,
-	0x0d, 0x24, 0x0d, 0x98, 0x36, 0x8d, 0xcf, 0xee, 0xe7, 0x4b, 0x7c, 0xaf,
-	0x25, 0x12, 0xe3, 0xdc, 0x6d, 0x44, 0xdc, 0xf9, 0x50, 0x21, 0x85, 0x3a,
-	0x8d, 0x19, 0x9c, 0xf3, 0x85, 0x86, 0x7d, 0x71, 0xca, 0x64, 0x27, 0x48,
-	0x43, 0xac, 0x98, 0xa9, 0xd6, 0x03, 0x1f, 0x5c, 0x43, 0x96, 0x2b, 0x97,
-	0x51, 0xce, 0x1f, 0x6a, 0xce, 0xed, 0x16, 0xe9, 0xb0, 0x72, 0xa0, 0x74,
-	0x84, 0x0e, 0x34, 0x8c, 0x29, 0x1b, 0xd7, 0x03, 0x2f, 0xd6, 0xd5, 0x14,
-	0x16, 0x44, 0x4d, 0x21, 0xb7, 0xc6, 0x6f, 0x3d, 0x19, 0x70, 0xee, 0xb5,
-	0x34, 0xd6, 0x93, 0x5d, 0x15, 0x3d, 0x71, 0xe1, 0xf8, 0x2c, 0xbe, 0x8d,
-	0x76, 0x8a, 0xb5, 0x0e, 0x2b, 0x59, 0xbb, 0x95, 0x76, 0x1a, 0x0e, 0xd6,
-	0xa3, 0x36, 0xe3, 0x75, 0x58, 0x39, 0x68, 0xe7, 0x95, 0xb4, 0xa8, 0x3d,
-	0x70, 0x8c, 0xbf, 0xe6, 0xda, 0x30, 0x95, 0xe9, 0xed, 0x98, 0xfb, 0x3d,
-	0xc3, 0x78, 0x6b, 0x8a, 0x2e, 0x9d, 0xf8, 0x2e, 0x51, 0x58, 0xe6, 0x6f,
-	0xce, 0x7c, 0xb9, 0x29, 0xae, 0x25, 0xde, 0x8f, 0xfd, 0x33, 0xfc, 0x6e,
-	0x25, 0x39, 0x55, 0x2e, 0xa7, 0x31, 0x3e, 0xd6, 0x7b, 0xaf, 0xc8, 0x8d,
-	0xd4, 0x38, 0x0d, 0x71, 0x8e, 0xac, 0x2d, 0xc9, 0x91, 0xd3, 0xd0, 0x35,
-	0xc4, 0x20, 0x76, 0x13, 0xbe, 0x75, 0xe3, 0x91, 0xcf, 0xae, 0x75, 0x64,
-	0xe4, 0xbb, 0x12, 0x0f, 0x1e, 0xff, 0xfb, 0x80, 0x7b, 0x0f, 0x28, 0x77,
-	0x2a, 0x8d, 0xfd, 0x37, 0x51, 0xca, 0x74, 0xf2, 0xbb, 0xec, 0x99, 0x23,
-	0x1b, 0x6a, 0xe1, 0xd1, 0x77, 0xca, 0x85, 0x0f, 0xd6, 0xc1, 0xf3, 0x19,
-	0xd7, 0x5f, 0xd5, 0xc1, 0x07, 0x3d, 0xf0, 0x66, 0x1d, 0x3c, 0xe2, 0xae,
-	0x33, 0xdf, 0xa8, 0x83, 0x37, 0x3d, 0xf0, 0xed, 0x75, 0xf0, 0xed, 0x80,
-	0x7f, 0xa3, 0x0e, 0x1e, 0x7d, 0xa7, 0x90, 0x13, 0x08, 0xda, 0x70, 0x8c,
-	0x74, 0x48, 0xe6, 0x89, 0x78, 0x2e, 0xb9, 0x1f, 0xc9, 0xf2, 0xd3, 0x01,
-	0x1a, 0x7b, 0xeb, 0xb5, 0x09, 0xd8, 0xa8, 0xaa, 0x4c, 0x39, 0xfa, 0xea,
-	0x95, 0x25, 0x96, 0xbd, 0x3c, 0xe4, 0x15, 0x7a, 0x54, 0x80, 0x3e, 0x15,
-	0x5c, 0x5f, 0xca, 0x77, 0xaa, 0x22, 0xc7, 0x1d, 0x3d, 0x56, 0x68, 0xbd,
-	0x35, 0x2f, 0x73, 0x91, 0xab, 0x8c, 0x3b, 0xfc, 0x86, 0xeb, 0x3b, 0xe8,
-	0x84, 0x63, 0x57, 0x58, 0xbf, 0x79, 0x7e, 0x69, 0x5f, 0x4a, 0x2c, 0x87,
-	0xce, 0x3a, 0xe9, 0x25, 0x32, 0x1b, 0x5e, 0x52, 0x77, 0xf1, 0xd5, 0xd9,
-	0x77, 0x12, 0xf6, 0x3d, 0xd7, 0xe2, 0xb7, 0x36, 0xac, 0xbd, 0x9e, 0x7d,
-	0xcf, 0x78, 0xec, 0x7b, 0x38, 0x58, 0xf5, 0xf9, 0x8f, 0x09, 0x9f, 0xdf,
-	0xd1, 0xc0, 0x66, 0xac, 0xde, 0xe7, 0xef, 0xfd, 0xd8, 0x3e, 0x7f, 0xb9,
-	0x75, 0x57, 0xe3, 0xf3, 0x1f, 0x69, 0xf9, 0x78, 0x3e, 0x9f, 0xd7, 0xac,
-	0xaf, 0x65, 0x7a, 0xcf, 0x59, 0x8e, 0xca, 0x18, 0x7b, 0xb7, 0x27, 0xc6,
-	0x66, 0xfc, 0xbe, 0x27, 0xef, 0x02, 0x9e, 0x5e, 0xeb, 0xc8, 0xdb, 0x51,
-	0x19, 0xa7, 0x73, 0xec, 0x8d, 0xf7, 0xc2, 0x23, 0x90, 0xd1, 0x7c, 0x8f,
-	0x8f, 0x54, 0x9a, 0x35, 0x9d, 0xb3, 0xed, 0x9f, 0x6f, 0xae, 0x17, 0xa1,
-	0xcb, 0xc2, 0x9f, 0x24, 0x3e, 0x81, 0x5a, 0xea, 0x49, 0xc8, 0x8f, 0xbb,
-	0xaf, 0x95, 0x6a, 0xa9, 0xf5, 0xe7, 0x1f, 0x7c, 0xee, 0x41, 0xca, 0x03,
-	0x95, 0x73, 0x10, 0xaf, 0x4e, 0xe9, 0x94, 0x9d, 0x21, 0xdd, 0x8c, 0x93,
-	0xb2, 0x8f, 0x71, 0x8e, 0xfd, 0xb0, 0x52, 0x6f, 0x3f, 0x24, 0x6b, 0x30,
-	0xea, 0xb2, 0x77, 0x82, 0x7e, 0x02, 0x7c, 0x58, 0xaf, 0x9c, 0x1a, 0x8c,
-	0xea, 0xdc, 0x09, 0x3a, 0xfe, 0xf3, 0xbb, 0x13, 0xc4, 0xf3, 0x6b, 0xb4,
-	0xb7, 0xc1, 0x9d, 0x20, 0xdf, 0x2a, 0xef, 0x04, 0xad, 0x17, 0x35, 0x18,
-	0x9e, 0xc7, 0xa9, 0xc1, 0x70, 0xbb, 0xb3, 0x8f, 0xe5, 0x3a, 0x4c, 0xa3,
-	0x93, 0xb7, 0x88, 0x7b, 0xa8, 0x9d, 0x7d, 0xb5, 0xf2, 0xbd, 0xef, 0x13,
-	0x8d, 0xa5, 0x79, 0xbd, 0xa3, 0x0d, 0xef, 0xb6, 0x24, 0x3f, 0xc1, 0x9a,
-	0xcb, 0x21, 0x51, 0x73, 0xb9, 0xb3, 0xcd, 0x5b, 0x73, 0x51, 0x57, 0xb8,
-	0xdb, 0x72, 0xa8, 0x41, 0xcd, 0xc5, 0xef, 0xb9, 0xdb, 0xe2, 0xf7, 0xdc,
-	0x6d, 0x39, 0x24, 0xeb, 0x2b, 0xea, 0x2f, 0xd1, 0xdd, 0x96, 0xe4, 0x8a,
-	0x77, 0x5b, 0xb6, 0x4a, 0x7d, 0xf5, 0xc2, 0xaf, 0xfe, 0xbc, 0x32, 0x55,
-	0x67, 0xe7, 0x13, 0xc2, 0xce, 0xdf, 0xd5, 0xea, 0xb7, 0x9e, 0x69, 0xbb,
-	0x9e, 0x9d, 0xdf, 0x57, 0xd1, 0x53, 0xbe, 0xa3, 0xcd, 0x77, 0xbe, 0x58,
-	0x16, 0xf9, 0x7c, 0xa6, 0x89, 0x72, 0x03, 0xbf, 0x2a, 0x68, 0xf6, 0x58,
-	0x6f, 0xed, 0x99, 0x63, 0xf5, 0x5e, 0xa4, 0xee, 0xb9, 0x17, 0x69, 0xa2,
-	0x5f, 0xaf, 0xab, 0x87, 0x04, 0xe4, 0xdd, 0x7e, 0xf8, 0xc2, 0x19, 0x43,
-	0xda, 0x5e, 0xc4, 0x70, 0x98, 0xae, 0x50, 0xe4, 0x3b, 0x95, 0x6d, 0xe4,
-	0x9b, 0x71, 0xce, 0x4b, 0x54, 0x11, 0x63, 0x42, 0x8e, 0x8b, 0x7e, 0xe1,
-	0x6f, 0xd4, 0xb8, 0x23, 0xb3, 0xe3, 0xf6, 0x05, 0xe0, 0xbf, 0x21, 0x51,
-	0x6d, 0x9b, 0x95, 0x5a, 0xce, 0x58, 0xe5, 0x0e, 0xbf, 0x09, 0xfb, 0xe0,
-	0xdc, 0x07, 0xca, 0x98, 0x7c, 0x67, 0xe4, 0x62, 0x5b, 0xf5, 0x3e, 0xd0,
-	0x67, 0xa4, 0x9c, 0x3a, 0xf7, 0x81, 0x48, 0x4d, 0x40, 0x3e, 0x6e, 0xe4,
-	0x3e, 0x50, 0xd7, 0x92, 0xfb, 0x40, 0x2b, 0xf3, 0x66, 0xe9, 0x7d, 0xa0,
-	0xc6, 0xfc, 0xe1, 0xfb, 0x40, 0xff, 0xde, 0xe6, 0xdc, 0x43, 0x5d, 0x89,
-	0x3f, 0x6e, 0x9c, 0xf4, 0x11, 0xe0, 0xf9, 0x3e, 0x50, 0xe5, 0x1e, 0x90,
-	0xe7, 0x0e, 0x10, 0xdf, 0x25, 0x59, 0xee, 0x0c, 0xce, 0x7b, 0xff, 0xa4,
-	0xa7, 0x72, 0xff, 0xe4, 0x7c, 0xc9, 0xf5, 0xed, 0xee, 0xb9, 0x1c, 0xc7,
-	0x39, 0xbb, 0x44, 0x8e, 0x7a, 0xae, 0x54, 0x5b, 0xc3, 0x60, 0xbe, 0x8f,
-	0x16, 0xcf, 0x81, 0x3e, 0x6f, 0x89, 0xdc, 0x00, 0x7c, 0xde, 0xe2, 0x23,
-	0xe6, 0x1d, 0x29, 0xa0, 0x8b, 0x38, 0xcb, 0x75, 0xf8, 0xdd, 0x21, 0x64,
-	0xc1, 0x91, 0x8b, 0xdd, 0x9e, 0xf3, 0xd0, 0xaa, 0x1c, 0x38, 0x67, 0xba,
-	0x0e, 0xef, 0x6a, 0x65, 0x46, 0x9c, 0xdd, 0x0c, 0xed, 0xb5, 0x9c, 0xf3,
-	0xc6, 0xa8, 0x38, 0xb7, 0x6d, 0xaf, 0xb3, 0x5b, 0x3a, 0xe4, 0x06, 0x31,
-	0x67, 0x8c, 0xeb, 0xd5, 0x8c, 0xfb, 0x66, 0xc1, 0xe3, 0x46, 0x67, 0x71,
-	0x2b, 0xd7, 0xf1, 0xdc, 0x9a, 0x0a, 0x21, 0x97, 0xd8, 0x9d, 0xce, 0x09,
-	0xbb, 0xe9, 0xac, 0xdd, 0x29, 0xd6, 0xde, 0x58, 0x77, 0x96, 0xcd, 0x72,
-	0xb5, 0x5c, 0x4c, 0x70, 0x3d, 0x9a, 0xde, 0xb3, 0x84, 0xa6, 0xb5, 0xba,
-	0x84, 0xdc, 0xb5, 0x62, 0xe3, 0x3b, 0x2a, 0xba, 0x34, 0x2e, 0xee, 0x21,
-	0xbb, 0xe7, 0xb5, 0x0e, 0xfd, 0xaa, 0xba, 0xb7, 0x5c, 0x3c, 0x53, 0x4f,
-	0xbf, 0x4d, 0xff, 0x4b, 0xe8, 0x77, 0x15, 0xf4, 0xe3, 0x77, 0x03, 0xef,
-	0xef, 0x8a, 0x7a, 0xc0, 0xb9, 0x52, 0xe4, 0x78, 0x9e, 0x38, 0x4e, 0x88,
-	0xcc, 0x2e, 0x50, 0x0f, 0xe8, 0xc8, 0xff, 0xeb, 0xe2, 0xde, 0x9d, 0x60,
-	0xfa, 0xb2, 0x7d, 0x8f, 0xbc, 0x70, 0x99, 0xd8, 0xc6, 0xdf, 0x8d, 0x7d,
-	0x94, 0xcb, 0x2f, 0xc5, 0x5c, 0xfa, 0xb3, 0xee, 0x73, 0x9d, 0xaa, 0x76,
-	0x5f, 0x7b, 0x57, 0xed, 0x53, 0x1d, 0xf9, 0xcc, 0x34, 0x90, 0xcf, 0x8c,
-	0xdc, 0xa3, 0x6f, 0xa6, 0x71, 0xbc, 0x9a, 0x9a, 0xfc, 0xef, 0x5e, 0xae,
-	0x26, 0xb6, 0x8d, 0x22, 0x0a, 0xbf, 0xac, 0xd7, 0x4e, 0xe3, 0xa4, 0x61,
-	0x93, 0x3a, 0xad, 0x69, 0xd2, 0x60, 0xc7, 0x4b, 0x12, 0x29, 0xa5, 0xa4,
-	0x52, 0x55, 0x45, 0x60, 0xa9, 0x21, 0x4e, 0xda, 0x0a, 0x71, 0x70, 0x0b,
-	0x48, 0x51, 0xc5, 0x21, 0x4d, 0xd3, 0x7b, 0x85, 0x84, 0x54, 0xa1, 0x8a,
-	0x46, 0x4e, 0x02, 0x15, 0x4a, 0xe5, 0x0a, 0x96, 0x72, 0x41, 0xa2, 0xd8,
-	0x8e, 0x02, 0x52, 0x2a, 0xf7, 0xca, 0x85, 0xba, 0xbf, 0x08, 0x89, 0x03,
-	0x70, 0x06, 0x29, 0x2a, 0x3f, 0xe2, 0xc0, 0x8d, 0x1b, 0x54, 0x5d, 0xde,
-	0x37, 0xb3, 0x63, 0xaf, 0x77, 0xd7, 0x8e, 0x03, 0x11, 0x07, 0x27, 0xbb,
-	0xf6, 0xcc, 0xce, 0xec, 0xcc, 0x37, 0x6f, 0xbe, 0xf7, 0x37, 0xfd, 0xbe,
-	0x78, 0x8d, 0x5a, 0xdb, 0x5b, 0xf3, 0x55, 0xec, 0xe7, 0xaf, 0x37, 0x18,
-	0x57, 0xed, 0xba, 0xe4, 0xa9, 0xf5, 0xe3, 0x9a, 0x72, 0xd9, 0x1b, 0xf0,
-	0xfe, 0xc7, 0x68, 0x51, 0xd8, 0x86, 0x94, 0xad, 0xee, 0xc5, 0x40, 0x9b,
-	0xd9, 0xff, 0x33, 0x16, 0x03, 0x3e, 0x9b, 0x68, 0xad, 0x6d, 0x8a, 0xed,
-	0x71, 0xd9, 0x16, 0xde, 0xda, 0xc2, 0xb6, 0x10, 0x3c, 0x16, 0xfd, 0x9e,
-	0xb1, 0xa8, 0xc9, 0xea, 0xa1, 0x16, 0xed, 0x74, 0x88, 0x21, 0xbf, 0x9d,
-	0x67, 0x6c, 0x05, 0xca, 0xce, 0x4f, 0x5d, 0x36, 0x3c, 0xe0, 0x73, 0xdc,
-	0x59, 0xeb, 0xc0, 0x27, 0xb5, 0x9d, 0x1a, 0x51, 0xed, 0x01, 0x8f, 0xc9,
-	0xc5, 0x45, 0x82, 0xbe, 0x86, 0x36, 0xe3, 0x82, 0xe3, 0xfa, 0x39, 0x14,
-	0x8f, 0xf1, 0xfa, 0x1b, 0x88, 0xe5, 0x70, 0xda, 0x3f, 0xd9, 0x76, 0xae,
-	0x9c, 0xe5, 0xbd, 0x42, 0xd4, 0x63, 0xbd, 0xef, 0x52, 0xdb, 0x82, 0xa8,
-	0x27, 0xe3, 0x20, 0x1c, 0x1d, 0xd0, 0xe1, 0xe2, 0x8d, 0x74, 0x3f, 0xff,
-	0x9e, 0x13, 0xcc, 0xdd, 0x7f, 0xdd, 0x1d, 0x36, 0x3f, 0x34, 0x64, 0xae,
-	0xde, 0x56, 0xdc, 0x5d, 0xd9, 0x89, 0x06, 0x85, 0xaf, 0xc1, 0xad, 0x7b,
-	0x41, 0x76, 0x5d, 0xe0, 0x3d, 0x7c, 0xa8, 0xba, 0x7f, 0xef, 0x84, 0x7d,
-	0xe8, 0x99, 0x16, 0x62, 0x1d, 0x44, 0x8e, 0xe5, 0x2b, 0x53, 0xc8, 0x45,
-	0xaa, 0xe6, 0xef, 0x78, 0xf3, 0x3c, 0x20, 0x3f, 0x55, 0x9e, 0x87, 0xca,
-	0x23, 0xc5, 0x7b, 0x24, 0x02, 0xf2, 0x3c, 0xdc, 0x32, 0x18, 0xf5, 0xea,
-	0xdf, 0xc3, 0x2d, 0x7f, 0x57, 0x1c, 0xf9, 0x5b, 0xf0, 0xd8, 0xe3, 0x97,
-	0xf3, 0x6a, 0x2d, 0x20, 0xe7, 0x43, 0xf1, 0x94, 0xde, 0x00, 0x9e, 0x12,
-	0x9c, 0xeb, 0xa1, 0xa5, 0x2f, 0xf2, 0x5e, 0x7e, 0x08, 0x7b, 0xb9, 0x51,
-	0x8b, 0xe9, 0x95, 0x72, 0xf0, 0xdc, 0x3a, 0x64, 0xa2, 0xca, 0xb9, 0x81,
-	0x5c, 0x44, 0x2c, 0x3c, 0xe6, 0xba, 0xe4, 0x60, 0x11, 0xbf, 0xa9, 0x58,
-	0x52, 0xa5, 0x47, 0xbd, 0x23, 0xf2, 0x0c, 0xbe, 0x1b, 0x3f, 0xcc, 0x1c,
-	0x18, 0xf2, 0x13, 0x76, 0xa6, 0x43, 0x0e, 0x1f, 0xbe, 0xcc, 0xbf, 0x8d,
-	0x39, 0xd7, 0x92, 0x8b, 0xca, 0x6b, 0xa5, 0x4b, 0xfd, 0xd0, 0x41, 0xe6,
-	0x6f, 0x0e, 0x2f, 0xad, 0xb3, 0x41, 0xc4, 0x53, 0xda, 0xdb, 0x74, 0xa1,
-	0xd8, 0x0c, 0x83, 0xf5, 0xf8, 0x4b, 0x79, 0x38, 0x4f, 0x42, 0x70, 0x9e,
-	0x9f, 0x3a, 0xc2, 0xe6, 0x44, 0x4f, 0xb3, 0x38, 0x9c, 0x53, 0x55, 0xfc,
-	0xa9, 0x72, 0xaa, 0x6f, 0x8f, 0x3a, 0x10, 0xa7, 0xe6, 0xc7, 0x04, 0xe6,
-	0x1f, 0xfa, 0x9c, 0x5a, 0x87, 0xd0, 0xeb, 0x10, 0xf3, 0x87, 0x76, 0x8d,
-	0x06, 0x6b, 0xb0, 0x66, 0x13, 0x2f, 0x50, 0x2b, 0xb1, 0x7f, 0xc9, 0xd1,
-	0x0a, 0x9d, 0xed, 0x69, 0xa6, 0xf3, 0x9e, 0x08, 0xd4, 0x79, 0x83, 0x72,
-	0xa4, 0xcc, 0x80, 0x1c, 0x29, 0x37, 0x0e, 0x75, 0x17, 0x0e, 0xe3, 0x2e,
-	0x2e, 0x30, 0xc0, 0xdc, 0xb9, 0x8b, 0xf1, 0x04, 0xee, 0x1c, 0xa5, 0xd0,
-	0x07, 0x6e, 0xee, 0xec, 0xf7, 0x13, 0x49, 0x5c, 0xfe, 0xdb, 0xdc, 0xa9,
-	0xa0, 0x7e, 0x27, 0x7c, 0xfd, 0x86, 0x1c, 0x9f, 0x6c, 0xc8, 0x13, 0x82,
-	0x38, 0xfe, 0x4e, 0xf7, 0xd3, 0xbb, 0xf6, 0xd1, 0xa6, 0x09, 0xfd, 0x70,
-	0x74, 0xb1, 0xba, 0xee, 0x5f, 0xf0, 0xd9, 0xb9, 0xc1, 0x67, 0x43, 0xc2,
-	0x27, 0xd7, 0x25, 0xf6, 0x90, 0x9d, 0x93, 0x61, 0x9d, 0x1e, 0x19, 0x66,
-	0xf7, 0xd4, 0xec, 0xfc, 0x88, 0x21, 0xec, 0x73, 0x74, 0x0e, 0xb9, 0xef,
-	0x14, 0x1a, 0xc6, 0xa5, 0xe2, 0x3b, 0xe9, 0x1b, 0x38, 0x77, 0x04, 0xb2,
-	0x1b, 0xf2, 0xfc, 0xf4, 0x6c, 0xd8, 0x34, 0x1c, 0x1f, 0x03, 0xfc, 0x08,
-	0xc0, 0xa9, 0x7a, 0x7e, 0x90, 0x0d, 0x3d, 0x68, 0x0e, 0x87, 0x7c, 0x73,
-	0x28, 0xf1, 0x06, 0x6e, 0x8f, 0x58, 0xbc, 0x83, 0x9e, 0x38, 0xc5, 0x9d,
-	0x18, 0x93, 0xee, 0x80, 0x78, 0x41, 0xc4, 0xfa, 0xf9, 0xfa, 0xcb, 0xef,
-	0x7c, 0x51, 0xf3, 0xaf, 0xad, 0x49, 0x6d, 0xba, 0x3c, 0xad, 0x4d, 0x15,
-	0x51, 0xee, 0xa2, 0x56, 0xdb, 0x97, 0x36, 0x5d, 0x1c, 0x11, 0x7c, 0x30,
-	0x79, 0xad, 0x42, 0x78, 0x4f, 0xdb, 0xbe, 0x25, 0xb8, 0xed, 0x80, 0x0f,
-	0xab, 0x8a, 0x73, 0x18, 0x2d, 0xbc, 0x97, 0xb4, 0xbd, 0xb8, 0xb9, 0x8e,
-	0x5b, 0xbe, 0x3f, 0x1d, 0x20, 0xdf, 0x9b, 0xd9, 0x0a, 0x91, 0xbf, 0x29,
-	0xe2, 0xb2, 0xa9, 0x68, 0x21, 0xde, 0xf1, 0x30, 0xe2, 0x7b, 0xe1, 0xd7,
-	0xa8, 0x62, 0xe1, 0x6e, 0x30, 0x16, 0xaa, 0xf6, 0x60, 0x1d, 0xb9, 0xa3,
-	0x2c, 0x8b, 0xc3, 0xe9, 0x5e, 0x0a, 0x99, 0x28, 0xff, 0x6c, 0xe2, 0x3e,
-	0x1d, 0x73, 0x78, 0x09, 0xfc, 0x3c, 0xb2, 0xde, 0x4c, 0x0b, 0x76, 0xe1,
-	0x60, 0x7f, 0x46, 0x84, 0x65, 0xf3, 0x67, 0xbd, 0xad, 0xf9, 0x33, 0x54,
-	0x39, 0xd4, 0xed, 0xa2, 0x35, 0x0b, 0x71, 0x92, 0xf0, 0x2f, 0x75, 0x77,
-	0xb4, 0x9b, 0x41, 0xf2, 0x4f, 0xc5, 0x7e, 0x82, 0x1f, 0xc9, 0xb9, 0xba,
-	0x41, 0x98, 0x3b, 0x9b, 0xbe, 0x6f, 0x30, 0x57, 0xdb, 0xb1, 0x29, 0x37,
-	0x9f, 0x2b, 0xc3, 0x33, 0x57, 0xd8, 0x8b, 0x9a, 0xcd, 0x95, 0xf2, 0x43,
-	0x2a, 0xdf, 0xdc, 0x51, 0xc8, 0x93, 0x45, 0xf7, 0x5c, 0xed, 0x8c, 0x7f,
-	0x4e, 0xce, 0xd9, 0x4e, 0xfb, 0xe0, 0x1a, 0x8f, 0x43, 0x34, 0xd0, 0x76,
-	0x12, 0x2c, 0x33, 0xfc, 0x6b, 0xeb, 0x86, 0x5c, 0x5b, 0xcc, 0x2b, 0x9e,
-	0x6f, 0xb8, 0xb6, 0xb0, 0x0f, 0x5c, 0x70, 0xf6, 0x81, 0xd3, 0x3e, 0x7d,
-	0x51, 0xd9, 0xbc, 0xff, 0xab, 0xed, 0x0d, 0xcf, 0x7d, 0x22, 0xce, 0xe9,
-	0xc8, 0x91, 0xdc, 0x47, 0xce, 0x37, 0xe4, 0x61, 0x3d, 0xdb, 0x5c, 0xa7,
-	0x6a, 0xee, 0x91, 0x73, 0x01, 0x79, 0x99, 0xa5, 0xf3, 0xf9, 0xc7, 0x06,
-	0x75, 0xf7, 0x53, 0xa4, 0x1a, 0xd3, 0x72, 0x40, 0xf0, 0x61, 0xb7, 0xbe,
-	0xbc, 0xec, 0xe4, 0x28, 0xe6, 0x5c, 0x63, 0xb0, 0x9c, 0xcf, 0x36, 0x89,
-	0xa7, 0x6f, 0x25, 0x9e, 0x63, 0xc0, 0x23, 0x37, 0xbd, 0x73, 0x35, 0xa1,
-	0x65, 0xf2, 0xa8, 0xb3, 0x87, 0xce, 0xea, 0x9f, 0xf0, 0x18, 0x3d, 0xb1,
-	0x23, 0xe2, 0x9c, 0x11, 0xe0, 0xd2, 0xb6, 0x97, 0xcd, 0x0e, 0x5a, 0x94,
-	0x7e, 0x46, 0x9a, 0xfa, 0xf8, 0x12, 0x15, 0x85, 0x7f, 0x0b, 0xb9, 0x51,
-	0xb0, 0x71, 0xc3, 0x47, 0x87, 0xe7, 0xf0, 0xf7, 0x1b, 0x13, 0x8e, 0xcc,
-	0xfd, 0x93, 0x31, 0x8c, 0x7a, 0x38, 0x0b, 0x01, 0xeb, 0x9d, 0x34, 0xc9,
-	0x31, 0xb9, 0x1d, 0x71, 0x4e, 0x80, 0x8c, 0xcd, 0xbb, 0x5d, 0xde, 0x8e,
-	0x4f, 0xa1, 0x55, 0xbd, 0xe4, 0xeb, 0x68, 0xd8, 0xfc, 0x72, 0xcf, 0xf6,
-	0x7d, 0x0a, 0x2a, 0x77, 0x5f, 0x71, 0x58, 0x75, 0x2d, 0x73, 0x69, 0xc1,
-	0x99, 0xe7, 0xd7, 0x55, 0xde, 0x6d, 0x77, 0x40, 0xde, 0x6d, 0x88, 0xe6,
-	0x84, 0xaf, 0x2e, 0x44, 0x39, 0x47, 0x37, 0x93, 0x9c, 0x5a, 0xd9, 0x6a,
-	0x23, 0x4e, 0xfc, 0x29, 0xee, 0xdd, 0x39, 0xf9, 0x7c, 0x5f, 0x04, 0xcf,
-	0x46, 0x4e, 0xb5, 0x2d, 0x62, 0xf1, 0x33, 0xa2, 0x5c, 0xa7, 0xa7, 0x1c,
-	0xdf, 0x17, 0xd5, 0x33, 0x3b, 0xb9, 0x7c, 0x8a, 0x64, 0x0e, 0x7d, 0x27,
-	0xcd, 0x15, 0x9b, 0xf5, 0x6b, 0x1f, 0xe2, 0x81, 0xe3, 0xf0, 0x95, 0x0a,
-	0xbf, 0x95, 0xa1, 0xfa, 0x80, 0x3e, 0xb5, 0x57, 0xfb, 0x04, 0xf9, 0x14,
-	0x12, 0x7e, 0x05, 0xbe, 0x76, 0xda, 0x99, 0x23, 0x77, 0xbf, 0xc2, 0xdc,
-	0x2f, 0x3c, 0xa7, 0xd3, 0x55, 0xb6, 0xd3, 0x55, 0xb6, 0x36, 0x5e, 0x3a,
-	0xeb, 0x54, 0x0b, 0xe5, 0x1f, 0x59, 0x2f, 0xfd, 0x56, 0xd8, 0xe6, 0xe6,
-	0xb3, 0x06, 0x2d, 0xac, 0xf7, 0xf2, 0x27, 0xc6, 0x1f, 0x94, 0xdb, 0xcb,
-	0xff, 0xdd, 0x9c, 0xa2, 0x5f, 0xc4, 0x02, 0xb6, 0xce, 0x07, 0x83, 0xf1,
-	0x1f, 0xbc, 0x6e, 0x13, 0x01, 0xeb, 0xb6, 0xf9, 0xbe, 0x22, 0xf7, 0x93,
-	0xe4, 0x95, 0x8a, 0x23, 0xaf, 0x36, 0x69, 0xd0, 0x27, 0xa7, 0x82, 0xd6,
-	0x29, 0xfa, 0x78, 0xca, 0xe9, 0xe3, 0x9b, 0xa2, 0x3f, 0xe3, 0x54, 0xa8,
-	0xe6, 0x0d, 0x1f, 0xe1, 0xeb, 0x98, 0xb2, 0xd1, 0x35, 0x90, 0xab, 0xdf,
-	0x6c, 0x43, 0xc6, 0x04, 0x71, 0xb2, 0x03, 0x01, 0xfa, 0x80, 0xee, 0xd2,
-	0x07, 0xe2, 0x55, 0x7d, 0x60, 0x45, 0xe8, 0x09, 0xbb, 0x1c, 0x1d, 0x34,
-	0xd8, 0x16, 0x97, 0xcb, 0xe3, 0xcc, 0x1b, 0xd8, 0xf8, 0xa4, 0x1d, 0x7d,
-	0xda, 0xaa, 0x9e, 0x99, 0xc3, 0xba, 0x65, 0x8d, 0x4b, 0xfb, 0xe5, 0x09,
-	0xce, 0xac, 0xa8, 0xcc, 0x3e, 0x30, 0xa3, 0xa4, 0xa5, 0x93, 0xf1, 0xa9,
-	0x50, 0x84, 0x16, 0xac, 0x28, 0x15, 0xac, 0x14, 0x73, 0x70, 0xf0, 0xe3,
-	0xd0, 0x80, 0x46, 0x11, 0x96, 0x35, 0x11, 0x2a, 0x95, 0x94, 0x4e, 0x76,
-	0x86, 0xc8, 0x2c, 0xc6, 0xa4, 0x0d, 0x9b, 0x71, 0x9a, 0x1f, 0x33, 0xe6,
-	0x49, 0x43, 0xcc, 0x8b, 0x93, 0xa3, 0x0e, 0x0c, 0x8a, 0x38, 0x4b, 0xfd,
-	0xe5, 0x91, 0x28, 0xb5, 0xa7, 0xa5, 0xcd, 0x68, 0x86, 0xdb, 0xf8, 0xc2,
-	0x8a, 0xd1, 0x95, 0x7c, 0xd2, 0x38, 0xc1, 0xed, 0x64, 0xac, 0x64, 0x62,
-	0x92, 0x9f, 0x5d, 0x2c, 0x45, 0x28, 0x67, 0x45, 0xa8, 0x50, 0x4a, 0x19,
-	0x43, 0x6d, 0xa2, 0xcd, 0x18, 0xda, 0x7c, 0x49, 0x1f, 0x33, 0x4e, 0x92,
-	0xbb, 0xcd, 0xaf, 0x9c, 0x36, 0xbd, 0x6d, 0xfd, 0x61, 0xe3, 0xfe, 0x44,
-	0xa8, 0x32, 0x7b, 0x9f, 0xf1, 0x92, 0x5b, 0x9d, 0x60, 0xd9, 0x14, 0x13,
-	0x67, 0xdb, 0x68, 0xe9, 0x34, 0xcb, 0x1d, 0x9c, 0x6d, 0x61, 0xd0, 0x62,
-	0x39, 0x4e, 0xef, 0x57, 0xed, 0x07, 0x12, 0x43, 0x39, 0x91, 0x43, 0x84,
-	0x33, 0x17, 0x2a, 0xb3, 0xbf, 0x9b, 0x5e, 0x7f, 0x3f, 0xeb, 0x5b, 0x1f,
-	0xc5, 0x28, 0x72, 0x15, 0x71, 0xdd, 0x36, 0x5d, 0x1b, 0x4f, 0x5e, 0xd9,
-	0x14, 0x79, 0x68, 0x09, 0x5a, 0x33, 0xa5, 0x3c, 0xcd, 0x71, 0xf9, 0x15,
-	0x94, 0x5b, 0x4b, 0xd0, 0x3d, 0x91, 0x8f, 0xd6, 0x4e, 0x77, 0xf4, 0x18,
-	0x85, 0x6e, 0x9a, 0xc6, 0xbc, 0xf0, 0x0b, 0x57, 0x66, 0x87, 0x86, 0x0d,
-	0xd2, 0xae, 0xa2, 0x1e, 0xff, 0xbf, 0x89, 0xfb, 0x28, 0x61, 0x7e, 0x66,
-	0xac, 0x31, 0x5e, 0x49, 0xc3, 0xf1, 0x12, 0x64, 0xf3, 0x41, 0x89, 0xa5,
-	0x39, 0x23, 0x42, 0xd0, 0x5f, 0x61, 0x7b, 0xeb, 0x35, 0x27, 0x7b, 0xa4,
-	0xfe, 0xe4, 0x3b, 0x9b, 0x43, 0x9f, 0x19, 0x71, 0x9f, 0xcf, 0x51, 0x7b,
-	0x66, 0xc6, 0x92, 0xef, 0xb9, 0x52, 0xee, 0xa5, 0x25, 0x6e, 0x7b, 0x64,
-	0xf8, 0x8c, 0x73, 0xa6, 0x0f, 0xff, 0xd9, 0x8b, 0x7b, 0x85, 0xb7, 0x7d,
-	0x7d, 0x14, 0xc5, 0x3d, 0x0d, 0xe8, 0x3c, 0xc7, 0xb0, 0xe9, 0x87, 0xc5,
-	0xb8, 0xa7, 0xe2, 0x98, 0xcb, 0xb9, 0xb8, 0x3a, 0x97, 0x08, 0x65, 0xba,
-	0xe9, 0x91, 0xd5, 0x45, 0x3f, 0x8b, 0xf3, 0x47, 0xf8, 0xba, 0x84, 0x9c,
-	0xa3, 0x36, 0xca, 0x64, 0xbb, 0x69, 0xb3, 0x14, 0x66, 0x71, 0x05, 0xec,
-	0x44, 0xb9, 0x4c, 0x81, 0xa6, 0xd6, 0x5f, 0xeb, 0x83, 0x1f, 0x66, 0x52,
-	0xab, 0x61, 0xe9, 0x51, 0x00, 0x96, 0x7e, 0xa9, 0xc3, 0xd2, 0xd1, 0xbe,
-	0xe6, 0x58, 0xea, 0x77, 0x62, 0xd6, 0xa3, 0x14, 0x71, 0x70, 0xf4, 0x39,
-	0xe3, 0xe8, 0x3d, 0xc6, 0xd1, 0xf1, 0x06, 0x38, 0xd2, 0x3c, 0x38, 0x3a,
-	0x51, 0x87, 0xa3, 0x6c, 0x5f, 0x33, 0x1c, 0x1d, 0x0f, 0xa1, 0xff, 0xcd,
-	0xd6, 0x32, 0xfa, 0xb0, 0x9f, 0x39, 0xbd, 0x49, 0xa5, 0xd5, 0xe4, 0xf8,
-	0x24, 0x55, 0x90, 0x73, 0x92, 0x58, 0xa2, 0xb4, 0xe0, 0x76, 0x05, 0x81,
-	0xbf, 0x2c, 0x8f, 0xc9, 0xae, 0x06, 0xe7, 0xaa, 0x24, 0x9c, 0x79, 0x93,
-	0x73, 0x99, 0xc9, 0x57, 0x66, 0x1f, 0x32, 0x36, 0xee, 0x6d, 0xe8, 0x3a,
-	0x7e, 0x0b, 0xb1, 0x8c, 0xbc, 0xbb, 0x81, 0x73, 0x5b, 0xe2, 0x74, 0xdf,
-	0x1a, 0xa0, 0x7b, 0xd6, 0x7e, 0xba, 0x6b, 0x0d, 0xd2, 0x03, 0x0b, 0x6d,
-	0x60, 0x0e, 0xf8, 0x5e, 0xcc, 0x81, 0x46, 0x33, 0x31, 0x2e, 0x53, 0xda,
-	0x4f, 0x95, 0x92, 0xc2, 0x35, 0xb0, 0x03, 0x0c, 0x35, 0xc6, 0x4e, 0xa6,
-	0x0e, 0x3b, 0xb2, 0x0e, 0x30, 0xb3, 0xe4, 0xb7, 0xad, 0xed, 0x32, 0xf8,
-	0x5d, 0x0d, 0xc6, 0x56, 0x58, 0xc4, 0x91, 0x24, 0x47, 0x67, 0x42, 0x90,
-	0x59, 0xb7, 0x18, 0x53, 0x3c, 0x17, 0x3c, 0x7e, 0xda, 0xf5, 0x41, 0x96,
-	0x39, 0x4f, 0x09, 0x1b, 0xf4, 0x94, 0xa9, 0xc7, 0x33, 0x64, 0x5f, 0xd6,
-	0xcc, 0x31, 0x91, 0xeb, 0xb6, 0x54, 0xf6, 0x9e, 0x31, 0x91, 0xe1, 0xb1,
-	0x57, 0x78, 0xf4, 0xca, 0xa1, 0x76, 0xaa, 0x38, 0x31, 0x4c, 0x85, 0x55,
-	0xdb, 0x7e, 0xc8, 0xfc, 0x7f, 0xcd, 0x84, 0xcc, 0xfe, 0xdb, 0xae, 0xc4,
-	0x74, 0x5a, 0x36, 0x55, 0xdf, 0xee, 0x08, 0x7c, 0x31, 0x47, 0xa4, 0x77,
-	0x37, 0xaa, 0xaf, 0xc4, 0xbf, 0xe3, 0xbb, 0xbf, 0x04, 0x97, 0x59, 0xab,
-	0x96, 0x85, 0xed, 0xf8, 0xd2, 0xd8, 0xc2, 0x2a, 0xce, 0x7e, 0x7b, 0xfc,
-	0xea, 0xf9, 0xd5, 0x5c, 0x1f, 0x4b, 0xd8, 0x94, 0x4e, 0x76, 0x68, 0x79,
-	0x3c, 0xf7, 0x5c, 0x98, 0x86, 0x19, 0x97, 0x38, 0x83, 0x6b, 0x6c, 0x34,
-	0x2c, 0xce, 0x38, 0xd9, 0xcd, 0x78, 0xc8, 0x0a, 0x3b, 0xfd, 0xd4, 0x91,
-	0x09, 0x9a, 0x2c, 0xa7, 0xf9, 0x53, 0x3f, 0x7e, 0xb5, 0xb9, 0xe3, 0xe1,
-	0x48, 0xe3, 0x37, 0x37, 0xff, 0xa8, 0xd5, 0x9d, 0xe6, 0xba, 0x33, 0x5b,
-	0xd6, 0x55, 0xe7, 0x12, 0xfd, 0x03, 0x69, 0xae, 0x1b, 0xa3, 0xbc, 0x57,
-	0x00, 0x00, 0x00 };
+	0x1f, 0x8b, 0x08, 0x00, 0x45, 0x30, 0xe7, 0x45, 0x00, 0x03, 0xdc, 0x5a,
+	0x6b, 0x6c, 0x1c, 0xd7, 0x75, 0x3e, 0x33, 0x3b, 0x4b, 0xae, 0xc8, 0x15,
+	0x35, 0xa2, 0xc6, 0xf4, 0x5a, 0xa2, 0xed, 0x5d, 0x72, 0x28, 0x12, 0x96,
+	0xec, 0x6e, 0x68, 0xda, 0x62, 0x8c, 0x8d, 0xb4, 0xd9, 0xa5, 0x0c, 0xa1,
+	0x65, 0x6b, 0x4a, 0xa2, 0x6d, 0x05, 0x11, 0x02, 0x62, 0x49, 0xa9, 0x46,
+	0x50, 0xb7, 0x92, 0xab, 0xb6, 0x81, 0x6b, 0x4b, 0x6b, 0x92, 0x6a, 0x09,
+	0x84, 0xe6, 0x08, 0x11, 0x43, 0x19, 0xa9, 0x11, 0x10, 0xa4, 0x1c, 0xbb,
+	0xc0, 0xb6, 0x2b, 0xbf, 0x05, 0x34, 0x2e, 0x15, 0x4a, 0x6e, 0xd4, 0x34,
+	0x30, 0xfc, 0xa7, 0xa8, 0x51, 0x38, 0xad, 0xe1, 0x04, 0xa8, 0x9b, 0x16,
+	0x45, 0xd0, 0xfc, 0x88, 0x0a, 0xdb, 0xd9, 0x7e, 0xdf, 0x9d, 0x3b, 0xcb,
+	0xe1, 0x92, 0xd4, 0xc3, 0x8f, 0xfe, 0x28, 0x81, 0xe5, 0xcc, 0xbd, 0x73,
+	0xe7, 0xde, 0x73, 0xcf, 0xe3, 0x3b, 0x8f, 0xb9, 0x77, 0x8a, 0x34, 0x88,
+	0xfe, 0x5b, 0x8f, 0x5f, 0xf2, 0xd1, 0x3f, 0x18, 0xbe, 0xab, 0xe7, 0xae,
+	0xbb, 0x71, 0x7b, 0xb7, 0x19, 0xb1, 0x22, 0xec, 0xe7, 0x3f, 0x07, 0xbf,
+	0x6e, 0x7d, 0xbf, 0xda, 0x9f, 0x8d, 0xdf, 0x65, 0xfc, 0x86, 0x7e, 0x2e,
+	0x62, 0xac, 0x31, 0x26, 0xfc, 0x57, 0xa9, 0x5c, 0xfd, 0xb9, 0x49, 0x5a,
+	0xae, 0xf2, 0x3c, 0xe2, 0x2f, 0xa9, 0x68, 0xe6, 0x4f, 0x62, 0x66, 0x46,
+	0x8e, 0xe7, 0x5c, 0x89, 0x45, 0x32, 0x1f, 0x1c, 0x1f, 0x76, 0x45, 0xb2,
+	0xa5, 0x6d, 0xc9, 0xbc, 0x7c, 0x5c, 0x29, 0x3a, 0x96, 0xb0, 0xff, 0xd6,
+	0xcc, 0x47, 0x27, 0xde, 0xd8, 0x91, 0xfa, 0xc5, 0x6c, 0x44, 0x62, 0x76,
+	0xe6, 0x15, 0xb1, 0xb7, 0x4a, 0xac, 0x15, 0xef, 0x3c, 0xdb, 0x99, 0x33,
+	0xa4, 0x29, 0x98, 0xeb, 0x83, 0xca, 0x1b, 0x9d, 0x52, 0xdc, 0x9c, 0x89,
+	0x89, 0x99, 0xe9, 0x78, 0x27, 0x17, 0xb1, 0x87, 0x22, 0x19, 0x5b, 0x16,
+	0xca, 0x32, 0x30, 0x32, 0x29, 0xb1, 0x58, 0x66, 0x22, 0x56, 0xdf, 0x21,
+	0xb1, 0x68, 0x66, 0xe8, 0xf8, 0xf7, 0xdc, 0x13, 0x15, 0xd3, 0x75, 0x93,
+	0xa3, 0x12, 0xef, 0x1d, 0xef, 0xc1, 0xf3, 0x52, 0x0a, 0x04, 0xef, 0x10,
+	0xd3, 0x2d, 0xc6, 0x23, 0x6e, 0x4c, 0x72, 0x65, 0x57, 0xf2, 0x65, 0x91,
+	0x1f, 0x96, 0x0c, 0x19, 0x77, 0x5b, 0x64, 0x74, 0xfb, 0x47, 0x95, 0x2c,
+	0x68, 0xf9, 0x3b, 0x77, 0xe8, 0xf8, 0x73, 0x2e, 0xe9, 0x9d, 0x8e, 0xf9,
+	0xf4, 0x8e, 0xd7, 0x0f, 0xbb, 0x96, 0xcc, 0x95, 0xd8, 0x77, 0xd0, 0x64,
+	0x9f, 0x95, 0xf9, 0x7e, 0xc3, 0xb8, 0x1b, 0xd7, 0x7d, 0x13, 0xd9, 0x1c,
+	0xe6, 0x9b, 0x2f, 0x71, 0xec, 0xbb, 0x5f, 0x18, 0x76, 0x1d, 0xdd, 0x9f,
+	0xdd, 0x91, 0x73, 0x13, 0xe8, 0x6f, 0xd5, 0xcf, 0x9e, 0x79, 0x74, 0xd8,
+	0x75, 0xf5, 0x33, 0xcb, 0xca, 0xb9, 0x5d, 0xba, 0xbf, 0xb4, 0x6b, 0xd8,
+	0xdd, 0xae, 0xfb, 0x7f, 0xbc, 0x2b, 0xe7, 0xa6, 0x75, 0x7f, 0xef, 0x57,
+	0x86, 0xdd, 0x1e, 0xdd, 0xff, 0xf6, 0xce, 0x9c, 0xdb, 0xab, 0xfb, 0x4f,
+	0xf5, 0x0e, 0xbb, 0xb6, 0x9c, 0x2d, 0x25, 0xf1, 0x9b, 0x88, 0x59, 0x1d,
+	0x19, 0x3d, 0xe6, 0x59, 0xd0, 0x9b, 0xc5, 0x98, 0x3e, 0xf4, 0xef, 0xc1,
+	0xaf, 0x1f, 0xbf, 0xf2, 0x06, 0x69, 0x1a, 0xc0, 0xf3, 0x0f, 0xb7, 0xf8,
+	0x3c, 0x04, 0xaf, 0xbc, 0x98, 0xbc, 0x17, 0x49, 0xc8, 0x1b, 0x9d, 0xef,
+	0x81, 0x97, 0xb6, 0x9c, 0x2b, 0x8b, 0x31, 0xd0, 0x99, 0x00, 0x0f, 0x1d,
+	0x79, 0xb1, 0xdc, 0x28, 0x91, 0x6f, 0x45, 0xc0, 0xa3, 0xaf, 0x4a, 0xc1,
+	0x89, 0xc9, 0xc6, 0x19, 0x43, 0xda, 0xba, 0xd7, 0x49, 0xd6, 0x2e, 0x4a,
+	0xbe, 0x13, 0x52, 0x9f, 0x72, 0xc4, 0x9a, 0x59, 0xdc, 0x68, 0xa2, 0xc7,
+	0x94, 0x54, 0xa2, 0x80, 0x19, 0x47, 0xce, 0xbe, 0x4b, 0x1d, 0xa5, 0x7c,
+	0xf1, 0x4b, 0x4a, 0x7e, 0xf2, 0x0e, 0x19, 0xb2, 0x49, 0xe7, 0x9f, 0xdd,
+	0xea, 0xaf, 0x19, 0x33, 0x72, 0x67, 0x06, 0xe5, 0xa4, 0x17, 0x37, 0xf2,
+	0x67, 0x76, 0x4a, 0x2e, 0x2d, 0x8e, 0x29, 0x1d, 0xea, 0xdd, 0xf9, 0xd2,
+	0xa0, 0x8c, 0x7b, 0x62, 0xe4, 0x3c, 0x4b, 0x46, 0x4b, 0x2d, 0x78, 0xde,
+	0xa4, 0xc6, 0xa2, 0xaf, 0x35, 0x22, 0x1d, 0x76, 0x5e, 0x62, 0xe8, 0xb7,
+	0xd1, 0xdf, 0x6c, 0xf4, 0xa9, 0x39, 0x54, 0x7f, 0x72, 0x4c, 0xe2, 0xd8,
+	0x9b, 0xa3, 0xc7, 0x56, 0x2a, 0xb9, 0xb4, 0x8d, 0x71, 0x83, 0x32, 0xe6,
+	0x39, 0x32, 0x84, 0xeb, 0xa8, 0xc7, 0xf5, 0x13, 0xd0, 0xb1, 0xb7, 0x8e,
+	0x17, 0xa6, 0xd5, 0x7c, 0xc9, 0x48, 0x86, 0xf3, 0xb5, 0x62, 0xdc, 0x05,
+	0xd0, 0x65, 0x88, 0xa5, 0x64, 0x9b, 0x95, 0xc2, 0xa4, 0x21, 0xe4, 0x5b,
+	0x41, 0xf1, 0xb0, 0x0f, 0xf4, 0x5b, 0xe2, 0x76, 0x1b, 0x32, 0xec, 0xde,
+	0x2c, 0x45, 0x1b, 0xed, 0xd2, 0x79, 0x33, 0xe7, 0xd5, 0x4b, 0xde, 0x4a,
+	0x62, 0xff, 0x94, 0xfd, 0x90, 0x8c, 0xe1, 0x1d, 0xd3, 0xe5, 0x98, 0x8f,
+	0xb0, 0x77, 0xb4, 0xf1, 0x6e, 0x5d, 0xe6, 0xa0, 0x5c, 0x9a, 0x2c, 0x9a,
+	0xb9, 0x72, 0x8b, 0x44, 0x66, 0x52, 0xd0, 0xfe, 0x71, 0x33, 0xff, 0xbc,
+	0x25, 0xd1, 0x29, 0xea, 0x97, 0xd8, 0x91, 0xcc, 0x84, 0xb9, 0xbb, 0x7c,
+	0xde, 0xcc, 0x97, 0xf9, 0x0e, 0xc6, 0x96, 0x4c, 0xf0, 0x96, 0xf7, 0xdb,
+	0xc0, 0x4b, 0xea, 0x36, 0xdf, 0x81, 0x1c, 0xb0, 0x87, 0x17, 0x3d, 0xc8,
+	0x45, 0xc9, 0x29, 0x09, 0x39, 0x89, 0xd1, 0xd7, 0x19, 0x93, 0xb1, 0x69,
+	0x4b, 0x0a, 0xe9, 0x9b, 0x15, 0xe7, 0x0b, 0xe9, 0x25, 0x9a, 0x46, 0x27,
+	0x6b, 0x69, 0xe2, 0x7b, 0xa4, 0xc9, 0xa7, 0x65, 0x6c, 0x9a, 0xb4, 0xf9,
+	0xb4, 0x9c, 0x9c, 0x24, 0x8d, 0x5c, 0x87, 0xf4, 0x90, 0xae, 0x80, 0x26,
+	0xbe, 0x43, 0x9a, 0x36, 0x61, 0x7e, 0x65, 0xc0, 0x46, 0x1f, 0x68, 0x18,
+	0xf3, 0x2c, 0xc8, 0x26, 0x2e, 0x05, 0xbb, 0x68, 0x8c, 0xf5, 0x6e, 0x4b,
+	0xc0, 0xaa, 0x8d, 0xd1, 0x5e, 0xd2, 0xeb, 0x42, 0x7e, 0x75, 0x4a, 0xce,
+	0x66, 0x66, 0x9c, 0x3c, 0xc3, 0x78, 0xae, 0x8d, 0xfb, 0x92, 0x2d, 0xe3,
+	0x6a, 0x3e, 0xd2, 0xf3, 0x59, 0xcc, 0x43, 0x7a, 0x2f, 0x43, 0x57, 0x7b,
+	0xa0, 0xa3, 0x69, 0xf9, 0xdb, 0xf2, 0x76, 0x79, 0xbd, 0xdc, 0x25, 0xaf,
+	0xc1, 0x7e, 0x5f, 0x2d, 0x27, 0xe5, 0x95, 0x72, 0xab, 0xbc, 0x5c, 0x4e,
+	0xc8, 0x4b, 0x4a, 0x7f, 0xfb, 0x44, 0x9a, 0x94, 0x4e, 0xc7, 0x6e, 0x86,
+	0x3e, 0xb6, 0x40, 0x1f, 0x9b, 0x61, 0x4f, 0x1b, 0x61, 0xab, 0xdf, 0x06,
+	0x0f, 0xa7, 0x3b, 0x25, 0xbb, 0x09, 0xfd, 0xb7, 0x65, 0x2c, 0xa5, 0x23,
+	0x16, 0x9e, 0x8f, 0x4d, 0x46, 0x25, 0x6f, 0x9f, 0x95, 0xf7, 0xa7, 0x2c,
+	0x19, 0x2b, 0x3f, 0x79, 0x9b, 0xaf, 0xb3, 0x6c, 0xcf, 0xca, 0x45, 0xf4,
+	0xe5, 0xed, 0x59, 0xb9, 0xb4, 0xd5, 0x94, 0xd1, 0xe9, 0xef, 0x4a, 0xee,
+	0xf9, 0xb3, 0xf2, 0xd3, 0xbf, 0x16, 0x19, 0x00, 0xef, 0xcd, 0xee, 0xff,
+	0xaa, 0x64, 0x6d, 0xec, 0xb1, 0x7b, 0xbb, 0x92, 0x89, 0xd9, 0x4d, 0x3d,
+	0x4e, 0x02, 0x57, 0x2c, 0x23, 0xef, 0xbd, 0x00, 0x6c, 0x69, 0x34, 0x72,
+	0xa7, 0x45, 0x86, 0x4f, 0x57, 0x64, 0x38, 0x1d, 0x95, 0xc7, 0xec, 0x8a,
+	0xf4, 0xa5, 0xeb, 0xe4, 0xa8, 0x4d, 0xac, 0x39, 0x6e, 0x04, 0xb8, 0xfe,
+	0xed, 0xf2, 0x09, 0xdc, 0xb3, 0x4f, 0x64, 0x5a, 0xdd, 0xfb, 0xfd, 0xc5,
+	0x72, 0x54, 0xb2, 0x4e, 0x31, 0x61, 0x49, 0x9b, 0xe9, 0xd3, 0xf4, 0xcd,
+	0xe0, 0x19, 0x78, 0x35, 0x04, 0x2c, 0xf5, 0xed, 0xaf, 0x30, 0xb9, 0xee,
+	0x4a, 0x56, 0x75, 0x47, 0x29, 0x3b, 0xe8, 0x34, 0x79, 0x9d, 0x1c, 0x32,
+	0x32, 0x8e, 0xb4, 0x29, 0xbc, 0xe8, 0xc1, 0x98, 0x5e, 0x63, 0x7f, 0x99,
+	0x7a, 0x8e, 0xfb, 0x12, 0x69, 0xdd, 0x8c, 0xb1, 0x16, 0xae, 0x59, 0x4d,
+	0x73, 0x98, 0x4e, 0xce, 0x45, 0x3a, 0x79, 0x7d, 0x21, 0x44, 0xe7, 0x5f,
+	0x56, 0xef, 0xa7, 0x43, 0xf7, 0xc5, 0xf2, 0x0f, 0x1a, 0x7c, 0xfa, 0xc8,
+	0xcf, 0x5e, 0xe8, 0xe3, 0x37, 0xf4, 0x5a, 0xb8, 0x2f, 0x71, 0x8d, 0xb3,
+	0x15, 0x5f, 0xa7, 0x8a, 0xd7, 0x58, 0xeb, 0x62, 0x68, 0xad, 0x4b, 0xa1,
+	0xb5, 0x2e, 0x85, 0xd6, 0x2a, 0x82, 0xb7, 0xb2, 0xc1, 0x74, 0xa3, 0xc0,
+	0x27, 0xf6, 0x4c, 0x60, 0xce, 0x67, 0x21, 0x97, 0x9f, 0x60, 0x4c, 0x46,
+	0x16, 0x3d, 0xf0, 0xe3, 0x74, 0x54, 0xf6, 0xa9, 0x67, 0xbd, 0x9a, 0xae,
+	0xf0, 0xb3, 0x98, 0xec, 0x75, 0x78, 0x1f, 0x3c, 0xb3, 0xc0, 0x63, 0xb6,
+	0xff, 0xe1, 0x16, 0xbf, 0xcd, 0xfb, 0xf3, 0x9a, 0xfe, 0x87, 0xfc, 0xf7,
+	0xca, 0x1f, 0x28, 0x9c, 0x5c, 0x28, 0x13, 0xc7, 0x24, 0x1d, 0x71, 0xe5,
+	0x48, 0x5f, 0x1a, 0x76, 0x65, 0x1b, 0xe9, 0xd1, 0xae, 0x7a, 0xf2, 0x3c,
+	0x6b, 0xba, 0x8d, 0xc0, 0x0a, 0x49, 0x9a, 0xd0, 0xb3, 0x51, 0xb5, 0x97,
+	0x75, 0xa6, 0x4f, 0xb3, 0xcd, 0xf6, 0x80, 0xe9, 0x36, 0xd7, 0xf4, 0xd3,
+	0xde, 0x1b, 0x71, 0x4f, 0xdd, 0x7e, 0x4c, 0xcb, 0x37, 0x8e, 0x36, 0xf1,
+	0xb9, 0x5f, 0xb7, 0x83, 0xe7, 0x39, 0x6b, 0x79, 0xfb, 0xed, 0x2d, 0xcb,
+	0xdb, 0x01, 0x76, 0x84, 0xb1, 0x9d, 0x7b, 0x4d, 0x4a, 0xc4, 0xa5, 0xce,
+	0x45, 0x41, 0x6b, 0x1a, 0xb6, 0x58, 0xaf, 0x69, 0xb8, 0x5d, 0xd3, 0x00,
+	0x5a, 0x31, 0x6e, 0x54, 0xd9, 0x98, 0x12, 0x5f, 0x4d, 0x9b, 0xfc, 0x0e,
+	0xee, 0xd7, 0xab, 0xe7, 0xbe, 0x2d, 0x06, 0x57, 0x31, 0x76, 0x77, 0x52,
+	0xe6, 0x13, 0x90, 0x79, 0x5c, 0xe6, 0xa7, 0xc9, 0xb3, 0x54, 0xe2, 0x71,
+	0x41, 0xbb, 0x94, 0x90, 0xb3, 0x93, 0x92, 0x3d, 0x7c, 0xaa, 0x57, 0xfa,
+	0x60, 0x9f, 0x73, 0x93, 0x57, 0x2a, 0xe0, 0xdb, 0xbd, 0x75, 0xe2, 0x02,
+	0x83, 0xe1, 0xef, 0x7b, 0xa2, 0x12, 0xc9, 0x64, 0xa0, 0x0b, 0x69, 0xe5,
+	0x83, 0x97, 0xfe, 0x2c, 0xeb, 0xfe, 0x65, 0xed, 0x3a, 0xf8, 0x79, 0xcc,
+	0xdb, 0x93, 0x56, 0x7a, 0x13, 0xfe, 0xcb, 0x01, 0x57, 0x72, 0xe9, 0x8f,
+	0xa1, 0x5b, 0x01, 0x4d, 0x81, 0x6d, 0xd0, 0x07, 0x7d, 0x10, 0xf2, 0x6d,
+	0xad, 0xc0, 0x17, 0x07, 0xf2, 0x0b, 0xfc, 0x11, 0xfd, 0x44, 0x82, 0x58,
+	0x0e, 0x5b, 0xa0, 0x6f, 0x88, 0x8b, 0x39, 0x63, 0x69, 0xff, 0x11, 0xd3,
+	0xfe, 0x23, 0x0e, 0xdf, 0xc1, 0xb6, 0xad, 0xdb, 0x8e, 0x6e, 0x27, 0xd0,
+	0x46, 0xec, 0x31, 0x43, 0xbb, 0x7a, 0xeb, 0xf8, 0xc8, 0xb4, 0xf2, 0x49,
+	0xf4, 0x67, 0xf0, 0x14, 0xf4, 0x29, 0xf4, 0x2d, 0xd8, 0x6f, 0x09, 0xeb,
+	0x55, 0x31, 0x9c, 0xf2, 0x08, 0xd3, 0x43, 0x5a, 0xd6, 0x89, 0x09, 0x3f,
+	0x9b, 0x75, 0x48, 0xef, 0x77, 0x20, 0x0f, 0x62, 0x25, 0xe9, 0xbe, 0x15,
+	0xb4, 0x72, 0x3f, 0xff, 0x97, 0xb4, 0x72, 0xbd, 0x5a, 0x7a, 0x3f, 0x2d,
+	0x66, 0x2b, 0xec, 0xc0, 0x9e, 0x33, 0xc0, 0x66, 0x31, 0xf6, 0x77, 0x0e,
+	0x62, 0xcf, 0x03, 0xc0, 0xee, 0x7e, 0x60, 0xf7, 0x1e, 0x60, 0x77, 0x1f,
+	0xb0, 0x3b, 0x0b, 0xec, 0xee, 0x05, 0x6e, 0xf7, 0x00, 0xb7, 0xd3, 0xe0,
+	0x8d, 0x23, 0xb3, 0xc0, 0xf1, 0x59, 0xe8, 0xcb, 0x2c, 0xe6, 0x28, 0xcc,
+	0x88, 0xf1, 0x35, 0xec, 0xe1, 0xe8, 0x54, 0x6a, 0x16, 0xfa, 0x9d, 0x18,
+	0x32, 0xa1, 0x07, 0xe9, 0xbb, 0x61, 0x6f, 0x88, 0x9b, 0xca, 0x83, 0x32,
+	0x0c, 0xbf, 0xdf, 0xb6, 0xb5, 0x1d, 0xfa, 0x84, 0x68, 0x24, 0x11, 0xe8,
+	0x68, 0xbf, 0x14, 0xbc, 0x76, 0xbb, 0xcd, 0xec, 0x42, 0x5f, 0x2a, 0x89,
+	0x18, 0xd5, 0x38, 0x74, 0x3a, 0x65, 0x8c, 0x9c, 0x26, 0x0f, 0x26, 0x81,
+	0x83, 0x15, 0x19, 0x4f, 0x53, 0x4f, 0x2b, 0xf2, 0x5c, 0x3a, 0xd5, 0x5b,
+	0x94, 0x46, 0x39, 0xe9, 0x4c, 0x2a, 0xdf, 0x6f, 0x65, 0x4e, 0x29, 0x1f,
+	0x3a, 0xec, 0xe2, 0x5a, 0x6a, 0x33, 0x0a, 0xa7, 0xb9, 0xd7, 0x76, 0xfc,
+	0xa2, 0x58, 0xf7, 0x57, 0x90, 0x91, 0x25, 0x7d, 0x3d, 0x62, 0x1c, 0xee,
+	0x2c, 0x02, 0x39, 0x53, 0xf6, 0x22, 0x56, 0xcb, 0x4f, 0xb6, 0x27, 0xda,
+	0x4d, 0x4b, 0x86, 0x2c, 0x43, 0x46, 0x61, 0x5f, 0x7d, 0xe9, 0xff, 0xa9,
+	0x9c, 0x74, 0xf8, 0xbc, 0x5e, 0xfe, 0x5c, 0x61, 0x31, 0xd6, 0x9e, 0x9f,
+	0xc6, 0xba, 0x51, 0xf0, 0x9b, 0xeb, 0x72, 0x1e, 0xb4, 0x81, 0x8b, 0x96,
+	0x9b, 0x9a, 0x2d, 0xca, 0x2e, 0xd8, 0xe9, 0x06, 0xc9, 0x6d, 0xaf, 0x93,
+	0xec, 0x40, 0x52, 0x0a, 0x53, 0xbb, 0x80, 0x8d, 0x31, 0x65, 0xab, 0x85,
+	0xc1, 0xa4, 0x3c, 0x36, 0xc5, 0xbe, 0x2c, 0xf6, 0x9a, 0x3a, 0x95, 0x15,
+	0xee, 0xd5, 0x90, 0xec, 0xc1, 0xac, 0x3c, 0xe6, 0x65, 0x65, 0x04, 0xf2,
+	0x3a, 0x0b, 0x5e, 0x1e, 0xf2, 0x5c, 0x79, 0x0e, 0xbe, 0x26, 0x7f, 0x1a,
+	0x58, 0xeb, 0xae, 0x07, 0x2e, 0xa6, 0xce, 0x31, 0xc6, 0x37, 0x19, 0x87,
+	0x82, 0x97, 0x7f, 0x34, 0x45, 0x5e, 0x9a, 0x32, 0x7d, 0xaf, 0x01, 0x3c,
+	0x48, 0x82, 0x77, 0xae, 0xfc, 0xb1, 0x97, 0x3a, 0x9f, 0x35, 0x81, 0xc5,
+	0xe9, 0xde, 0x88, 0x34, 0x24, 0x30, 0xce, 0x1f, 0x93, 0x4f, 0x47, 0x20,
+	0xd7, 0x22, 0xc6, 0xa6, 0xd0, 0xcf, 0x77, 0x1d, 0xfc, 0xb2, 0x18, 0x07,
+	0x5d, 0xb5, 0x53, 0xe7, 0x67, 0x4d, 0x8e, 0x4f, 0x42, 0x3e, 0x36, 0xc6,
+	0x03, 0xf8, 0x6c, 0xde, 0xa7, 0x8d, 0x02, 0x69, 0xf0, 0xa8, 0x53, 0x88,
+	0x49, 0xcb, 0xc4, 0xd4, 0xf6, 0x73, 0xaf, 0x0b, 0xd7, 0xf9, 0x22, 0xc6,
+	0x7f, 0x88, 0x38, 0xdc, 0x96, 0x79, 0xc8, 0xe5, 0xa7, 0xe0, 0x55, 0x36,
+	0xe1, 0xb7, 0x0b, 0x33, 0xa9, 0x73, 0x8b, 0x26, 0xef, 0xdd, 0xe2, 0xa8,
+	0xd9, 0x23, 0xd2, 0x4c, 0x7e, 0xa5, 0xc1, 0x2b, 0xd7, 0x36, 0xcd, 0xb4,
+	0xf2, 0x65, 0xbe, 0x2d, 0xdf, 0x05, 0x9a, 0xa0, 0xf3, 0xdd, 0x61, 0x9b,
+	0xa0, 0xaf, 0x0d, 0x6c, 0x22, 0x95, 0x98, 0x35, 0xe1, 0x9f, 0xbb, 0x2d,
+	0x39, 0xa5, 0xda, 0xe0, 0xd1, 0x60, 0x2a, 0x91, 0x35, 0x11, 0x33, 0x95,
+	0xba, 0xe4, 0xac, 0xc7, 0xf1, 0x49, 0x85, 0x51, 0xfe, 0x78, 0xc4, 0x7a,
+	0x1e, 0xe3, 0xc5, 0x2e, 0xd0, 0xec, 0xdb, 0xc9, 0xdc, 0xa4, 0xa3, 0x9e,
+	0x9d, 0xf4, 0xfc, 0xb8, 0xd0, 0x44, 0xec, 0x38, 0x8b, 0xd8, 0x31, 0xaf,
+	0x6c, 0xc6, 0xce, 0x22, 0xd7, 0x80, 0xce, 0xfb, 0xf6, 0x32, 0x5f, 0xba,
+	0x4f, 0x86, 0xcf, 0x7c, 0x3f, 0x6e, 0x22, 0xce, 0x2a, 0x38, 0xa4, 0x8b,
+	0xe3, 0xcf, 0x81, 0x4e, 0xf2, 0x4e, 0x86, 0x18, 0x57, 0x21, 0x16, 0x7e,
+	0x84, 0x32, 0x1e, 0xed, 0x7e, 0x88, 0x7c, 0x2b, 0x82, 0xe8, 0x53, 0x3e,
+	0x8e, 0x49, 0x91, 0x71, 0xe8, 0x62, 0xe4, 0x09, 0x19, 0x9a, 0xa7, 0x2f,
+	0xc4, 0xcf, 0x23, 0x26, 0x02, 0xc7, 0x94, 0xcf, 0x6a, 0x87, 0x3e, 0x14,
+	0xc1, 0xef, 0x8d, 0x3a, 0x0e, 0x3b, 0x08, 0xf9, 0xf6, 0x43, 0xfe, 0x19,
+	0x19, 0x39, 0x33, 0x42, 0xdd, 0xee, 0x9a, 0x97, 0x54, 0xd7, 0x49, 0xd9,
+	0x66, 0xcf, 0xc1, 0x06, 0xb3, 0x83, 0x95, 0x5d, 0x66, 0x86, 0xef, 0x9c,
+	0xc0, 0x3b, 0xb8, 0xce, 0x8f, 0xc8, 0xd1, 0x32, 0xfb, 0x9e, 0x05, 0xdf,
+	0x11, 0x17, 0xf7, 0x1c, 0xd4, 0xf6, 0x80, 0xf9, 0xac, 0x60, 0xbe, 0x11,
+	0x3d, 0x1f, 0xc7, 0x71, 0x0c, 0xdf, 0x59, 0x9a, 0x77, 0x37, 0x7d, 0x22,
+	0x30, 0xa8, 0xc3, 0xac, 0xec, 0x8a, 0xe2, 0xf9, 0x73, 0x3d, 0xbc, 0xc7,
+	0x3c, 0xf0, 0x89, 0xb6, 0xdb, 0x8f, 0xb1, 0x83, 0x98, 0x73, 0x9d, 0xb4,
+	0xb5, 0x04, 0xf4, 0x52, 0x3f, 0x18, 0xab, 0xb0, 0x3d, 0xb2, 0xc9, 0x97,
+	0xd1, 0xab, 0x11, 0xdf, 0xc7, 0xcc, 0xa2, 0x4d, 0x3b, 0x3c, 0x26, 0x79,
+	0x2f, 0x85, 0x7d, 0x42, 0x06, 0xe5, 0x51, 0xbd, 0x47, 0xc8, 0x69, 0xe0,
+	0x29, 0xf0, 0x41, 0x8a, 0x3e, 0x6f, 0xc8, 0x17, 0xf2, 0xe4, 0x38, 0x6c,
+	0xe0, 0x71, 0x8c, 0x41, 0xbc, 0xab, 0x78, 0x60, 0x6f, 0xf2, 0xe3, 0xf5,
+	0x54, 0x31, 0xcb, 0xbc, 0xb3, 0x99, 0xba, 0x0d, 0xdc, 0x2a, 0x0f, 0xd8,
+	0x9c, 0x7b, 0xd6, 0x64, 0x7e, 0x92, 0x4a, 0x5e, 0x88, 0xec, 0x67, 0xbb,
+	0x6b, 0xd6, 0x84, 0x8c, 0x20, 0xc7, 0xdc, 0xf6, 0x76, 0x8d, 0x55, 0xef,
+	0x28, 0x5d, 0xa6, 0xde, 0x17, 0xbc, 0x6d, 0xf6, 0x43, 0x42, 0x5d, 0x76,
+	0xa0, 0x17, 0xc4, 0x0b, 0x5e, 0x2d, 0xf8, 0xee, 0x04, 0x74, 0x61, 0xbd,
+	0xa6, 0x9d, 0xf7, 0x96, 0xcc, 0xda, 0x58, 0xc3, 0xfb, 0x8f, 0x0d, 0x7e,
+	0x1f, 0xef, 0x19, 0x33, 0x05, 0x72, 0x0c, 0x68, 0xa5, 0x3c, 0x6b, 0x65,
+	0xf8, 0x24, 0x68, 0x67, 0x3f, 0xae, 0xf3, 0xc7, 0x60, 0xa7, 0xc0, 0x94,
+	0x9e, 0x8e, 0xc4, 0x45, 0x8c, 0xcf, 0x03, 0xf7, 0x8b, 0x16, 0x9f, 0x5d,
+	0x31, 0x96, 0xde, 0x31, 0x19, 0x27, 0x23, 0x1e, 0xbf, 0x60, 0x7c, 0x0d,
+	0xb1, 0x4e, 0x6e, 0xfe, 0x8a, 0x91, 0x87, 0x5e, 0xcc, 0x7b, 0x77, 0x43,
+	0x9f, 0x68, 0x57, 0x36, 0xd6, 0x4e, 0x25, 0xfe, 0xc9, 0x6c, 0x4f, 0xce,
+	0x01, 0x03, 0x0e, 0x81, 0xb1, 0xbe, 0x2c, 0x5d, 0x25, 0xdb, 0x45, 0x33,
+	0xaa, 0xf1, 0x8f, 0xed, 0x94, 0xfd, 0xb0, 0xc0, 0x58, 0x1a, 0xf6, 0x80,
+	0xcf, 0x7b, 0x64, 0xb8, 0x9c, 0x91, 0xc2, 0x99, 0x6d, 0xf6, 0x28, 0x72,
+	0xf5, 0x25, 0xda, 0x89, 0x75, 0x45, 0x60, 0x1d, 0xfc, 0xb7, 0x27, 0xc5,
+	0xba, 0x0c, 0x31, 0xaf, 0x03, 0xfa, 0x84, 0xbe, 0xd2, 0x92, 0x4e, 0xde,
+	0xbf, 0x62, 0x3f, 0xf4, 0xdb, 0xcb, 0xf7, 0x34, 0x2f, 0xd7, 0xde, 0xd3,
+	0xee, 0xea, 0x9e, 0x88, 0x31, 0xf0, 0x03, 0x1e, 0xfc, 0x00, 0x74, 0xfa,
+	0x75, 0x0f, 0x7e, 0xc0, 0x83, 0x1f, 0x80, 0x3d, 0xbe, 0x02, 0x7d, 0x7c,
+	0xd9, 0x83, 0x2f, 0xf0, 0xe0, 0x0b, 0x3c, 0xf8, 0x02, 0x2f, 0x07, 0xd9,
+	0x11, 0xef, 0xe9, 0x4b, 0x0e, 0x54, 0xfd, 0xa7, 0x1f, 0x83, 0xdd, 0xa2,
+	0xe3, 0x1a, 0xd8, 0xae, 0xbd, 0x59, 0x46, 0xbb, 0x98, 0x13, 0x35, 0xe0,
+	0xda, 0x88, 0x2b, 0x62, 0x98, 0xae, 0x2f, 0x69, 0xdb, 0x79, 0x1c, 0x74,
+	0x01, 0x17, 0xba, 0xbe, 0x08, 0xdd, 0x44, 0x1c, 0xe1, 0xfe, 0x86, 0x8e,
+	0x7f, 0x7e, 0x64, 0xf9, 0xba, 0xd9, 0x88, 0xbe, 0xfb, 0xd0, 0xd7, 0x88,
+	0x31, 0x47, 0x31, 0x86, 0xf1, 0x53, 0x93, 0xee, 0x0b, 0x8f, 0x63, 0x1c,
+	0xf5, 0x00, 0xd6, 0x4a, 0x61, 0x5c, 0x13, 0xe6, 0x6e, 0xc5, 0x98, 0x9d,
+	0x18, 0x73, 0x2b, 0xda, 0x8c, 0xb9, 0xb7, 0xa0, 0x7d, 0x4f, 0xcd, 0x3b,
+	0xb7, 0xa3, 0xef, 0x4b, 0x35, 0x7d, 0x8b, 0xe8, 0xeb, 0x41, 0xdf, 0x45,
+	0xfd, 0x5e, 0x11, 0xed, 0x96, 0x9a, 0x31, 0x97, 0xd1, 0x87, 0xb8, 0xd9,
+	0xfe, 0x7b, 0x5c, 0xfb, 0x71, 0x25, 0x4d, 0xc1, 0x33, 0xc6, 0xcd, 0xc8,
+	0x41, 0xab, 0xb1, 0xef, 0x5b, 0x8c, 0x0b, 0xe1, 0x7b, 0x7f, 0x6c, 0xf9,
+	0x71, 0xe3, 0x77, 0x6d, 0x5f, 0x57, 0x83, 0xf6, 0x8f, 0x6a, 0xda, 0x1c,
+	0xfb, 0xdf, 0x35, 0x7d, 0x3b, 0x36, 0x2e, 0x6f, 0xdf, 0x59, 0xb7, 0xf2,
+	0x9d, 0x89, 0x9a, 0x31, 0x2f, 0x37, 0x2f, 0x6f, 0xff, 0xe9, 0x2a, 0xef,
+	0xec, 0xd9, 0xb0, 0xbc, 0xef, 0xd1, 0x4d, 0x35, 0x63, 0xa0, 0x53, 0x0e,
+	0x72, 0xab, 0x60, 0xfc, 0x03, 0x37, 0xf9, 0xcf, 0xc9, 0xdf, 0x5a, 0x5d,
+	0x52, 0x5b, 0x47, 0xdb, 0x84, 0x1c, 0x2e, 0x18, 0xb0, 0x39, 0xdb, 0xcc,
+	0x5c, 0x32, 0xf2, 0xd0, 0xa9, 0x5c, 0x39, 0x98, 0x8f, 0xb6, 0x5c, 0x5b,
+	0xdb, 0x08, 0x6a, 0x1a, 0x8c, 0xbb, 0xe2, 0xd0, 0x9b, 0xfd, 0x90, 0x71,
+	0x6a, 0xa2, 0x28, 0x4b, 0x36, 0xdc, 0x66, 0xae, 0x65, 0xc3, 0x4f, 0x6b,
+	0xdc, 0x7a, 0x0a, 0x74, 0x56, 0x64, 0x20, 0x5d, 0x4f, 0xff, 0xa4, 0xf1,
+	0x8c, 0x58, 0x54, 0xa9, 0x44, 0xb6, 0x56, 0xe4, 0x48, 0xfa, 0xc3, 0x8a,
+	0x28, 0x1c, 0x9c, 0x50, 0x58, 0x94, 0x34, 0xdb, 0x21, 0x23, 0x1b, 0xb9,
+	0x8d, 0x23, 0x43, 0x0e, 0xfd, 0xd9, 0x31, 0xc6, 0x29, 0x27, 0x7c, 0x9c,
+	0x25, 0x16, 0xa1, 0x8d, 0xbc, 0xae, 0x70, 0xda, 0x50, 0x31, 0x70, 0x61,
+	0x9e, 0xd8, 0x4e, 0x3c, 0x85, 0xdf, 0xb6, 0x39, 0xef, 0x6a, 0x78, 0x19,
+	0x8b, 0x32, 0x3e, 0xb4, 0xdc, 0x17, 0xe0, 0x1b, 0xf9, 0x8c, 0x71, 0x04,
+	0xee, 0x4b, 0xaa, 0xae, 0x56, 0x5c, 0xbe, 0x97, 0xcd, 0xcc, 0x43, 0xae,
+	0x63, 0x7f, 0xab, 0x63, 0x54, 0xbb, 0x79, 0x6d, 0x7b, 0xde, 0x5b, 0xb5,
+	0xe7, 0x40, 0xdf, 0x56, 0xab, 0x59, 0xbc, 0xa3, 0xf8, 0xff, 0x52, 0x39,
+	0x75, 0xaa, 0x08, 0xfb, 0x59, 0x50, 0x39, 0x7a, 0x20, 0x0b, 0xc6, 0x3c,
+	0xa9, 0x67, 0x66, 0xe9, 0x2d, 0x54, 0x8e, 0xc2, 0xfc, 0xa4, 0x22, 0xbb,
+	0xd3, 0xff, 0xa6, 0xf6, 0x9e, 0x35, 0x3b, 0xeb, 0x18, 0x63, 0x2c, 0x78,
+	0xe4, 0x53, 0x1a, 0xcf, 0x11, 0xfb, 0xa7, 0x7f, 0x26, 0x79, 0x87, 0x7d,
+	0xbf, 0xac, 0xcc, 0x21, 0x36, 0x52, 0xf1, 0x92, 0x8a, 0x0f, 0x18, 0xef,
+	0x1d, 0x01, 0x8f, 0xc8, 0xc7, 0x01, 0xf0, 0x36, 0x88, 0x19, 0xfe, 0x91,
+	0xbe, 0x58, 0x96, 0xc7, 0xd1, 0xc8, 0xb4, 0x4a, 0x97, 0x30, 0xa7, 0x89,
+	0xf9, 0xe8, 0xe3, 0xe8, 0x47, 0xd8, 0x5f, 0x88, 0x32, 0xb6, 0xf3, 0x63,
+	0x83, 0x08, 0xd6, 0xb3, 0x80, 0x83, 0xef, 0x0a, 0x63, 0x9a, 0x61, 0x25,
+	0x03, 0x62, 0x29, 0x9f, 0xb1, 0x2f, 0xa6, 0x63, 0xef, 0xb8, 0x8e, 0xb5,
+	0x6d, 0x1d, 0x6b, 0x93, 0x0e, 0xd6, 0x2d, 0x83, 0x38, 0x82, 0x72, 0xba,
+	0x70, 0xdc, 0xdc, 0xca, 0x38, 0xa2, 0x49, 0x56, 0x8f, 0x23, 0x02, 0x9a,
+	0x76, 0x82, 0x26, 0xc6, 0x7d, 0xaa, 0x4e, 0xd5, 0xec, 0xd7, 0xc6, 0x48,
+	0x43, 0xe0, 0x27, 0x95, 0x3f, 0x9e, 0x80, 0xeb, 0xc3, 0xde, 0x10, 0x48,
+	0x02, 0xdb, 0x73, 0x93, 0x3b, 0xb5, 0xdf, 0x65, 0x0e, 0xc1, 0xf8, 0xdd,
+	0xd7, 0xd3, 0x5c, 0x7a, 0x34, 0x98, 0xa7, 0x05, 0x9e, 0x32, 0x54, 0x43,
+	0xe3, 0x5a, 0x8c, 0x7b, 0x82, 0x18, 0x68, 0x8f, 0x8e, 0x81, 0xfa, 0xe5,
+	0x88, 0xe7, 0xe7, 0x0c, 0x03, 0xa5, 0x01, 0xf4, 0x29, 0xda, 0x13, 0x8c,
+	0x35, 0x4d, 0x93, 0xb1, 0x66, 0x0a, 0xc9, 0x87, 0xbf, 0x97, 0xb6, 0xad,
+	0xac, 0x65, 0x06, 0x7b, 0x69, 0xbc, 0xb0, 0x7c, 0x2f, 0xbb, 0x94, 0xde,
+	0x9b, 0xe0, 0x9d, 0x8f, 0x4d, 0x9c, 0xf3, 0x7c, 0x94, 0xb8, 0x35, 0x50,
+	0x1a, 0x54, 0xf3, 0x8e, 0xaf, 0x98, 0x57, 0xb0, 0xc7, 0x03, 0x6b, 0x3c,
+	0xe3, 0xfe, 0x19, 0x5b, 0xd8, 0x7a, 0xff, 0x81, 0x0c, 0x2f, 0x63, 0xce,
+	0x2e, 0xa3, 0xa0, 0xe2, 0xb6, 0x83, 0x4a, 0x1e, 0x85, 0xd2, 0x10, 0xae,
+	0xb4, 0x17, 0x35, 0x8f, 0xb2, 0x99, 0x51, 0x25, 0x83, 0x11, 0xb5, 0xc7,
+	0xb9, 0xd2, 0x23, 0x88, 0xd7, 0xbe, 0x0e, 0x3f, 0x18, 0xae, 0x2b, 0x3a,
+	0x18, 0x43, 0x5e, 0x15, 0x43, 0x78, 0x4a, 0x9a, 0x59, 0x33, 0xbc, 0x82,
+	0x35, 0xb8, 0xe7, 0x38, 0xe4, 0x6f, 0xf8, 0xcf, 0xd5, 0xfa, 0x01, 0xcf,
+	0xeb, 0x42, 0xf4, 0x54, 0x10, 0xbf, 0x26, 0x40, 0x43, 0xf8, 0x9d, 0x63,
+	0xd2, 0xe7, 0x51, 0x56, 0xed, 0x89, 0x11, 0xe4, 0xbb, 0x05, 0x09, 0x62,
+	0x11, 0xae, 0x4f, 0x0c, 0xc8, 0x23, 0x97, 0x4a, 0x60, 0x7f, 0x01, 0x5f,
+	0x03, 0x9e, 0xc6, 0x2f, 0xd4, 0xea, 0xc7, 0x38, 0xe8, 0x19, 0xf6, 0xc8,
+	0xa7, 0x40, 0x6f, 0x83, 0xb5, 0x2f, 0xab, 0xfd, 0x8c, 0xa9, 0xda, 0xe7,
+	0xfa, 0xba, 0x40, 0x7f, 0x47, 0x11, 0xb7, 0xf8, 0xfa, 0xf8, 0x7b, 0x9a,
+	0x37, 0x81, 0xde, 0xc6, 0xb5, 0x0e, 0x30, 0x47, 0xa4, 0x5d, 0x05, 0x3a,
+	0xd2, 0x61, 0xef, 0x57, 0xbc, 0xe0, 0x33, 0x95, 0x13, 0x2a, 0x39, 0x0f,
+	0x55, 0xe5, 0xbc, 0xbe, 0x46, 0x67, 0x3b, 0x6d, 0xdf, 0x46, 0x69, 0x8b,
+	0xb0, 0x69, 0xd0, 0xf7, 0xd2, 0x32, 0xdb, 0xef, 0x5a, 0xa3, 0xae, 0x1c,
+	0x97, 0xc8, 0xcc, 0x0f, 0xc0, 0xcb, 0xdb, 0x91, 0xd7, 0x20, 0xcb, 0x9f,
+	0x22, 0x46, 0x31, 0xfe, 0x58, 0x8a, 0x89, 0xe7, 0x64, 0xb5, 0x78, 0xf8,
+	0x5a, 0xb1, 0xc7, 0x9d, 0xd7, 0x19, 0x7b, 0xfc, 0x49, 0x1d, 0xf3, 0x9c,
+	0x05, 0xd8, 0xe9, 0x21, 0xbc, 0x5f, 0xe7, 0xfe, 0x10, 0x3e, 0xed, 0xaf,
+	0xac, 0x7a, 0x37, 0xc0, 0x8b, 0xb8, 0x6c, 0x9c, 0xd9, 0xac, 0x30, 0xc3,
+	0x9e, 0x5a, 0xc2, 0x8c, 0x51, 0xcf, 0xd7, 0x5f, 0xf0, 0xca, 0xd9, 0x28,
+	0xd7, 0x9b, 0x77, 0x2f, 0xe5, 0x10, 0x43, 0xd5, 0x1c, 0xe2, 0x96, 0x1a,
+	0x3e, 0xae, 0x86, 0x99, 0xe7, 0x54, 0xbe, 0xfc, 0x6a, 0x39, 0xf5, 0x82,
+	0x48, 0x1f, 0xf2, 0xe4, 0xd4, 0x79, 0x91, 0x2c, 0x72, 0x65, 0xe6, 0x73,
+	0x7b, 0x90, 0x3b, 0xa7, 0x7e, 0x21, 0xd2, 0x8b, 0x9c, 0x99, 0xf9, 0x70,
+	0x3f, 0xf8, 0xda, 0x03, 0x4c, 0x4d, 0x03, 0x63, 0xb7, 0x83, 0xbf, 0x5d,
+	0x0a, 0x57, 0x0f, 0x9d, 0x46, 0xae, 0xad, 0xea, 0xec, 0xb4, 0x75, 0x07,
+	0x7e, 0xb5, 0x52, 0x79, 0x2c, 0xdd, 0x8e, 0x7c, 0x3f, 0x29, 0x5f, 0xb6,
+	0x98, 0xf3, 0x1a, 0x56, 0xae, 0x7b, 0x26, 0x12, 0x8e, 0x63, 0x0b, 0xd7,
+	0xf4, 0x11, 0x2b, 0x79, 0x3f, 0xac, 0xfc, 0xc4, 0x78, 0xe4, 0x6a, 0xbc,
+	0xdf, 0x5f, 0xe5, 0xfd, 0x9d, 0x0d, 0xd2, 0xd0, 0xaf, 0xea, 0x0b, 0xb9,
+	0xee, 0xaf, 0x13, 0xcb, 0xd2, 0xf0, 0xf3, 0xf0, 0xc7, 0x15, 0xb9, 0x3f,
+	0x7d, 0xa5, 0x72, 0xd1, 0xdd, 0x20, 0x85, 0xed, 0x07, 0x34, 0x9e, 0x1f,
+	0x78, 0x32, 0xe7, 0x16, 0x61, 0x1f, 0xfa, 0xdb, 0xc2, 0x64, 0x0c, 0x51,
+	0x29, 0xff, 0x9a, 0x65, 0xae, 0xf7, 0xf6, 0x7a, 0x69, 0xd8, 0xf6, 0x02,
+	0x8b, 0x63, 0xc4, 0x99, 0x39, 0x27, 0xae, 0xea, 0xdd, 0x37, 0xb9, 0xec,
+	0xb7, 0x21, 0xd3, 0xdf, 0x92, 0x39, 0xc4, 0x13, 0xf3, 0xbd, 0xa0, 0x71,
+	0x7b, 0x0b, 0xc6, 0xd3, 0xee, 0xc8, 0xf3, 0xdf, 0x96, 0xa1, 0x41, 0xf2,
+	0xd4, 0xc1, 0xf8, 0xfb, 0x31, 0xa6, 0x19, 0xd7, 0x07, 0x23, 0x73, 0x76,
+	0xcc, 0x6f, 0x0f, 0x70, 0x0e, 0xfa, 0x52, 0xce, 0xc3, 0xb5, 0x5a, 0x94,
+	0xcd, 0x2f, 0xcd, 0xcf, 0xb9, 0xf9, 0xec, 0xe3, 0xca, 0xbe, 0xee, 0xee,
+	0xd0, 0x1a, 0x4d, 0xa1, 0x35, 0x7a, 0x42, 0x6b, 0x90, 0xb6, 0xe6, 0x10,
+	0x6d, 0xcd, 0x78, 0xff, 0x3e, 0xac, 0xd7, 0xaf, 0xe3, 0x94, 0x60, 0x9d,
+	0x60, 0x1f, 0x2d, 0xa1, 0xb1, 0x1f, 0x62, 0x0d, 0xf6, 0x39, 0xa1, 0x3e,
+	0xae, 0x0b, 0x1c, 0x73, 0xd8, 0x6e, 0x0e, 0xd1, 0x42, 0xfa, 0x1a, 0xd0,
+	0xaf, 0xe6, 0x02, 0x3f, 0x1b, 0xe0, 0xbb, 0x4c, 0xf8, 0x8f, 0x08, 0xe2,
+	0xaa, 0x60, 0x4f, 0xc1, 0x1c, 0x0e, 0xde, 0xe3, 0x18, 0xff, 0xb9, 0xff,
+	0x0e, 0xfb, 0xf9, 0x3c, 0x22, 0xdf, 0x53, 0xf4, 0xb2, 0xcd, 0x3d, 0x34,
+	0x81, 0x56, 0x5e, 0x53, 0x32, 0xdb, 0x0c, 0xd9, 0x77, 0x33, 0x9f, 0x36,
+	0xe4, 0x36, 0xd7, 0x34, 0xf2, 0xdd, 0x94, 0xef, 0x06, 0x8d, 0x97, 0x0d,
+	0x46, 0xee, 0x34, 0x6b, 0x08, 0x8d, 0x3a, 0xf7, 0x43, 0xbe, 0xa1, 0x7c,
+	0x4c, 0xe0, 0x03, 0xe8, 0x63, 0x18, 0xab, 0xd0, 0x7f, 0x66, 0xf5, 0x3d,
+	0xae, 0xd0, 0xd3, 0xc3, 0xf3, 0xcd, 0x72, 0x51, 0xf1, 0xd0, 0x96, 0xc5,
+	0x2a, 0x0f, 0xa3, 0xfa, 0xbb, 0xd1, 0x31, 0xfd, 0x4d, 0x66, 0x3f, 0xe2,
+	0x01, 0xdc, 0x97, 0x80, 0xb9, 0xdd, 0xd0, 0xb7, 0x6e, 0xe6, 0x70, 0x45,
+	0x5c, 0x59, 0xc3, 0x30, 0x70, 0x75, 0x70, 0x8d, 0xe1, 0x0a, 0xbf, 0x04,
+	0xac, 0xc9, 0x77, 0xbf, 0x0d, 0x1d, 0x82, 0x6c, 0xca, 0xb6, 0x71, 0xbf,
+	0xe7, 0xd7, 0x87, 0x16, 0xdd, 0xd5, 0xeb, 0x43, 0x8b, 0xa2, 0xea, 0x43,
+	0x13, 0xd7, 0xa8, 0x0f, 0x65, 0xaf, 0xbf, 0x3e, 0x74, 0xa2, 0x9e, 0x18,
+	0xbc, 0xb7, 0x47, 0x8c, 0xdf, 0xd5, 0xf5, 0xa1, 0xf7, 0xc5, 0xaf, 0x0f,
+	0x5d, 0x94, 0xd5, 0xeb, 0x43, 0x13, 0x35, 0xf5, 0xa1, 0x8d, 0xaa, 0x3e,
+	0xc4, 0x79, 0xfc, 0xfa, 0x10, 0xdb, 0x6d, 0xdd, 0xbd, 0xa1, 0x3a, 0x08,
+	0xf0, 0x54, 0xe5, 0x84, 0xb6, 0x31, 0xe8, 0x05, 0x18, 0x45, 0x2c, 0xbf,
+	0xb9, 0xea, 0x8f, 0x96, 0xf0, 0xca, 0x50, 0xba, 0x75, 0x2d, 0xbc, 0x1a,
+	0xf4, 0x63, 0x90, 0x65, 0x58, 0x35, 0x5e, 0x8d, 0x53, 0x5e, 0xab, 0x67,
+	0xde, 0x3c, 0x56, 0x5a, 0x9a, 0x77, 0x0c, 0xb2, 0x1d, 0xaa, 0xd6, 0x50,
+	0xd6, 0x8a, 0x85, 0x1c, 0x39, 0xb6, 0xea, 0x37, 0xb8, 0x44, 0x76, 0xe5,
+	0x37, 0x38, 0x43, 0x1c, 0xd0, 0xd9, 0xd6, 0x5d, 0x50, 0x79, 0xd5, 0x9c,
+	0xf7, 0x55, 0xb9, 0xf0, 0xb0, 0x0d, 0x3c, 0x09, 0x6a, 0x26, 0x94, 0xe5,
+	0x92, 0x8f, 0x28, 0x98, 0x9f, 0x5f, 0xdd, 0xe4, 0xb0, 0xaa, 0x9b, 0xfc,
+	0xbc, 0x3e, 0x5c, 0x37, 0x59, 0x94, 0xab, 0xd7, 0x4d, 0x0e, 0xaf, 0x52,
+	0x37, 0x79, 0x53, 0x96, 0xea, 0x26, 0x6f, 0x4a, 0x50, 0x37, 0x89, 0xc8,
+	0x85, 0x4d, 0x9c, 0xe7, 0x08, 0xde, 0x19, 0xc0, 0xaf, 0x1f, 0x3f, 0xbf,
+	0x8e, 0xb2, 0x58, 0xa5, 0x7f, 0xb5, 0x3a, 0x4a, 0x7d, 0xec, 0x93, 0xd4,
+	0x51, 0x7c, 0x4c, 0x0f, 0xea, 0x28, 0x0d, 0x88, 0x5f, 0xe0, 0x43, 0xcc,
+	0x70, 0x1d, 0xa5, 0x15, 0xf3, 0xb2, 0x8f, 0x6d, 0xf6, 0xc3, 0x2e, 0xe0,
+	0x67, 0xb2, 0xaa, 0xce, 0xf1, 0x9b, 0x9a, 0x87, 0x07, 0xb0, 0xe7, 0x24,
+	0x64, 0x41, 0x3e, 0xb6, 0xab, 0x38, 0x32, 0x6b, 0x25, 0x8c, 0x5c, 0x27,
+	0xbc, 0xd3, 0x24, 0xbf, 0xd9, 0x27, 0x64, 0xa4, 0x4c, 0x1d, 0x6f, 0x45,
+	0xdc, 0x6d, 0xa1, 0xef, 0x00, 0xda, 0x41, 0x8c, 0xd4, 0x5d, 0x9d, 0x83,
+	0x76, 0x38, 0xc7, 0x7a, 0x9f, 0x73, 0x3d, 0x3e, 0x67, 0x27, 0x68, 0x0e,
+	0xef, 0xa3, 0x08, 0x7f, 0x83, 0x3e, 0x25, 0x73, 0xc6, 0x8a, 0x01, 0x2d,
+	0x49, 0xda, 0xf4, 0x75, 0xcc, 0xc7, 0xbe, 0x9d, 0x2a, 0xdf, 0x1a, 0xee,
+	0xe1, 0x5e, 0xe9, 0xbb, 0x16, 0x40, 0x1f, 0xfa, 0xe6, 0x99, 0xe3, 0xd1,
+	0x8f, 0x05, 0x39, 0x58, 0x5c, 0xe5, 0x60, 0x2d, 0x8a, 0x1f, 0xe4, 0xf5,
+	0x23, 0x31, 0xe2, 0x63, 0x8b, 0xcb, 0x3d, 0xf4, 0x6b, 0x5c, 0x63, 0xdb,
+	0xcf, 0xf5, 0x58, 0x8f, 0x6e, 0x71, 0x9f, 0x80, 0x5c, 0x59, 0xab, 0x09,
+	0xe4, 0xf7, 0x0d, 0xbd, 0xef, 0x5e, 0x29, 0xb6, 0x48, 0x6c, 0x23, 0xe8,
+	0x69, 0x9b, 0x62, 0x8c, 0x7d, 0x8f, 0xca, 0x37, 0x1c, 0x77, 0x6d, 0xbb,
+	0xdd, 0x7f, 0x03, 0x76, 0x3b, 0x70, 0x55, 0xbb, 0x3d, 0x1b, 0x0b, 0xdb,
+	0xed, 0xfe, 0x1b, 0xb0, 0xdb, 0x23, 0x37, 0x64, 0xb7, 0xdc, 0x1b, 0x31,
+	0x29, 0xa8, 0x8b, 0xad, 0x8c, 0x9b, 0x82, 0x75, 0x47, 0xb1, 0x66, 0x76,
+	0x8d, 0x35, 0x87, 0xd6, 0xac, 0xbb, 0xd6, 0xc6, 0x4c, 0xd7, 0x23, 0x6f,
+	0xe6, 0x21, 0xf4, 0xab, 0x71, 0xed, 0x83, 0x9e, 0xd6, 0x3a, 0x1f, 0xe4,
+	0xed, 0x61, 0xfb, 0xa1, 0x5e, 0x50, 0x17, 0x7e, 0x02, 0x7e, 0x51, 0x1f,
+	0x02, 0x9b, 0x6b, 0xaf, 0xd1, 0xc1, 0x05, 0xe4, 0xf3, 0xed, 0x5a, 0x07,
+	0x29, 0xeb, 0x4e, 0xf5, 0x3d, 0x69, 0xde, 0x7b, 0xc2, 0xcf, 0xe3, 0xa1,
+	0x03, 0x85, 0xf9, 0xc0, 0xd6, 0x92, 0x58, 0x37, 0x78, 0x46, 0x3e, 0xba,
+	0x88, 0x61, 0xb6, 0x21, 0xfe, 0x02, 0x8f, 0x54, 0xff, 0xf2, 0x3a, 0xf0,
+	0xd5, 0xf1, 0x4c, 0x8a, 0x51, 0x8c, 0x7d, 0xae, 0x07, 0x36, 0xde, 0x43,
+	0x8c, 0xca, 0x20, 0x8f, 0xa1, 0x1e, 0x52, 0x37, 0x3b, 0xba, 0x0e, 0x99,
+	0x8c, 0x91, 0x0e, 0xc2, 0xf6, 0x6c, 0xa5, 0xc7, 0xbb, 0xcb, 0x1d, 0xe7,
+	0x16, 0x4d, 0xae, 0x51, 0xa9, 0x14, 0x54, 0xbd, 0x5e, 0xcc, 0x5c, 0xf7,
+	0x4d, 0xeb, 0xe8, 0x97, 0x6e, 0x76, 0x23, 0x5a, 0xd7, 0xb2, 0xb8, 0xa7,
+	0xde, 0xfe, 0x2b, 0x7c, 0x3b, 0xf2, 0x89, 0xee, 0x7f, 0x41, 0x7f, 0x02,
+	0x36, 0x4f, 0x5f, 0xce, 0xfc, 0x62, 0x87, 0x1e, 0xd7, 0xae, 0xbe, 0x95,
+	0xaa, 0xef, 0x2d, 0x4e, 0xe0, 0x7f, 0x52, 0xf4, 0xcf, 0xcb, 0xe4, 0xcc,
+	0xb3, 0x1b, 0x79, 0x95, 0x9f, 0xf0, 0x7d, 0xa5, 0x93, 0xc8, 0x29, 0xac,
+	0x50, 0x9d, 0x3d, 0xa6, 0x73, 0x31, 0xda, 0x58, 0x5c, 0xe5, 0x89, 0x7e,
+	0xee, 0xc1, 0x5c, 0x75, 0xf9, 0x99, 0x8d, 0xd5, 0x75, 0x60, 0xf3, 0x27,
+	0xd0, 0x81, 0x5a, 0xf9, 0xc5, 0x60, 0xfb, 0x81, 0xfc, 0x82, 0x98, 0x65,
+	0x56, 0xef, 0xbb, 0xdd, 0x97, 0xe1, 0xff, 0x8b, 0x7d, 0x1a, 0xa1, 0x7d,
+	0x06, 0x78, 0x74, 0x58, 0xef, 0x73, 0x47, 0x0d, 0x1e, 0x0d, 0xd4, 0xd8,
+	0xec, 0xe7, 0x89, 0x47, 0x97, 0xd7, 0x7d, 0xfe, 0x78, 0xc4, 0x7d, 0x6d,
+	0x59, 0x15, 0x87, 0xfc, 0x7d, 0x3c, 0x2d, 0x66, 0xe6, 0xb3, 0xcc, 0xdf,
+	0x3e, 0x89, 0x7c, 0xc2, 0x38, 0x42, 0x99, 0x34, 0xa9, 0x78, 0xd5, 0xb7,
+	0x3d, 0xf8, 0xf2, 0xf9, 0xa8, 0xbc, 0xf7, 0x50, 0x4c, 0x7e, 0x75, 0x2f,
+	0xbf, 0x95, 0x59, 0xba, 0x7e, 0xc5, 0x76, 0xb4, 0xc1, 0xf7, 0x43, 0x48,
+	0x24, 0x94, 0xdf, 0xe1, 0x3b, 0x81, 0x3d, 0xdb, 0x78, 0xce, 0x67, 0x5b,
+	0xe4, 0x42, 0xf3, 0x8d, 0xe4, 0x74, 0x1d, 0xf6, 0xfb, 0xe6, 0x6a, 0x39,
+	0xdd, 0xd5, 0x6b, 0x7f, 0x4b, 0x39, 0x1d, 0x71, 0xb6, 0x59, 0xd7, 0x7b,
+	0x98, 0xd7, 0xec, 0xd7, 0xd8, 0xc9, 0x7b, 0xe4, 0xaa, 0x1e, 0xf2, 0x57,
+	0xc8, 0xf6, 0x35, 0xc4, 0x4b, 0xaf, 0x7a, 0xc8, 0x59, 0x3d, 0xe4, 0xaa,
+	0x1e, 0x72, 0x55, 0x0f, 0xb9, 0xaa, 0xd7, 0xa5, 0x73, 0xde, 0x01, 0x5d,
+	0xd7, 0xe7, 0xf7, 0x70, 0xd6, 0x0b, 0x8a, 0xf0, 0x25, 0xe3, 0x3c, 0x63,
+	0x61, 0xe6, 0xd2, 0xeb, 0x82, 0x73, 0x48, 0xba, 0xe6, 0xdd, 0xaa, 0x6b,
+	0x30, 0x75, 0x37, 0x29, 0xdf, 0x6c, 0xbe, 0xd1, 0xe0, 0x7f, 0x33, 0xe7,
+	0xf9, 0x8f, 0x3f, 0x44, 0x5c, 0xc2, 0x1a, 0xd8, 0x04, 0x6d, 0xb4, 0x62,
+	0x66, 0x58, 0x63, 0x11, 0xd3, 0xcc, 0x7c, 0x01, 0xef, 0x6c, 0xc3, 0x1e,
+	0xea, 0x69, 0xdb, 0x11, 0x33, 0xd3, 0x48, 0x9e, 0x1a, 0x66, 0x66, 0xbd,
+	0x9e, 0xeb, 0x6f, 0x1a, 0xfc, 0xd8, 0xaa, 0x93, 0x6d, 0xcb, 0x64, 0x9c,
+	0xa0, 0x62, 0xed, 0xa0, 0x7f, 0x4f, 0xf3, 0xf2, 0xb5, 0xa2, 0x0a, 0xdf,
+	0x73, 0xe9, 0x87, 0x31, 0x9f, 0x3a, 0xdb, 0x54, 0xe5, 0xb7, 0xb9, 0x26,
+	0xbf, 0xa3, 0x9a, 0xdf, 0x3e, 0x8f, 0x23, 0x1c, 0xa7, 0xea, 0xbe, 0xe4,
+	0x75, 0x30, 0x9f, 0xaa, 0xe1, 0x61, 0x1d, 0x75, 0x8e, 0x03, 0xd7, 0xbb,
+	0xa2, 0xd2, 0x34, 0x78, 0x20, 0xea, 0x86, 0xd7, 0x25, 0x46, 0xf5, 0x2e,
+	0xfb, 0xfe, 0xb4, 0xf6, 0x9a, 0xed, 0xea, 0xdb, 0x99, 0xef, 0x33, 0xa2,
+	0x4a, 0x07, 0x2d, 0x75, 0x36, 0xef, 0xd7, 0xea, 0xcc, 0x0d, 0xf5, 0x2f,
+	0x8f, 0x3c, 0x66, 0xbc, 0xa7, 0x23, 0x69, 0x99, 0x7f, 0xd1, 0xc0, 0x5a,
+	0x6b, 0x5f, 0x39, 0xc0, 0x3d, 0xae, 0x57, 0xeb, 0xc7, 0x59, 0x27, 0x0b,
+	0xf0, 0x4c, 0x36, 0xfb, 0xf5, 0xb3, 0x4f, 0x63, 0x4b, 0x0d, 0x35, 0xb6,
+	0x14, 0xec, 0xd3, 0xcf, 0x57, 0xf9, 0xdd, 0x7a, 0xb5, 0xb3, 0x13, 0x0b,
+	0xe5, 0xd0, 0xf7, 0x8f, 0xaa, 0x6e, 0xf0, 0x5c, 0xcb, 0x83, 0xd0, 0x41,
+	0xd6, 0xfe, 0xf7, 0xc0, 0x8e, 0x2a, 0x95, 0x3e, 0xd6, 0x93, 0xb7, 0x3f,
+	0xa0, 0xcf, 0x27, 0x3c, 0xa3, 0xea, 0x09, 0xd6, 0x8a, 0x7a, 0x42, 0x1f,
+	0x74, 0x05, 0x31, 0x00, 0x6c, 0xb0, 0xa0, 0x64, 0xc9, 0x78, 0xa0, 0xf6,
+	0xfb, 0xca, 0xf9, 0x46, 0x9f, 0x0f, 0xb7, 0x37, 0xfa, 0xdf, 0x18, 0x7e,
+	0xe9, 0x2c, 0x6f, 0xf3, 0xfd, 0x44, 0x63, 0x70, 0xce, 0x67, 0xf8, 0x4c,
+	0x1f, 0x74, 0xb1, 0x4e, 0xf2, 0x6a, 0x3e, 0xc4, 0xbb, 0xcf, 0xff, 0xac,
+	0x79, 0xf9, 0x78, 0xf4, 0x9d, 0x09, 0xc6, 0x37, 0xd7, 0x8c, 0x6f, 0xc6,
+	0xf8, 0x7f, 0xaf, 0x19, 0xdf, 0x1c, 0x1a, 0xef, 0xd4, 0x8c, 0x77, 0x30,
+	0xbe, 0x7e, 0xd3, 0xf2, 0xf1, 0x4e, 0x68, 0x7c, 0x4b, 0xcd, 0xf8, 0x16,
+	0x8c, 0x6f, 0xa8, 0x19, 0x8f, 0xbe, 0x33, 0x75, 0xfa, 0xbb, 0x17, 0x31,
+	0xf6, 0x88, 0xce, 0xbb, 0x71, 0x2d, 0xd5, 0x7e, 0x4b, 0xa1, 0xde, 0xb5,
+	0x42, 0x06, 0xc1, 0x39, 0x3b, 0xda, 0x6b, 0x16, 0xf6, 0xba, 0x14, 0xcb,
+	0xf8, 0xfa, 0x18, 0xd6, 0x45, 0xe2, 0x43, 0x51, 0x22, 0x2e, 0x74, 0x67,
+	0x1e, 0x3a, 0x34, 0x1f, 0xf8, 0x24, 0x9e, 0x99, 0x4a, 0x75, 0xf9, 0x7a,
+	0x6a, 0x48, 0xd4, 0x5d, 0xd0, 0x39, 0xd8, 0x4e, 0xd2, 0x0e, 0xbc, 0x0c,
+	0x30, 0x53, 0x4e, 0xf9, 0x76, 0x43, 0xfd, 0xe5, 0xfc, 0xda, 0x7e, 0xa8,
+	0xab, 0x7a, 0x9d, 0xbe, 0x15, 0xb8, 0x96, 0x5c, 0x51, 0xab, 0x8a, 0x5c,
+	0x07, 0xae, 0x0d, 0x54, 0x71, 0xed, 0x41, 0x99, 0xad, 0xe6, 0xdb, 0xfd,
+	0x72, 0xd4, 0xdb, 0xcb, 0xf3, 0x38, 0xa7, 0xb2, 0xf2, 0xd9, 0xe4, 0xdb,
+	0x7b, 0xab, 0x7e, 0x32, 0x35, 0x91, 0x95, 0x0b, 0xc7, 0x99, 0x43, 0x05,
+	0xb5, 0xd6, 0x71, 0xef, 0x5b, 0x94, 0x0b, 0x6c, 0xe3, 0x46, 0xf3, 0x6d,
+	0xce, 0xe7, 0xc8, 0x51, 0xff, 0x2c, 0x44, 0x75, 0xde, 0x62, 0x75, 0xde,
+	0x84, 0xb6, 0x37, 0xfa, 0xe0, 0x25, 0x7f, 0x99, 0x87, 0xbf, 0x1c, 0x42,
+	0xce, 0xbd, 0xe0, 0xad, 0x56, 0xef, 0xbc, 0x51, 0x7f, 0x59, 0x5b, 0x37,
+	0xae, 0xf5, 0x97, 0x5c, 0xa7, 0xb6, 0x56, 0x9c, 0xac, 0xc1, 0x7f, 0xea,
+	0xd3, 0x53, 0x3a, 0xa6, 0xc6, 0x75, 0xfe, 0x29, 0xd8, 0xa3, 0x29, 0x43,
+	0x4a, 0x7f, 0xd9, 0x0e, 0x72, 0xcb, 0x03, 0xd5, 0xdc, 0x72, 0x29, 0x1f,
+	0x44, 0xec, 0xda, 0x75, 0x9f, 0xc6, 0x47, 0xc6, 0xc8, 0xe3, 0xe8, 0x3f,
+	0x05, 0x1d, 0xe0, 0x33, 0xd6, 0x3f, 0xef, 0x90, 0x2f, 0x5b, 0xbe, 0x7f,
+	0xf2, 0xeb, 0x50, 0x07, 0x54, 0xfc, 0xcf, 0xfa, 0xff, 0x70, 0x7a, 0xa3,
+	0x8e, 0xf7, 0xae, 0x85, 0xab, 0xcb, 0x73, 0x53, 0xd3, 0x3c, 0x81, 0x77,
+	0x99, 0x9b, 0x3e, 0x10, 0x27, 0x86, 0xe6, 0xca, 0x57, 0x7d, 0xbf, 0x48,
+	0xff, 0x32, 0xac, 0xbe, 0xfb, 0xa9, 0x3c, 0x14, 0xe3, 0x16, 0xf4, 0xfb,
+	0x7e, 0x1e, 0x9a, 0x2b, 0x6f, 0x89, 0xfb, 0x38, 0x78, 0xb5, 0x9c, 0xe5,
+	0x58, 0x9c, 0xb5, 0xbc, 0x05, 0xef, 0x5a, 0xb4, 0xae, 0xcc, 0x7b, 0x23,
+	0x2b, 0xf2, 0xde, 0x41, 0x9d, 0xd7, 0x7e, 0x45, 0xe5, 0xbd, 0x3e, 0x8f,
+	0xb9, 0x97, 0x70, 0x1e, 0xe5, 0x02, 0x0b, 0xf9, 0x8d, 0x84, 0xf8, 0x30,
+	0xaa, 0xfc, 0x56, 0x61, 0xf2, 0x77, 0xd4, 0xf9, 0x89, 0x95, 0x7a, 0xf3,
+	0x79, 0xfb, 0x89, 0x60, 0xef, 0x4f, 0x89, 0x5f, 0xaf, 0xdb, 0x03, 0x5a,
+	0x98, 0x5b, 0x45, 0xb5, 0x3e, 0xa4, 0x34, 0x5e, 0x07, 0xe3, 0x82, 0x3c,
+	0xbe, 0xfa, 0x5d, 0xb5, 0x98, 0x5d, 0x56, 0x3f, 0xd9, 0x42, 0x18, 0x86,
+	0xdc, 0xb3, 0x37, 0xf0, 0x1d, 0xe2, 0xd3, 0x9c, 0x7f, 0xa8, 0xf5, 0x6b,
+	0xfc, 0x46, 0xda, 0xaa, 0xcf, 0xc7, 0xb9, 0xb0, 0x01, 0x9e, 0x65, 0x0e,
+	0xe3, 0xab, 0x3a, 0x03, 0x17, 0x73, 0x32, 0x62, 0xec, 0x23, 0x7d, 0xe9,
+	0x7f, 0xd6, 0xfb, 0x4c, 0xc8, 0x91, 0x29, 0xbf, 0xbe, 0x69, 0xae, 0x71,
+	0xfe, 0xcd, 0x34, 0xaf, 0xab, 0xbe, 0x79, 0x03, 0xe7, 0xdf, 0x5e, 0x8f,
+	0x07, 0xf5, 0xcd, 0xda, 0xf3, 0x6f, 0x91, 0xeb, 0x3c, 0xff, 0xe6, 0xd7,
+	0x37, 0x39, 0x4f, 0xb8, 0xbe, 0x79, 0x8f, 0x3a, 0x43, 0x36, 0x3a, 0xd5,
+	0xa3, 0xce, 0x23, 0xb7, 0x75, 0xaf, 0x8d, 0xb3, 0xfb, 0x3e, 0xb3, 0x7c,
+	0xe4, 0x3f, 0xe3, 0xe1, 0x7c, 0x64, 0xdf, 0xe7, 0x92, 0x8f, 0x70, 0x2f,
+	0xbf, 0xef, 0x7f, 0xb7, 0xad, 0x39, 0xfb, 0x95, 0xfb, 0x1c, 0x6b, 0x98,
+	0x47, 0x54, 0x0d, 0x73, 0xcb, 0xfa, 0x70, 0x0d, 0xd3, 0xbc, 0xc6, 0xd9,
+	0xaf, 0x23, 0xab, 0xd4, 0x30, 0xa3, 0xa1, 0xb3, 0x5f, 0x51, 0x7d, 0xf6,
+	0x6b, 0xa3, 0x8b, 0xbc, 0x51, 0xd7, 0x2c, 0xcd, 0xab, 0x9e, 0xfd, 0xea,
+	0x59, 0xff, 0x49, 0x6a, 0x96, 0xb9, 0x65, 0x35, 0xcb, 0x15, 0x67, 0xbf,
+	0xe0, 0xd7, 0x36, 0x4b, 0x32, 0x94, 0xe3, 0xe4, 0x6e, 0xf0, 0x6c, 0x43,
+	0xfe, 0x3a, 0xe2, 0x80, 0x7d, 0x55, 0x5b, 0xe5, 0xd9, 0xfd, 0x3a, 0xec,
+	0x39, 0x2a, 0x7b, 0x1d, 0xea, 0x27, 0xcf, 0x38, 0x76, 0xc2, 0x16, 0x70,
+	0x2d, 0xb3, 0xdd, 0x45, 0x19, 0x19, 0x03, 0x9d, 0xcb, 0xcf, 0x17, 0x2c,
+	0x9d, 0xd3, 0x8d, 0x55, 0xcf, 0xe9, 0x9e, 0x84, 0xde, 0x98, 0x53, 0x31,
+	0x99, 0x0b, 0xe9, 0xd4, 0x38, 0x62, 0x3b, 0x73, 0xc6, 0xd6, 0xcf, 0x93,
+	0x12, 0x99, 0x72, 0x80, 0x6f, 0x3c, 0xdb, 0xdb, 0x24, 0x91, 0x19, 0xff,
+	0x7b, 0xa3, 0xa9, 0xf0, 0x33, 0x81, 0x31, 0x3c, 0xdb, 0x19, 0x95, 0xa3,
+	0xaa, 0x3e, 0x11, 0xe8, 0xf2, 0x37, 0xc1, 0xe3, 0x4d, 0xd9, 0xa5, 0xb6,
+	0xb3, 0x8a, 0x8f, 0x47, 0xcc, 0x38, 0x45, 0x7d, 0xbe, 0x5b, 0xf2, 0xba,
+	0xf6, 0x33, 0x5c, 0xde, 0xa9, 0x73, 0x09, 0xf5, 0xcd, 0x06, 0xbc, 0x6c,
+	0xd3, 0xfe, 0x16, 0xd7, 0xf9, 0x36, 0xfa, 0x37, 0xc6, 0xcc, 0xd2, 0x37,
+	0xb9, 0x2d, 0x31, 0x02, 0x6c, 0x1b, 0x52, 0x6b, 0xde, 0x08, 0xcf, 0x8d,
+	0x15, 0xf1, 0xd7, 0x8d, 0xf1, 0x3d, 0x88, 0x85, 0xdf, 0xc4, 0xfe, 0xda,
+	0xa0, 0x1f, 0x8f, 0x4b, 0xfe, 0xcc, 0x1d, 0xd2, 0x37, 0x9d, 0x02, 0x3d,
+	0xbf, 0xae, 0x0c, 0xa7, 0x11, 0x37, 0x3f, 0xcf, 0x33, 0x60, 0xc0, 0x4b,
+	0xf0, 0xed, 0x95, 0x15, 0xdf, 0xa0, 0xc3, 0xe7, 0xc6, 0xba, 0xaa, 0xe7,
+	0x80, 0x5e, 0x2a, 0x4b, 0xac, 0x99, 0x34, 0x4f, 0x2d, 0x9d, 0x09, 0x5f,
+	0x28, 0xef, 0x56, 0x7e, 0xec, 0xc5, 0xf2, 0xff, 0x52, 0x77, 0x6d, 0xb1,
+	0x6d, 0x9d, 0xf7, 0xfd, 0xcf, 0x43, 0xea, 0x12, 0xdd, 0x7c, 0x24, 0xd3,
+	0x32, 0x2d, 0xd1, 0xf2, 0x39, 0xd2, 0xb1, 0xc5, 0xd8, 0x5a, 0xc7, 0x6a,
+	0xca, 0x26, 0xac, 0x5a, 0xc2, 0x52, 0xf4, 0x65, 0x59, 0x36, 0xd0, 0x97,
+	0x76, 0x1e, 0x16, 0xa0, 0x0e, 0x65, 0x3b, 0x1d, 0xd0, 0x07, 0xb7, 0xd9,
+	0x80, 0xa4, 0x03, 0x6c, 0x96, 0xb2, 0x1c, 0xaf, 0x53, 0x4d, 0x36, 0x66,
+	0xd5, 0xac, 0x1b, 0x50, 0x4e, 0x92, 0x9d, 0xb4, 0x50, 0xc0, 0x64, 0xbd,
+	0x60, 0xd8, 0x43, 0xad, 0xc9, 0xf6, 0xf6, 0xb2, 0x87, 0x6c, 0xd8, 0x83,
+	0x81, 0x0d, 0x98, 0x63, 0x05, 0x68, 0x96, 0x02, 0x49, 0x87, 0x15, 0x43,
+	0x1e, 0x36, 0x70, 0xff, 0xdf, 0x77, 0x21, 0x0f, 0x0f, 0x0f, 0x75, 0x89,
+	0x9d, 0x01, 0x33, 0x60, 0x88, 0xe7, 0x9c, 0xef, 0x9c, 0xf3, 0x7d, 0xff,
+	0xef, 0x7f, 0xbf, 0x9d, 0x3a, 0x3f, 0x8f, 0xd8, 0xc3, 0xdc, 0xca, 0x5b,
+	0x0c, 0x8b, 0xbb, 0x42, 0x96, 0xcd, 0xe5, 0x69, 0x28, 0x48, 0xd8, 0x0f,
+	0x0a, 0x30, 0x0c, 0x44, 0x6e, 0x86, 0x8c, 0xcd, 0x47, 0xc5, 0xbe, 0x4a,
+	0x5e, 0x71, 0xcc, 0x95, 0x5b, 0x51, 0xdb, 0x5b, 0x99, 0x73, 0x21, 0xf7,
+	0x42, 0xe6, 0x85, 0x00, 0x9e, 0xab, 0x17, 0x8f, 0x3b, 0x32, 0x2f, 0x64,
+	0x64, 0x01, 0xe7, 0xfa, 0x3d, 0x72, 0xae, 0x9d, 0x71, 0x00, 0x39, 0x44,
+	0xc8, 0x05, 0xc7, 0x9c, 0x85, 0x5f, 0xc3, 0x37, 0x2e, 0xbd, 0x3d, 0xff,
+	0xaa, 0x7c, 0xe7, 0xb0, 0x78, 0xe7, 0x2e, 0xc5, 0xb3, 0x74, 0x0e, 0x78,
+	0x3c, 0x30, 0x93, 0x1f, 0x8d, 0x04, 0x19, 0xbf, 0x67, 0xca, 0xb0, 0xa5,
+	0x9b, 0xe9, 0x6b, 0x1b, 0xc1, 0x33, 0xd1, 0x00, 0xcf, 0x7a, 0x9a, 0x60,
+	0xdb, 0xbb, 0xca, 0xbb, 0x25, 0xec, 0xe4, 0x79, 0xe4, 0xb7, 0xeb, 0xfc,
+	0x04, 0x09, 0xbb, 0x2a, 0x0d, 0x5d, 0x73, 0xe7, 0x26, 0xd4, 0x60, 0x77,
+	0xa6, 0x0a, 0xbb, 0xdd, 0xff, 0x8f, 0x60, 0x77, 0x4f, 0xe8, 0xba, 0x6f,
+	0x95, 0x91, 0x83, 0xa6, 0xe5, 0xbd, 0xae, 0x5d, 0x02, 0x1c, 0xc1, 0x4f,
+	0xed, 0xd2, 0x2a, 0x81, 0xa7, 0x22, 0x6f, 0xb8, 0x52, 0xf9, 0x41, 0xbc,
+	0xea, 0x93, 0x64, 0x1b, 0x04, 0xb6, 0x08, 0x7c, 0x77, 0xcd, 0x65, 0xe4,
+	0xf1, 0x8f, 0x25, 0x23, 0xa1, 0x17, 0x79, 0x6d, 0x91, 0x1f, 0xf5, 0xb8,
+	0x6d, 0x91, 0xe3, 0xdb, 0xb4, 0x45, 0x2e, 0x48, 0x5b, 0x24, 0xbb, 0x75,
+	0x5b, 0x64, 0xa0, 0x21, 0x5f, 0xab, 0xb6, 0x9e, 0xed, 0xdb, 0x22, 0xc6,
+	0x86, 0xb6, 0xc8, 0x88, 0xcb, 0xef, 0x82, 0xf9, 0xfe, 0x2e, 0x65, 0x4f,
+	0x80, 0xc7, 0x69, 0x38, 0x03, 0xc6, 0x27, 0x3c, 0x3e, 0xe0, 0x4f, 0x12,
+	0xd6, 0xe6, 0x8e, 0xff, 0x5b, 0x58, 0x0f, 0x36, 0xf8, 0xb7, 0x6b, 0xeb,
+	0xa1, 0xf0, 0xce, 0x6d, 0xe9, 0xec, 0x5e, 0x58, 0x0f, 0x36, 0xf5, 0x93,
+	0x36, 0xcf, 0x45, 0xac, 0xf7, 0x93, 0x0e, 0x1b, 0xcd, 0x78, 0xfb, 0x77,
+	0x5d, 0xfe, 0x53, 0x37, 0x7f, 0x07, 0x4d, 0x51, 0xe0, 0xf8, 0xa8, 0x7e,
+	0x17, 0x68, 0xc9, 0xce, 0x66, 0x09, 0xf6, 0x11, 0xde, 0x17, 0x11, 0xb4,
+	0xe6, 0xd1, 0xb7, 0xf8, 0x7d, 0xbc, 0xbe, 0xd7, 0x9e, 0x15, 0x72, 0x4a,
+	0xfa, 0x1a, 0x30, 0x3e, 0x16, 0x38, 0x2b, 0xc6, 0xca, 0xdc, 0x24, 0xe5,
+	0x7b, 0x50, 0x7a, 0x7e, 0x33, 0x9f, 0x43, 0xa3, 0xcc, 0xdb, 0x9e, 0x5d,
+	0xa0, 0x69, 0x7c, 0x1f, 0xef, 0x4b, 0xa4, 0xce, 0xae, 0x02, 0xff, 0xbc,
+	0xc0, 0x7a, 0xc1, 0x70, 0x55, 0x27, 0xa8, 0xdf, 0x9b, 0xcb, 0xc2, 0x7e,
+	0xd3, 0xbc, 0x33, 0x2d, 0xf2, 0xdd, 0x24, 0xef, 0x84, 0x9e, 0xa6, 0x79,
+	0xa7, 0x57, 0x0f, 0xde, 0xe7, 0x83, 0x17, 0xbe, 0x75, 0xa7, 0x7a, 0xef,
+	0x2c, 0xe4, 0x8f, 0xa7, 0x7c, 0xf7, 0xae, 0x5a, 0x77, 0x95, 0xad, 0x8d,
+	0x95, 0xf7, 0xa7, 0xc4, 0xba, 0xa2, 0x4f, 0x27, 0x51, 0x13, 0x57, 0xad,
+	0x09, 0xf2, 0xd6, 0x41, 0x41, 0x0e, 0x68, 0x3a, 0xd4, 0x75, 0xe2, 0x80,
+	0x45, 0xcc, 0xa7, 0x0e, 0xca, 0x2d, 0x4b, 0x70, 0x9f, 0x17, 0x16, 0x35,
+	0x39, 0x32, 0xa7, 0xe4, 0xc8, 0xa2, 0x8b, 0x8f, 0x37, 0xea, 0xed, 0x7d,
+	0x3e, 0x7a, 0xbb, 0xbb, 0xb6, 0x43, 0xd4, 0xb8, 0x35, 0xa9, 0xed, 0xf0,
+	0xab, 0x99, 0xc2, 0xd8, 0x17, 0x59, 0x5f, 0xf9, 0x14, 0xf4, 0x15, 0x13,
+	0x35, 0x4b, 0x52, 0x67, 0xc1, 0x75, 0x96, 0x49, 0xaf, 0x45, 0x18, 0xa7,
+	0x8e, 0xd1, 0x79, 0xd6, 0xc9, 0x6f, 0xd2, 0xe3, 0xca, 0x66, 0x4b, 0xb8,
+	0xf2, 0x4c, 0x91, 0xdf, 0x1f, 0xa0, 0xec, 0xb3, 0x76, 0x2c, 0x41, 0xc7,
+	0xe8, 0x9c, 0xc8, 0x99, 0x41, 0xcc, 0x0f, 0x79, 0x08, 0x07, 0xc5, 0x3c,
+	0xa5, 0x7f, 0xe3, 0x51, 0xe4, 0xcd, 0x6d, 0x3d, 0x67, 0x5f, 0xd7, 0xfa,
+	0x25, 0xc5, 0x3b, 0x97, 0x15, 0xed, 0x89, 0x73, 0x7c, 0xff, 0x8b, 0x46,
+	0xe3, 0xfd, 0x09, 0x23, 0x55, 0x4e, 0x19, 0xc9, 0x25, 0x8c, 0x7b, 0xd1,
+	0x98, 0x2e, 0xc3, 0xd6, 0xd4, 0xb8, 0x64, 0xc7, 0x41, 0x97, 0x6b, 0xb4,
+	0x79, 0x7c, 0x62, 0x91, 0x3c, 0xf5, 0x13, 0x5b, 0x98, 0xf7, 0x91, 0xba,
+	0x79, 0x6b, 0xf8, 0xe2, 0x37, 0x7c, 0x40, 0x09, 0x86, 0xa9, 0xd6, 0x7f,
+	0x3b, 0xe0, 0x73, 0x8f, 0x65, 0x69, 0x23, 0xfd, 0xd7, 0x6e, 0xd0, 0x7f,
+	0x17, 0x37, 0x9d, 0xf7, 0xc3, 0xf2, 0x02, 0x59, 0xc3, 0x1d, 0x74, 0x84,
+	0x9e, 0xcb, 0xf3, 0xae, 0xd3, 0x81, 0x3d, 0x38, 0x85, 0x31, 0xda, 0x37,
+	0xae, 0x7d, 0x63, 0x3d, 0x2a, 0x1f, 0x58, 0xe7, 0x2c, 0x74, 0x28, 0x3c,
+	0xc6, 0x75, 0xd8, 0x62, 0xab, 0x3c, 0x3f, 0xd8, 0x65, 0x4f, 0x8a, 0x39,
+	0xb2, 0x5d, 0x66, 0x4d, 0x93, 0xf4, 0x7f, 0x9f, 0x2d, 0xd7, 0xd5, 0x8f,
+	0xfa, 0xd4, 0x51, 0x0e, 0xfb, 0xd4, 0x51, 0xba, 0x69, 0x32, 0xe4, 0xa2,
+	0xc9, 0x88, 0x4b, 0xbf, 0x8b, 0xb2, 0x7d, 0xd3, 0xc5, 0xbc, 0x06, 0xf6,
+	0x4d, 0x07, 0x05, 0x5f, 0x71, 0xdb, 0x37, 0xde, 0xba, 0x7d, 0xd0, 0x27,
+	0x74, 0x38, 0x69, 0xeb, 0xa4, 0x8a, 0xd5, 0x9a, 0x7f, 0x5e, 0x77, 0xad,
+	0x66, 0x71, 0xa9, 0xa1, 0xbe, 0xd2, 0x6f, 0xbe, 0x43, 0x0d, 0xf3, 0x85,
+	0x9c, 0x4b, 0x34, 0xd5, 0xfd, 0xfc, 0xec, 0xaf, 0x47, 0x35, 0x3f, 0x2f,
+	0xdf, 0xc3, 0xbb, 0x86, 0x85, 0x1f, 0x3c, 0x5b, 0xe5, 0x79, 0x93, 0x72,
+	0xbe, 0xf9, 0x7a, 0x7b, 0x24, 0x78, 0x8d, 0x14, 0xec, 0xfc, 0x65, 0xc0,
+	0xf6, 0x7c, 0x6a, 0x9d, 0x1e, 0xf9, 0x3c, 0xd1, 0x2b, 0x7d, 0x65, 0x2d,
+	0x2a, 0xd7, 0x7a, 0x97, 0xb2, 0x0b, 0x37, 0xc3, 0x77, 0x9c, 0x6b, 0x51,
+	0xfe, 0x45, 0xdb, 0x2a, 0x11, 0xf0, 0xfc, 0xc4, 0xe9, 0x16, 0xc7, 0x54,
+	0xf1, 0x2d, 0xc4, 0xb0, 0x80, 0xf7, 0xfa, 0xf9, 0xb2, 0xd6, 0x6a, 0xf3,
+	0x3d, 0xb3, 0x1a, 0xf6, 0x4c, 0xe2, 0x15, 0x6c, 0x32, 0xe4, 0x10, 0x8f,
+	0x79, 0xf2, 0xb8, 0x1f, 0x06, 0x16, 0x3d, 0x3e, 0xb9, 0xcd, 0xc8, 0x4d,
+	0x6e, 0x36, 0xcf, 0xfb, 0x2e, 0xfd, 0x1d, 0xf3, 0xad, 0x54, 0xde, 0x8c,
+	0x0f, 0x48, 0x99, 0x5d, 0xf6, 0xd7, 0xa5, 0xcc, 0x2d, 0xcf, 0xcf, 0x2b,
+	0xa3, 0xf7, 0x6c, 0x51, 0x46, 0x8b, 0x7e, 0x28, 0x81, 0xc3, 0x82, 0x07,
+	0xa0, 0x06, 0x1b, 0x39, 0xd6, 0x9f, 0x06, 0xcd, 0x33, 0x9f, 0x75, 0xd5,
+	0xaa, 0xf9, 0xef, 0x63, 0x35, 0xce, 0x12, 0x42, 0x2f, 0x88, 0x09, 0xe4,
+	0x9b, 0xf4, 0x31, 0xef, 0xc1, 0xf8, 0xfd, 0xd6, 0x1d, 0xf8, 0x80, 0x95,
+	0x9f, 0x2a, 0xa5, 0xe4, 0xcb, 0xe1, 0x2d, 0xc4, 0x5b, 0xb6, 0xc7, 0xa7,
+	0x6d, 0x6b, 0x95, 0x10, 0x0b, 0x42, 0x4e, 0xf0, 0x0b, 0x3d, 0xd4, 0x73,
+	0xaa, 0xad, 0xcd, 0xb9, 0xdb, 0x2b, 0xe3, 0x53, 0xb8, 0xd6, 0x45, 0x37,
+	0x8a, 0xc8, 0xd7, 0xc6, 0xb5, 0xdf, 0xe3, 0x6b, 0x7e, 0x3c, 0x4a, 0xe7,
+	0x9b, 0x43, 0xe7, 0x93, 0xfb, 0x53, 0x22, 0xd8, 0x54, 0x15, 0xfa, 0xa7,
+	0xf8, 0xaf, 0xc8, 0x18, 0x47, 0xf9, 0x51, 0xc7, 0x6f, 0xfc, 0xfc, 0x8a,
+	0x46, 0xdf, 0xc7, 0xcd, 0x97, 0xfc, 0xf2, 0x96, 0xfc, 0x8a, 0xc8, 0xbb,
+	0xdf, 0x4a, 0x1c, 0x45, 0xc7, 0x8b, 0x27, 0x44, 0xed, 0xa9, 0x1b, 0x0f,
+	0x1e, 0x4d, 0xcc, 0x18, 0xf8, 0x30, 0xd4, 0xc0, 0xab, 0x1e, 0x3e, 0x06,
+	0xe0, 0x85, 0x6b, 0x87, 0xaf, 0x4f, 0xcb, 0x3f, 0x36, 0x8c, 0x3c, 0x00,
+	0xf8, 0xb3, 0x9f, 0xa2, 0xb3, 0xd7, 0x81, 0xc3, 0x06, 0x63, 0xdb, 0x08,
+	0xcd, 0x86, 0x51, 0x57, 0x24, 0x6a, 0x73, 0x54, 0x2c, 0x51, 0xd6, 0x0a,
+	0x9d, 0x15, 0x75, 0x8f, 0xfb, 0x23, 0xeb, 0x94, 0x66, 0xb9, 0x97, 0xa5,
+	0x73, 0x2c, 0x63, 0xcf, 0x2d, 0xd5, 0x74, 0xfc, 0xc6, 0xda, 0xc7, 0x7a,
+	0x1c, 0x5f, 0x17, 0x38, 0x1e, 0xdd, 0x10, 0xc7, 0x8f, 0x56, 0x71, 0x7c,
+	0xae, 0x4f, 0xe2, 0xf3, 0x45, 0x7e, 0x56, 0x0f, 0x1d, 0x16, 0xcf, 0xcd,
+	0xf2, 0xef, 0x4e, 0x3a, 0x2c, 0xfb, 0x62, 0xf0, 0xbb, 0x99, 0xc7, 0xe7,
+	0xb3, 0x74, 0xfe, 0x7a, 0x36, 0x90, 0x12, 0x35, 0x0a, 0xee, 0xbe, 0x1e,
+	0xfa, 0x7e, 0x8c, 0x6b, 0x86, 0xff, 0x9a, 0x2f, 0xc9, 0x9a, 0xab, 0x92,
+	0xe4, 0x4f, 0xf4, 0x76, 0x7c, 0xd0, 0x83, 0xff, 0xf5, 0x36, 0xe6, 0x05,
+	0x25, 0x03, 0x4f, 0x6c, 0xe0, 0xff, 0x68, 0xc4, 0xcb, 0x5e, 0x1f, 0xbd,
+	0xf9, 0x8d, 0x3e, 0x19, 0xbb, 0xda, 0xc8, 0xff, 0xe1, 0xc6, 0xd1, 0xba,
+	0x58, 0x3e, 0xf3, 0xfd, 0x84, 0xaa, 0xff, 0x7b, 0xa7, 0x4f, 0xca, 0x0b,
+	0xd4, 0x04, 0xa6, 0x19, 0x0e, 0x6f, 0xb2, 0xae, 0x32, 0x48, 0xad, 0xaf,
+	0xe8, 0xb5, 0x0e, 0x0a, 0x7e, 0xeb, 0xf6, 0xe7, 0x5c, 0x56, 0xb5, 0xe0,
+	0x39, 0xd7, 0x9a, 0x2e, 0x0b, 0x5b, 0xa8, 0x39, 0xbd, 0x35, 0xcf, 0xc3,
+	0x8a, 0x7a, 0x64, 0x82, 0x17, 0xdf, 0xd0, 0x2f, 0x05, 0xfb, 0x4b, 0x86,
+	0xd4, 0x83, 0x27, 0x59, 0xbf, 0xdd, 0x6e, 0x0c, 0xe9, 0x61, 0x75, 0x44,
+	0x6f, 0x4f, 0x0e, 0xef, 0x6f, 0xec, 0x83, 0xb4, 0x39, 0x32, 0xaf, 0x3d,
+	0x25, 0x78, 0xc1, 0xe5, 0xb1, 0x0a, 0x4d, 0xc7, 0xbb, 0x29, 0x33, 0xc6,
+	0xef, 0x9e, 0x44, 0x4f, 0xac, 0x20, 0x65, 0x99, 0x7e, 0x33, 0x63, 0x8f,
+	0x29, 0x7d, 0x51, 0xfb, 0xdd, 0xdb, 0x54, 0xee, 0xc3, 0x45, 0x11, 0xab,
+	0x94, 0xfd, 0x84, 0xf8, 0xf7, 0x92, 0x7e, 0xf6, 0x45, 0x11, 0x33, 0xcd,
+	0x5c, 0x6f, 0x55, 0xe3, 0x3a, 0x5d, 0xe3, 0x30, 0xa6, 0x53, 0x8d, 0xc5,
+	0x33, 0xb5, 0x4e, 0xd1, 0xae, 0xf8, 0x2d, 0xe8, 0x30, 0xad, 0x6a, 0xf5,
+	0x70, 0xfd, 0x02, 0xcd, 0x54, 0xd7, 0xd2, 0xc9, 0x63, 0xff, 0x5b, 0xf5,
+	0xf2, 0xe8, 0x64, 0x9d, 0x17, 0xf3, 0x6e, 0x9c, 0x13, 0xd6, 0x12, 0x14,
+	0x71, 0x24, 0xfe, 0xad, 0xde, 0x73, 0xa6, 0x3a, 0x27, 0xe4, 0x6d, 0xd8,
+	0x11, 0xf9, 0x2c, 0x3d, 0xae, 0xd3, 0x35, 0x4e, 0xf3, 0x0a, 0x1d, 0xa7,
+	0xf8, 0x57, 0x9e, 0xc7, 0x3f, 0xa8, 0xbc, 0x5e, 0x53, 0xc4, 0x54, 0x65,
+	0xde, 0x86, 0xfe, 0x0d, 0x3f, 0x34, 0xf2, 0x2c, 0x90, 0x3b, 0xe1, 0xe6,
+	0x37, 0x72, 0xbd, 0x21, 0xc8, 0xa2, 0x32, 0x62, 0xa9, 0x88, 0x6b, 0x34,
+	0xd3, 0x9d, 0xf7, 0x20, 0x5f, 0x7f, 0x1b, 0x3a, 0xe8, 0x56, 0xe8, 0xcf,
+	0xf2, 0xa1, 0x3f, 0xf7, 0xfb, 0x51, 0xeb, 0x86, 0x9a, 0xb7, 0x6c, 0xcc,
+	0xa0, 0x0a, 0xdb, 0x0a, 0x06, 0x95, 0xcc, 0x00, 0x9d, 0x77, 0xec, 0xf8,
+	0x12, 0xc9, 0x9a, 0xc9, 0xe9, 0x79, 0x3b, 0xb6, 0x4a, 0x87, 0xcc, 0x73,
+	0x24, 0x7b, 0x25, 0x94, 0x58, 0x06, 0x9f, 0xa1, 0x18, 0xdb, 0x47, 0x6c,
+	0x7f, 0x9e, 0x42, 0x5c, 0x46, 0xef, 0x0b, 0x6a, 0xe3, 0xf1, 0x37, 0xc6,
+	0x70, 0xba, 0xb9, 0x93, 0x3a, 0x12, 0xfc, 0xcc, 0x18, 0xf8, 0x13, 0x3f,
+	0x27, 0x4d, 0x49, 0xb6, 0x93, 0x60, 0xb3, 0x9e, 0x39, 0x65, 0x9b, 0x25,
+	0x32, 0x78, 0x2c, 0x6c, 0x57, 0x3c, 0x07, 0xf7, 0x27, 0xcc, 0x16, 0xf2,
+	0xd6, 0xe1, 0x5e, 0x14, 0x75, 0x8a, 0x6f, 0xc7, 0x0f, 0x92, 0xd1, 0x0f,
+	0x7e, 0x85, 0x7d, 0x1b, 0x55, 0xf1, 0xa4, 0x4b, 0xfc, 0xdb, 0x51, 0xbf,
+	0xbf, 0x2a, 0xea, 0xdd, 0xe4, 0x6f, 0xe0, 0xf6, 0x2f, 0xab, 0x3d, 0xab,
+	0xcb, 0x09, 0x89, 0x8c, 0x18, 0x5f, 0xa5, 0x0b, 0x4b, 0x1b, 0xf9, 0x66,
+	0xfc, 0xea, 0x5b, 0xbb, 0xb6, 0x58, 0xdf, 0xba, 0xbe, 0x53, 0xd6, 0x8c,
+	0xe1, 0xfd, 0x7e, 0xba, 0x97, 0x77, 0x6d, 0xee, 0x7a, 0xd5, 0xef, 0xd0,
+	0xb4, 0xac, 0x35, 0x56, 0xb8, 0x70, 0xbd, 0x89, 0x7f, 0xf3, 0x49, 0x21,
+	0x2f, 0xcf, 0xca, 0x38, 0xc3, 0x80, 0xec, 0x6d, 0x16, 0xa2, 0xe5, 0x6a,
+	0xed, 0x67, 0x50, 0xd5, 0x7f, 0x30, 0x53, 0x7c, 0xa4, 0x75, 0x9f, 0x3a,
+	0x57, 0x15, 0x71, 0xa7, 0xb4, 0x2b, 0x8f, 0x22, 0xa4, 0xf2, 0x24, 0x70,
+	0xdf, 0x48, 0x18, 0x75, 0x5b, 0xb2, 0xd6, 0x12, 0x63, 0x50, 0xe7, 0x08,
+	0x1b, 0x12, 0x75, 0xae, 0xf0, 0xfb, 0x35, 0xab, 0x05, 0xc5, 0x78, 0xf8,
+	0x9f, 0xb4, 0x5d, 0x78, 0x5a, 0xd0, 0x98, 0x7c, 0xa7, 0xac, 0xd9, 0x5c,
+	0x5c, 0x39, 0x23, 0xea, 0x24, 0x93, 0xaa, 0xf6, 0x33, 0x43, 0x5d, 0x42,
+	0x6f, 0xfa, 0xf8, 0x35, 0x9b, 0xe7, 0xc2, 0xdb, 0xaf, 0xd9, 0x74, 0xdf,
+	0xb3, 0xbd, 0x9a, 0x4d, 0x93, 0xd7, 0x6e, 0x2c, 0xc8, 0x9a, 0xcd, 0xfa,
+	0x58, 0x80, 0xf4, 0x43, 0x65, 0x5c, 0xf2, 0x48, 0xea, 0x7f, 0x5f, 0x72,
+	0xe5, 0x08, 0xcb, 0x7a, 0xcc, 0xc5, 0xaa, 0x0e, 0x24, 0xeb, 0x31, 0x65,
+	0x4e, 0xb1, 0xbb, 0x0f, 0x89, 0x8c, 0x39, 0xc8, 0xf7, 0x74, 0x7b, 0x62,
+	0x0e, 0x2d, 0x4c, 0xa3, 0xa3, 0xaa, 0xe6, 0xbc, 0x19, 0x6e, 0xd6, 0xd9,
+	0x2a, 0x4c, 0x73, 0x15, 0xfa, 0x69, 0xfc, 0xd3, 0x74, 0x3f, 0x1c, 0x51,
+	0xb9, 0x74, 0xc8, 0x9d, 0x3b, 0xa8, 0xe0, 0xa8, 0xf5, 0x0f, 0xf2, 0xd1,
+	0x3f, 0x7e, 0x5b, 0xe4, 0x10, 0x4b, 0xfd, 0x65, 0x50, 0xd1, 0x24, 0xe8,
+	0x36, 0xe2, 0xa2, 0xdb, 0x5d, 0x4d, 0xe8, 0x16, 0xf4, 0xf9, 0xdd, 0x1d,
+	0xb2, 0x4f, 0x01, 0xe2, 0xde, 0xdf, 0x57, 0xbf, 0x37, 0xa3, 0xbf, 0xf7,
+	0x78, 0x6f, 0x40, 0x83, 0x78, 0xc6, 0x87, 0xe1, 0x1a, 0x1d, 0xea, 0xdf,
+	0x98, 0xcb, 0x7e, 0xd7, 0x5c, 0x86, 0x5d, 0x73, 0xd9, 0xd7, 0x64, 0x2e,
+	0xac, 0x4f, 0x94, 0x2f, 0xf0, 0xff, 0x8f, 0x3b, 0x27, 0xe1, 0xab, 0x65,
+	0x5a, 0x8d, 0x0b, 0xf9, 0x9a, 0x03, 0x1c, 0x85, 0x9e, 0x32, 0xaa, 0xea,
+	0xe0, 0xdd, 0xf3, 0x6c, 0x66, 0xab, 0x41, 0x16, 0xa0, 0xd7, 0x41, 0x82,
+	0xef, 0xeb, 0x6c, 0xd2, 0xeb, 0x00, 0x3a, 0x86, 0x5f, 0xaf, 0x03, 0x37,
+	0x8f, 0x77, 0xeb, 0x52, 0xd0, 0x7d, 0x21, 0x03, 0xa1, 0xf3, 0xa2, 0x57,
+	0xc1, 0x2f, 0xd1, 0x85, 0xaa, 0x8e, 0x79, 0x90, 0xd2, 0x4a, 0xc7, 0xbc,
+	0xb0, 0xa4, 0xf7, 0x7c, 0xd8, 0xb3, 0xe7, 0x7e, 0x3a, 0xe7, 0x90, 0xca,
+	0xf1, 0xd1, 0xb0, 0xca, 0xba, 0x60, 0x95, 0xf5, 0x81, 0x95, 0x78, 0x47,
+	0x93, 0x79, 0x03, 0x3e, 0xb8, 0x07, 0xff, 0xbf, 0x13, 0x41, 0x8f, 0x16,
+	0xa2, 0xdf, 0xd8, 0x55, 0xf3, 0x0b, 0xe8, 0xdf, 0x98, 0x63, 0xd3, 0xdc,
+	0x4f, 0xa5, 0x0f, 0x0e, 0x06, 0x8e, 0x5c, 0x67, 0x03, 0x9d, 0x65, 0x5e,
+	0xbd, 0x2d, 0xa8, 0x75, 0x85, 0x03, 0x82, 0xef, 0xdd, 0x0f, 0x22, 0x77,
+	0x45, 0x9f, 0xeb, 0xd6, 0xbe, 0x5c, 0xb5, 0xfe, 0xd6, 0x3a, 0x7d, 0xa2,
+	0xa6, 0x4b, 0xe8, 0x1c, 0x54, 0xfd, 0x5b, 0xcb, 0xc0, 0x7b, 0x75, 0xfe,
+	0x89, 0x5b, 0x75, 0xfd, 0x06, 0xe1, 0x0b, 0xea, 0x4e, 0x1b, 0x4e, 0x4a,
+	0xe4, 0x91, 0xf6, 0x3a, 0xf0, 0x7b, 0x25, 0x99, 0x37, 0xf7, 0xa6, 0x91,
+	0xb3, 0xdc, 0x7b, 0xcd, 0xa2, 0x93, 0xf9, 0x2f, 0xed, 0x95, 0x74, 0x7a,
+	0x89, 0x86, 0xc7, 0x79, 0xfc, 0x14, 0x7c, 0xbd, 0x76, 0x2c, 0xc9, 0x4a,
+	0xe4, 0x5c, 0xb9, 0x8d, 0x16, 0x59, 0x5b, 0x0f, 0x3a, 0x25, 0xe1, 0xbb,
+	0x63, 0x99, 0x51, 0x40, 0x6f, 0x55, 0x63, 0xa1, 0x95, 0x9f, 0xdb, 0x4f,
+	0xcb, 0x45, 0xd0, 0x7c, 0x8b, 0xea, 0x11, 0x82, 0xb1, 0x01, 0xea, 0x73,
+	0xfe, 0x84, 0xe1, 0xf5, 0x05, 0x91, 0x47, 0xb9, 0x58, 0xb8, 0x24, 0xff,
+	0x96, 0x5e, 0x52, 0xef, 0xe0, 0xf7, 0x95, 0xff, 0x86, 0x12, 0x7d, 0x96,
+	0xcb, 0x36, 0x73, 0xff, 0xf3, 0xd7, 0x3f, 0x8e, 0x6f, 0x4b, 0xff, 0xc8,
+	0xa6, 0x6b, 0xfa, 0x87, 0xfb, 0xd9, 0x5a, 0x17, 0x39, 0xd6, 0x2f, 0xfb,
+	0x37, 0x00, 0x06, 0x9d, 0xd0, 0xad, 0xd2, 0x80, 0xa5, 0x31, 0x65, 0x47,
+	0x92, 0xc1, 0x49, 0x9a, 0x2d, 0x47, 0x8d, 0x4c, 0x01, 0x3a, 0x30, 0xff,
+	0x2d, 0x5d, 0xd9, 0x2d, 0x7d, 0x2e, 0xfa, 0x1e, 0xf0, 0xf5, 0x9d, 0x3c,
+	0xfe, 0x3f, 0xfa, 0x65, 0xee, 0xb5, 0xfb, 0x7c, 0x0f, 0x9f, 0x7f, 0x2e,
+	0x52, 0x7f, 0xfe, 0x31, 0x3e, 0xdf, 0xc7, 0xe7, 0xe1, 0x87, 0x84, 0x9f,
+	0x31, 0x46, 0x39, 0xde, 0x9f, 0xd9, 0x32, 0xf3, 0xa9, 0x57, 0x58, 0x5e,
+	0x2c, 0xe9, 0x71, 0xbb, 0x50, 0x97, 0x23, 0xf6, 0xc4, 0xe0, 0x31, 0x97,
+	0xf3, 0x63, 0x3c, 0x6e, 0x90, 0x82, 0xaf, 0x58, 0x34, 0xbb, 0xa4, 0x71,
+	0x52, 0xe7, 0xd4, 0xbf, 0xc3, 0xf0, 0x45, 0xde, 0xce, 0x47, 0xbb, 0x25,
+	0xfc, 0x62, 0xc2, 0x87, 0x89, 0x3c, 0x8e, 0x2b, 0x02, 0xf7, 0xec, 0x49,
+	0xab, 0xfa, 0x7e, 0xe0, 0x96, 0x88, 0x73, 0xf0, 0x1a, 0x58, 0x2e, 0x4d,
+	0x39, 0x66, 0xae, 0x9a, 0x8f, 0xf6, 0xe7, 0x03, 0xf2, 0xfe, 0xff, 0xda,
+	0x25, 0xfb, 0xa3, 0xbe, 0x3f, 0xa0, 0xfb, 0x24, 0x4a, 0x9d, 0x00, 0x39,
+	0xca, 0x01, 0x01, 0x9b, 0xe0, 0x02, 0xe4, 0x95, 0xc1, 0xbf, 0x79, 0x3d,
+	0x69, 0xcc, 0xb1, 0xad, 0x5f, 0xf7, 0x7c, 0x91, 0xeb, 0x3a, 0xc6, 0xf3,
+	0x4d, 0xf1, 0xba, 0xf4, 0xf9, 0x04, 0x1f, 0xfb, 0xed, 0x2f, 0x9e, 0xd5,
+	0x91, 0x46, 0x5d, 0x70, 0xe6, 0x54, 0x47, 0x3a, 0x13, 0x93, 0xfb, 0x5c,
+	0xf3, 0xd1, 0x46, 0xaa, 0x3e, 0xda, 0xb9, 0xfc, 0x78, 0x3f, 0xfc, 0x15,
+	0xc6, 0x35, 0xde, 0xef, 0xf0, 0x15, 0x1e, 0x8b, 0x7a, 0x84, 0x1c, 0xff,
+	0xed, 0x52, 0xf9, 0x3c, 0x8d, 0xb8, 0x22, 0xf3, 0x23, 0xb4, 0x5e, 0x81,
+	0x7b, 0x9f, 0xe0, 0x67, 0x48, 0xdd, 0xa2, 0xf9, 0x7b, 0xa8, 0x21, 0xff,
+	0xa5, 0x11, 0xc7, 0x36, 0xf2, 0xab, 0x8a, 0x38, 0xa2, 0x0f, 0x9e, 0x6d,
+	0xd4, 0x83, 0xe0, 0x9e, 0xf0, 0x8b, 0x4d, 0x37, 0xd0, 0x2b, 0xe8, 0x38,
+	0x44, 0x2f, 0xcc, 0x67, 0xe9, 0x31, 0xde, 0xab, 0x3f, 0x30, 0x3e, 0x83,
+	0x38, 0x3b, 0xc9, 0x5c, 0x27, 0x86, 0x71, 0xde, 0x89, 0x9d, 0x33, 0x52,
+	0xe0, 0x8b, 0x95, 0x90, 0xd3, 0x45, 0xad, 0x4c, 0xab, 0xbf, 0x49, 0x23,
+	0x6c, 0xcf, 0x81, 0x66, 0x9d, 0x48, 0x8a, 0x40, 0x6f, 0xb6, 0x79, 0x84,
+	0x71, 0x62, 0xba, 0x0c, 0x7c, 0x36, 0xe8, 0x8b, 0x45, 0xa2, 0xe7, 0x8b,
+	0x23, 0xe6, 0xf7, 0xc8, 0xb1, 0x6a, 0xd7, 0x6d, 0x33, 0xc9, 0xf3, 0x48,
+	0x95, 0x5f, 0xa2, 0xf7, 0x44, 0xdf, 0x12, 0xc0, 0x51, 0xef, 0xfb, 0x1f,
+	0xd1, 0x99, 0x34, 0xe6, 0xbd, 0x75, 0xfa, 0x3c, 0xb9, 0x2d, 0xfa, 0xec,
+	0xf0, 0xa1, 0xcf, 0x7f, 0x54, 0x78, 0x53, 0x61, 0x1c, 0xed, 0xa0, 0x99,
+	0x02, 0x72, 0xbf, 0x3e, 0x8b, 0xfe, 0x52, 0x85, 0x0c, 0xf3, 0xa5, 0x4c,
+	0x8d, 0x2f, 0x5d, 0x4d, 0x06, 0x13, 0xa0, 0x71, 0xf4, 0x65, 0x53, 0xf9,
+	0x3e, 0x58, 0xc7, 0x00, 0x8d, 0x2c, 0x74, 0x22, 0xf6, 0xb5, 0x9a, 0x9c,
+	0x48, 0xa8, 0xfa, 0x7c, 0xdb, 0x9a, 0x66, 0xfe, 0x38, 0xc7, 0xb4, 0x9c,
+	0x2b, 0x1c, 0xa4, 0xc5, 0x70, 0x94, 0x86, 0x17, 0x74, 0xbf, 0x12, 0x11,
+	0x37, 0x89, 0x4a, 0x9e, 0xa4, 0xd7, 0xfd, 0x84, 0xf0, 0x45, 0x58, 0x37,
+	0x3f, 0xa9, 0x75, 0x77, 0x6e, 0xc2, 0x97, 0xde, 0x57, 0x34, 0x5b, 0xb9,
+	0x95, 0x8c, 0x53, 0x36, 0x39, 0xf1, 0xef, 0x02, 0xff, 0x87, 0x6f, 0xc2,
+	0xaf, 0x06, 0x1e, 0x6d, 0x51, 0x3a, 0xef, 0x85, 0x45, 0x94, 0xd7, 0x8d,
+	0xeb, 0x95, 0x0f, 0x67, 0xe2, 0x2f, 0x09, 0xdd, 0x6b, 0xe4, 0x26, 0x8f,
+	0x13, 0xf2, 0x48, 0xf3, 0x0d, 0x3f, 0x3c, 0xd4, 0x3d, 0x29, 0x35, 0x2e,
+	0xca, 0x7c, 0x4e, 0x93, 0x9f, 0x9b, 0x0e, 0x7a, 0x71, 0xf2, 0x5e, 0xe0,
+	0xf8, 0xbc, 0x45, 0x27, 0xf2, 0xf6, 0xab, 0x59, 0x9a, 0x64, 0xba, 0x76,
+	0xcb, 0x0b, 0x1e, 0x4f, 0xc0, 0xb3, 0x29, 0xd0, 0x3e, 0x65, 0x0a, 0x96,
+	0xcc, 0xb7, 0x13, 0x3d, 0xe5, 0x70, 0x8c, 0xda, 0xe2, 0xee, 0xdd, 0x5a,
+	0x1e, 0x64, 0x0a, 0xa8, 0x15, 0xe4, 0xbf, 0x25, 0x1e, 0x8f, 0xfc, 0xfe,
+	0x22, 0x9e, 0x03, 0x19, 0x87, 0xb9, 0xf3, 0xf1, 0xb2, 0xdc, 0xd7, 0x61,
+	0x7e, 0xf6, 0xc8, 0x38, 0xbf, 0xb3, 0x3c, 0xc6, 0xfb, 0xdb, 0x23, 0x78,
+	0xb3, 0xdc, 0xcf, 0x29, 0xba, 0xec, 0xcb, 0x57, 0xe4, 0xbe, 0x64, 0x5c,
+	0xf4, 0x9d, 0x11, 0xf4, 0x3d, 0x25, 0xf6, 0x23, 0x53, 0x34, 0x58, 0x5f,
+	0xd6, 0xbe, 0x04, 0xb6, 0x9b, 0x8b, 0x21, 0xc5, 0x43, 0x70, 0xed, 0x89,
+	0xdd, 0x22, 0x1f, 0x11, 0xf6, 0x74, 0x11, 0x7f, 0xa7, 0xe8, 0x0a, 0xeb,
+	0xfd, 0x2f, 0xe7, 0xdb, 0xe8, 0x4e, 0xa1, 0x8d, 0xee, 0x16, 0xa2, 0x74,
+	0x7b, 0x7e, 0x07, 0x5d, 0x66, 0x9b, 0xe6, 0xb2, 0x13, 0xb2, 0x72, 0xb4,
+	0x03, 0xf1, 0x42, 0xe4, 0x0a, 0x31, 0xdd, 0x61, 0x3c, 0xf4, 0xef, 0xe4,
+	0x1e, 0xc6, 0x39, 0xb6, 0x8d, 0xda, 0xe9, 0x5d, 0x7e, 0x67, 0x2e, 0xaf,
+	0x73, 0x1c, 0xe0, 0x63, 0xdf, 0x5f, 0xb5, 0x1f, 0x36, 0xc7, 0x11, 0x73,
+	0x13, 0x1c, 0x99, 0x12, 0xbc, 0x7e, 0x76, 0x3e, 0x8a, 0xbe, 0xca, 0xd9,
+	0x16, 0xf8, 0x49, 0x99, 0x3f, 0x3f, 0x17, 0xc2, 0x78, 0x9c, 0x73, 0x64,
+	0x8e, 0xa4, 0x58, 0x5b, 0x84, 0x8f, 0x03, 0xa2, 0x0e, 0x5a, 0xc2, 0xa1,
+	0x9d, 0xd7, 0x17, 0x10, 0xe3, 0x33, 0xcb, 0xed, 0x74, 0xb6, 0x68, 0xf2,
+	0x71, 0x90, 0xf5, 0x44, 0x8c, 0xed, 0xdd, 0xa7, 0xfb, 0xcb, 0x5e, 0xe6,
+	0xb9, 0xe7, 0xc4, 0x38, 0xfe, 0xbb, 0xdc, 0x43, 0xb3, 0xc5, 0x2e, 0x75,
+	0x7c, 0x50, 0xe6, 0xf2, 0x8a, 0x5c, 0x6c, 0x5c, 0xdb, 0x88, 0xbf, 0xbd,
+	0xcd, 0x38, 0x05, 0x99, 0x2a, 0x75, 0x7c, 0xf0, 0x9a, 0x5b, 0x0d, 0xfd,
+	0x90, 0x81, 0x73, 0x93, 0xf4, 0x4d, 0x96, 0xb7, 0xc3, 0xaf, 0xc0, 0x1f,
+	0xfc, 0xfb, 0xc0, 0x9b, 0x52, 0x96, 0x06, 0xf9, 0x18, 0x7d, 0x8e, 0x82,
+	0xa2, 0x96, 0x69, 0x3a, 0x1c, 0x13, 0xf5, 0x1f, 0x92, 0x46, 0x4f, 0x89,
+	0x9e, 0x73, 0x3f, 0x12, 0xbc, 0xc9, 0xce, 0x5a, 0x06, 0xf4, 0x11, 0xf8,
+	0x54, 0x64, 0xee, 0xd5, 0x49, 0xa7, 0xf7, 0xed, 0x5d, 0x53, 0xa3, 0x94,
+	0xe8, 0x07, 0xde, 0x4b, 0x9a, 0x55, 0x3d, 0x04, 0x04, 0xbf, 0x37, 0x0f,
+	0xe8, 0x9a, 0x48, 0x7d, 0xac, 0x65, 0x85, 0x3e, 0xee, 0xf2, 0x5c, 0x37,
+	0x3d, 0xd7, 0xab, 0x79, 0x72, 0x2c, 0xf3, 0x58, 0xce, 0x93, 0xec, 0x39,
+	0x84, 0xbe, 0x71, 0xc0, 0x3f, 0xf3, 0xc0, 0x7e, 0xf3, 0x73, 0xca, 0x06,
+	0xca, 0xac, 0x8c, 0x44, 0x7a, 0x8d, 0x98, 0x91, 0x19, 0xfb, 0x97, 0x4a,
+	0x22, 0x0d, 0xbd, 0xe8, 0xc6, 0x6e, 0xc9, 0xe3, 0x30, 0xaf, 0x6c, 0x1c,
+	0xaa, 0xdb, 0xa9, 0x95, 0x2e, 0x5a, 0x15, 0x7d, 0xb5, 0xa0, 0x63, 0xe0,
+	0x7e, 0x3c, 0x27, 0x6b, 0xb6, 0xb0, 0x7d, 0x77, 0xc3, 0x01, 0x8d, 0x1f,
+	0x8a, 0xdc, 0xe4, 0xfd, 0x4c, 0xad, 0x7c, 0x54, 0x39, 0x23, 0xfa, 0xd2,
+	0x60, 0x6c, 0x0f, 0xcd, 0x08, 0x9b, 0x8b, 0xf5, 0x97, 0x3a, 0xbb, 0x76,
+	0x12, 0xf3, 0xcc, 0x22, 0x56, 0x62, 0x38, 0xdf, 0x0e, 0x64, 0x4a, 0x32,
+	0xf6, 0x9d, 0xf2, 0xc4, 0xbe, 0x4f, 0x89, 0xd8, 0x37, 0xe2, 0xde, 0x80,
+	0x2b, 0x60, 0xe9, 0x97, 0xcb, 0x82, 0x7d, 0x8c, 0xf3, 0x3e, 0x5a, 0x34,
+	0x77, 0x5d, 0xf0, 0x9b, 0xc9, 0xe9, 0x60, 0xa2, 0xb7, 0x85, 0xac, 0x40,
+	0xd2, 0xb1, 0xe3, 0x0f, 0x58, 0x87, 0xb8, 0x5d, 0xc0, 0x3c, 0x5f, 0xa2,
+	0xf5, 0x52, 0x0b, 0xd3, 0x89, 0xcd, 0x78, 0xb7, 0xca, 0x3a, 0xed, 0x2c,
+	0xbd, 0x5b, 0x22, 0xba, 0x5d, 0xbc, 0x8a, 0x5e, 0xbb, 0xb1, 0x07, 0x4c,
+	0x2b, 0x88, 0x05, 0x67, 0x62, 0xf0, 0xb1, 0xb1, 0x5e, 0x1b, 0x6b, 0x55,
+	0xb8, 0xd9, 0xc5, 0xb6, 0xa3, 0xc9, 0xff, 0x1d, 0xfe, 0x1f, 0x89, 0x00,
+	0x2e, 0x6b, 0xc5, 0x31, 0xc1, 0x4b, 0x97, 0xf8, 0xfc, 0x12, 0x9f, 0x87,
+	0x4c, 0x5d, 0x2b, 0x56, 0xde, 0x49, 0xc6, 0x13, 0x56, 0x72, 0xe2, 0xa4,
+	0x1c, 0xc3, 0x38, 0x77, 0xf9, 0x7a, 0x62, 0x4f, 0x88, 0xe7, 0x31, 0xc3,
+	0xf3, 0x58, 0x27, 0x99, 0xeb, 0x9d, 0x12, 0xef, 0x26, 0xba, 0x23, 0xde,
+	0xcb, 0x3a, 0x53, 0xfc, 0x71, 0x3a, 0x13, 0x96, 0xef, 0xcf, 0xc5, 0x51,
+	0x73, 0xd5, 0x49, 0xb3, 0x63, 0xa3, 0xaa, 0xe6, 0xea, 0xcd, 0x26, 0x35,
+	0x57, 0xed, 0xb4, 0x36, 0x0f, 0xbb, 0xb7, 0x9d, 0xe9, 0xdd, 0x14, 0xb9,
+	0x7a, 0x6b, 0xf3, 0xa2, 0x1f, 0x3e, 0xaf, 0xa7, 0xb2, 0x3e, 0xc3, 0xaa,
+	0x79, 0x26, 0xde, 0x2d, 0x74, 0xa7, 0xdb, 0xcb, 0xbf, 0xc5, 0xf3, 0x49,
+	0x58, 0x99, 0x09, 0xf7, 0x3a, 0xc4, 0x7c, 0xd7, 0xa7, 0xc5, 0xb8, 0xa0,
+	0x67, 0x5c, 0x82, 0x32, 0x13, 0x98, 0xbf, 0x18, 0xf3, 0x3f, 0xc9, 0xb8,
+	0x5e, 0x8f, 0xfb, 0x7e, 0x8b, 0x72, 0x42, 0xdf, 0xe7, 0xbf, 0x4b, 0x3d,
+	0x81, 0xf5, 0x02, 0xfc, 0x26, 0x06, 0xe3, 0x3f, 0xe6, 0x66, 0x51, 0x76,
+	0x89, 0xd7, 0x75, 0xbd, 0x2b, 0xf0, 0xa0, 0xf0, 0x93, 0x4a, 0xa6, 0x2e,
+	0xb7, 0xa5, 0xde, 0xbf, 0x2e, 0x6d, 0xae, 0x28, 0x39, 0xd7, 0x20, 0x4b,
+	0x21, 0x47, 0xb3, 0x95, 0xa0, 0x03, 0xbd, 0x0f, 0xb6, 0xd0, 0x25, 0xe6,
+	0x63, 0x32, 0x3f, 0x89, 0x79, 0x2a, 0xf3, 0x32, 0x49, 0x47, 0xa9, 0xba,
+	0xcf, 0x32, 0x48, 0x5c, 0x1e, 0xae, 0xe5, 0x45, 0xba, 0xe2, 0xe6, 0x21,
+	0x57, 0xdc, 0xdc, 0x74, 0xe5, 0x45, 0x86, 0x85, 0x9e, 0x56, 0xd3, 0xad,
+	0xc2, 0x4a, 0xb7, 0x8a, 0x8a, 0x9e, 0xf4, 0xe0, 0x71, 0x8b, 0x55, 0x1e,
+	0xb7, 0x73, 0x13, 0x1e, 0xe7, 0x67, 0x9b, 0xae, 0x2a, 0x7e, 0x62, 0xc7,
+	0x21, 0x6b, 0x6e, 0x31, 0xdf, 0xf8, 0x71, 0x79, 0x82, 0xf9, 0x49, 0x9c,
+	0xf9, 0xc9, 0x18, 0xf3, 0x93, 0x18, 0xf3, 0x13, 0x87, 0x61, 0x60, 0xf1,
+	0xda, 0xef, 0x05, 0x6e, 0xcf, 0x43, 0x8e, 0x4c, 0xd2, 0x95, 0x32, 0x78,
+	0xf3, 0x18, 0xeb, 0x42, 0xf7, 0x02, 0x6b, 0xf3, 0x3d, 0x8c, 0xc7, 0x52,
+	0xff, 0xa9, 0xb7, 0x6f, 0xec, 0x57, 0x51, 0x1f, 0x97, 0x8c, 0xaf, 0x81,
+	0xff, 0xbc, 0x99, 0xa5, 0xee, 0xc0, 0xed, 0x42, 0x57, 0x60, 0xad, 0xf0,
+	0x13, 0xf4, 0xa5, 0x78, 0x1d, 0x34, 0x8e, 0xbe, 0xbf, 0x3f, 0x1c, 0x9d,
+	0xe4, 0xb9, 0x77, 0x07, 0x66, 0x79, 0x5f, 0xbe, 0x12, 0x4f, 0xf4, 0xf6,
+	0x49, 0x5a, 0xc8, 0xe6, 0xc0, 0x3d, 0x17, 0x76, 0xd0, 0xfe, 0xf1, 0xe4,
+	0x9e, 0x5e, 0xa6, 0x5b, 0xe0, 0x7b, 0xad, 0xef, 0x4e, 0x90, 0xf1, 0xb0,
+	0x43, 0xf5, 0xeb, 0xb1, 0x58, 0x5e, 0x7e, 0xc8, 0xf7, 0x7f, 0x10, 0xc8,
+	0x15, 0x5e, 0xe3, 0x67, 0xe3, 0xf8, 0x4f, 0xe1, 0xdf, 0x64, 0x7b, 0x01,
+	0xbd, 0x7e, 0x3a, 0x79, 0x0c, 0xc6, 0xe2, 0xd8, 0x8e, 0x31, 0x6f, 0x8b,
+	0xaf, 0x1a, 0xf6, 0x64, 0xc2, 0x78, 0x3e, 0x8a, 0x9e, 0xf1, 0x3f, 0x2c,
+	0x3f, 0x15, 0x95, 0x31, 0xb6, 0xe7, 0xf6, 0x48, 0x3e, 0xc2, 0xb8, 0x19,
+	0x4e, 0x08, 0x9b, 0xad, 0xe5, 0x9a, 0x94, 0x9b, 0x8b, 0xbc, 0xbf, 0x4b,
+	0xf1, 0x18, 0xef, 0x6f, 0x97, 0x92, 0x99, 0x59, 0xbe, 0x2e, 0xe4, 0x31,
+	0xcb, 0x4e, 0x86, 0x77, 0x91, 0x4c, 0xd1, 0x03, 0xe2, 0x14, 0xfa, 0xea,
+	0x3c, 0x83, 0xe7, 0x31, 0xb6, 0x82, 0x6f, 0x7c, 0x18, 0xc8, 0x14, 0xf0,
+	0x5e, 0xe0, 0x1f, 0xff, 0x2e, 0x4d, 0xd2, 0xd5, 0xbc, 0x9e, 0xc3, 0x80,
+	0x61, 0x7c, 0x13, 0xf3, 0x08, 0xd0, 0x4e, 0xe7, 0xdf, 0x18, 0x4e, 0x7c,
+	0xfc, 0x97, 0xde, 0x39, 0x9d, 0x57, 0x73, 0x42, 0x9f, 0xca, 0x36, 0x5e,
+	0xc3, 0x4e, 0x42, 0xff, 0xa2, 0x45, 0xd1, 0x47, 0xb2, 0x55, 0xd8, 0xaa,
+	0x8b, 0xc2, 0xe6, 0x38, 0xba, 0xa7, 0xd6, 0xdb, 0xf2, 0x71, 0xcf, 0xb9,
+	0x9f, 0x07, 0x72, 0xf3, 0x87, 0x85, 0x6e, 0x36, 0x3c, 0xbe, 0x47, 0xd5,
+	0x9c, 0x7e, 0x5e, 0x5c, 0x33, 0x16, 0x70, 0xed, 0x49, 0x75, 0xed, 0xd7,
+	0x84, 0x4e, 0x8c, 0xfc, 0xb8, 0xd0, 0x35, 0x81, 0xdf, 0xbc, 0xaf, 0x4e,
+	0x8c, 0xf1, 0x3b, 0xb2, 0x04, 0xdf, 0xbc, 0x80, 0xa7, 0x86, 0x07, 0x60,
+	0x01, 0x9c, 0xef, 0x52, 0xf8, 0x6e, 0x5b, 0xa9, 0xa0, 0x5e, 0x77, 0x33,
+	0x38, 0xb3, 0x8e, 0x93, 0xc7, 0x5a, 0xb1, 0xa6, 0xdd, 0x81, 0x44, 0xc9,
+	0x32, 0x72, 0xf3, 0xb0, 0x71, 0xe0, 0x7f, 0xdc, 0x8b, 0xbc, 0x28, 0x9e,
+	0xc3, 0x6e, 0x4a, 0xa4, 0x31, 0x2f, 0x8c, 0xd3, 0x30, 0x18, 0xf7, 0xc0,
+	0xc2, 0x7d, 0xdf, 0x0e, 0x75, 0x5f, 0xbb, 0xd8, 0x0b, 0x32, 0xf0, 0x1e,
+	0xfd, 0x6e, 0xbc, 0x17, 0xef, 0xc7, 0x7d, 0x78, 0x9e, 0x7c, 0xee, 0x2e,
+	0xe6, 0xd7, 0xc9, 0x09, 0xf9, 0x2c, 0xe3, 0xa6, 0xbc, 0xb6, 0xcb, 0xf1,
+	0x9f, 0xaf, 0xdc, 0x3f, 0xdc, 0xab, 0xf7, 0x6f, 0x07, 0x95, 0x84, 0x5f,
+	0x09, 0xd7, 0xba, 0xc5, 0xb5, 0xa4, 0xd3, 0x2d, 0xf6, 0x75, 0x8e, 0x8f,
+	0xcf, 0x16, 0x7a, 0x02, 0xb0, 0xd5, 0x73, 0xe9, 0xee, 0x40, 0xa9, 0x84,
+	0xf5, 0x76, 0x07, 0x52, 0x8c, 0xf3, 0xd3, 0x85, 0x23, 0x95, 0x59, 0xc1,
+	0x5b, 0x58, 0xc7, 0xed, 0xb3, 0xcd, 0x33, 0xc6, 0xcf, 0xc4, 0x9a, 0xf8,
+	0x7d, 0xfc, 0x9b, 0xe9, 0x2e, 0xcf, 0x74, 0x97, 0x67, 0xba, 0xcb, 0x33,
+	0xdd, 0xb1, 0x8d, 0xfa, 0x83, 0x3c, 0xd3, 0x1d, 0xcb, 0x90, 0xb7, 0x58,
+	0x86, 0x48, 0x5a, 0x4d, 0x28, 0xdf, 0x9e, 0xa6, 0x55, 0x6f, 0x4d, 0xa6,
+	0xa6, 0x4d, 0xc8, 0x6d, 0x0a, 0x1c, 0x1d, 0xad, 0xa7, 0xd1, 0x3b, 0x4c,
+	0xa3, 0x2d, 0x53, 0xfd, 0xf4, 0xa0, 0x88, 0x3d, 0xb3, 0xad, 0x39, 0xe6,
+	0xd1, 0xa9, 0x20, 0x74, 0xac, 0x10, 0xd3, 0x13, 0x74, 0x4c, 0x9b, 0xe1,
+	0xde, 0x4f, 0xeb, 0xc5, 0x76, 0x1e, 0x03, 0x9a, 0xdd, 0xab, 0x8e, 0xf3,
+	0x4c, 0xb3, 0x90, 0x7b, 0xd7, 0x02, 0x77, 0x0a, 0x06, 0xeb, 0x62, 0x21,
+	0x33, 0x43, 0xe0, 0x9f, 0x42, 0x3f, 0xe3, 0x7d, 0x5f, 0x65, 0x7e, 0x0f,
+	0xdf, 0x29, 0x7a, 0x77, 0x95, 0x20, 0x3b, 0x22, 0xb7, 0x99, 0x7f, 0x5e,
+	0x28, 0x5e, 0x63, 0x3a, 0xef, 0xa3, 0x2f, 0x17, 0x21, 0x9f, 0x01, 0x23,
+	0x3e, 0x2e, 0x91, 0xf0, 0x7d, 0x19, 0x53, 0x58, 0xfb, 0xfe, 0xac, 0x21,
+	0xf0, 0xe4, 0xaf, 0x01, 0x07, 0x86, 0xfd, 0xdd, 0x3d, 0xe8, 0x69, 0x9f,
+	0x30, 0x5a, 0x95, 0x8f, 0x17, 0xbf, 0x31, 0x1e, 0x63, 0x01, 0x37, 0x1c,
+	0x37, 0x8b, 0x2f, 0xe2, 0x1b, 0x11, 0x71, 0x86, 0x87, 0x97, 0x5f, 0x5d,
+	0xe5, 0xfb, 0x05, 0xbc, 0x26, 0x93, 0x41, 0xd4, 0x87, 0xd3, 0xd7, 0x82,
+	0x53, 0x93, 0xf4, 0x72, 0x19, 0xf3, 0xbe, 0x42, 0xb3, 0x61, 0xf0, 0x1f,
+	0x3b, 0x7e, 0x9f, 0x24, 0xec, 0xda, 0x59, 0xdf, 0xfc, 0xa2, 0x3f, 0x4f,
+	0xb3, 0x92, 0x42, 0x3f, 0x6e, 0x63, 0x7b, 0x07, 0xb0, 0x79, 0x83, 0x71,
+	0x2d, 0x0e, 0x1f, 0x80, 0xe2, 0x67, 0xdf, 0x67, 0x9e, 0x83, 0x3d, 0xc3,
+	0x71, 0x3d, 0x0f, 0x5b, 0x53, 0x3c, 0xcc, 0x71, 0xf1, 0xb0, 0x5c, 0x95,
+	0x87, 0x31, 0x2e, 0x08, 0xde, 0x05, 0xde, 0x74, 0x82, 0xf5, 0x45, 0xf9,
+	0x1b, 0x7a, 0xe0, 0x4e, 0xc1, 0xab, 0x98, 0xb7, 0xb3, 0xfd, 0xb0, 0x58,
+	0xce, 0x06, 0x8e, 0x08, 0x9e, 0xa1, 0xf1, 0xf9, 0xa9, 0x01, 0x49, 0x07,
+	0xed, 0xd2, 0x1f, 0x79, 0x0a, 0x7c, 0xca, 0x6f, 0xfc, 0x67, 0x78, 0x1c,
+	0xc6, 0x3b, 0x91, 0xd7, 0x99, 0x7f, 0x2d, 0xc6, 0x63, 0x22, 0x06, 0x22,
+	0x6d, 0x9c, 0x2c, 0xdb, 0x01, 0xbb, 0x90, 0x6b, 0x69, 0x25, 0xab, 0xfc,
+	0x4b, 0xd7, 0x1f, 0xc1, 0xaf, 0x88, 0x3d, 0x4e, 0xf4, 0x1a, 0x72, 0x1d,
+	0x16, 0xd6, 0x31, 0x5b, 0xa4, 0xd0, 0x4c, 0x1c, 0xb9, 0x71, 0xe0, 0xeb,
+	0x1f, 0xf0, 0xba, 0xb1, 0xaf, 0x1f, 0x60, 0x5f, 0xe5, 0xb5, 0x89, 0x63,
+	0x62, 0x5e, 0xb3, 0xcb, 0x35, 0xfe, 0x37, 0x97, 0x1f, 0x30, 0x16, 0x0b,
+	0x72, 0x6e, 0x4b, 0xa3, 0x92, 0xc7, 0x2d, 0x96, 0xd0, 0xab, 0x4b, 0xcc,
+	0x91, 0xe7, 0xa6, 0xd7, 0x85, 0xf7, 0x6a, 0x7a, 0xdf, 0x0a, 0x6d, 0x3d,
+	0xc3, 0x74, 0x84, 0x3d, 0xc8, 0xba, 0x70, 0xe4, 0x5b, 0xfc, 0x7e, 0x9c,
+	0x6b, 0x9c, 0xff, 0x83, 0xea, 0xfc, 0x9f, 0xe4, 0xf9, 0x63, 0xcc, 0x07,
+	0x2c, 0xef, 0xe5, 0xfc, 0x1f, 0x54, 0xe7, 0x5f, 0x54, 0xf3, 0xa7, 0x9c,
+	0x31, 0xd5, 0xab, 0xf4, 0xf7, 0xa6, 0xcf, 0x6a, 0x9f, 0x99, 0x10, 0x63,
+	0xcd, 0x19, 0xe8, 0x44, 0xa6, 0x9e, 0x8b, 0xb6, 0x0d, 0xdd, 0x73, 0xb1,
+	0x63, 0xf7, 0xe9, 0x8f, 0x49, 0xea, 0x1d, 0x43, 0xac, 0x77, 0xe0, 0x3c,
+	0xcd, 0x82, 0xcf, 0xe6, 0xc2, 0xe8, 0x11, 0x3b, 0xc8, 0x30, 0x62, 0x3b,
+	0x6a, 0x82, 0xff, 0x0a, 0xbf, 0x18, 0x9e, 0xa3, 0xef, 0xff, 0x43, 0x5a,
+	0x9f, 0x07, 0x2f, 0x86, 0xfe, 0x29, 0xfb, 0xc8, 0xae, 0xaf, 0x48, 0xff,
+	0x6b, 0xca, 0xd7, 0xff, 0x0a, 0xdf, 0xeb, 0x04, 0xf4, 0x73, 0x13, 0x7e,
+	0xda, 0x69, 0xf5, 0xed, 0x8f, 0x5c, 0x19, 0xcf, 0xf2, 0xe3, 0x2b, 0x93,
+	0xae, 0x1c, 0x35, 0xe4, 0x8c, 0x64, 0x99, 0x4f, 0x38, 0x66, 0x8b, 0x21,
+	0x6b, 0x64, 0x6e, 0x95, 0xb5, 0xae, 0x73, 0x8c, 0xf7, 0xc4, 0x89, 0x1b,
+	0x46, 0x4a, 0xf8, 0x08, 0xda, 0x9d, 0x2e, 0x6a, 0x63, 0x39, 0x78, 0x8e,
+	0xd0, 0xe7, 0xcc, 0xb6, 0x10, 0x3b, 0xb9, 0xca, 0x38, 0x36, 0x1b, 0xb7,
+	0x23, 0xcf, 0x0b, 0x7b, 0x12, 0xf2, 0x01, 0xdf, 0x4e, 0x01, 0xac, 0x30,
+	0x07, 0xfe, 0xbd, 0x8c, 0x9e, 0x95, 0x71, 0x5e, 0x3f, 0x7c, 0xbd, 0x23,
+	0xd6, 0x5d, 0x96, 0x2b, 0x57, 0x85, 0x3f, 0xe5, 0x12, 0xeb, 0x92, 0xb6,
+	0x79, 0x54, 0xd0, 0x99, 0x31, 0xc4, 0x54, 0xc1, 0x74, 0x82, 0x1c, 0x81,
+	0xfd, 0xa2, 0xa7, 0x8e, 0xb4, 0x51, 0x78, 0x95, 0x2b, 0xaa, 0x57, 0x41,
+	0x1a, 0xb4, 0xbf, 0x75, 0x5f, 0x42, 0xfa, 0xa1, 0x7d, 0x28, 0x6e, 0x1d,
+	0xca, 0xeb, 0xa7, 0x86, 0x3d, 0x66, 0x89, 0xde, 0x8c, 0x80, 0x9d, 0xf0,
+	0x03, 0x1a, 0x63, 0x0c, 0x37, 0xfd, 0x9d, 0x1a, 0xb7, 0xbd, 0x7f, 0x5e,
+	0xd4, 0xdc, 0xbf, 0x59, 0x96, 0x32, 0x34, 0xc7, 0xb6, 0xf8, 0xec, 0xb8,
+	0x5b, 0xa7, 0xb0, 0x0b, 0xd3, 0xc2, 0x07, 0x33, 0x40, 0xc9, 0x85, 0x31,
+	0xfa, 0x7c, 0x1e, 0x3c, 0x88, 0xee, 0x27, 0x1d, 0xf1, 0xcd, 0x25, 0x9e,
+	0xd3, 0x18, 0xa5, 0xca, 0x80, 0x51, 0x80, 0x66, 0x99, 0xcb, 0xe7, 0x0a,
+	0x88, 0xbd, 0xf3, 0xef, 0x12, 0xbe, 0xa9, 0xf2, 0x3b, 0xca, 0xb7, 0x1d,
+	0xa5, 0xe9, 0x05, 0xca, 0x66, 0xe2, 0x4f, 0x8b, 0x3e, 0xd3, 0x99, 0xf8,
+	0xa8, 0xf2, 0xc9, 0x44, 0xf8, 0x3c, 0xfc, 0x5c, 0x16, 0x7d, 0x2e, 0x6f,
+	0x67, 0x33, 0x24, 0x7d, 0x0d, 0xc4, 0x73, 0x30, 0x58, 0x76, 0xee, 0x64,
+	0x9e, 0x70, 0x52, 0xf8, 0x1b, 0x58, 0xd3, 0x98, 0xc7, 0x78, 0xf8, 0x0a,
+	0xfa, 0x08, 0xf6, 0x55, 0xa6, 0xf0, 0x92, 0x1a, 0x5b, 0x21, 0x93, 0x71,
+	0xc1, 0xfc, 0x55, 0x27, 0x1b, 0x37, 0x6a, 0xf7, 0xc3, 0x57, 0x71, 0x52,
+	0xe8, 0x7d, 0x43, 0xb4, 0x24, 0x68, 0xbd, 0x52, 0x99, 0x11, 0x7e, 0x07,
+	0x3e, 0x2e, 0x4d, 0x0e, 0x4a, 0x5e, 0x25, 0xcf, 0x4b, 0x7f, 0x04, 0x3f,
+	0xb3, 0xc4, 0xf3, 0xa8, 0xcb, 0x7f, 0x8f, 0x52, 0x62, 0x1b, 0xfe, 0xa1,
+	0x53, 0x8f, 0xd4, 0x3f, 0xc4, 0xb0, 0x66, 0xd9, 0x71, 0x8b, 0x69, 0xe3,
+	0xc7, 0x9b, 0xda, 0x6d, 0xef, 0x69, 0x19, 0xcc, 0xb0, 0x32, 0xc5, 0xb7,
+	0x2b, 0xa0, 0x33, 0xcf, 0x96, 0xe7, 0xf0, 0x1d, 0x99, 0x40, 0x5a, 0xe8,
+	0xb2, 0x11, 0xd6, 0x4d, 0xa0, 0xa3, 0x8c, 0x88, 0x78, 0x62, 0xe2, 0x59,
+	0xcb, 0x98, 0x5d, 0xc1, 0xb7, 0xa1, 0xa0, 0x9b, 0xe9, 0x9c, 0x86, 0x76,
+	0x91, 0xa7, 0x2e, 0xe3, 0xbc, 0x90, 0xaf, 0xe0, 0x79, 0x3f, 0x0f, 0x64,
+	0x56, 0x9e, 0xde, 0xa5, 0xf3, 0xd5, 0x12, 0x61, 0x9d, 0x0f, 0xa3, 0x79,
+	0x8a, 0xc6, 0x3d, 0x1d, 0xa3, 0x70, 0x7f, 0xcb, 0x0b, 0xb4, 0xeb, 0xd6,
+	0x09, 0xe0, 0x57, 0x12, 0x7b, 0x74, 0x15, 0xb1, 0x31, 0xa3, 0x2e, 0xfe,
+	0xd0, 0xc6, 0xfb, 0x64, 0x31, 0x6e, 0xc0, 0x5f, 0xf7, 0x05, 0xfe, 0x8b,
+	0x38, 0x42, 0x69, 0x10, 0x7a, 0x50, 0xaf, 0xc3, 0x38, 0x33, 0x81, 0xe3,
+	0x7e, 0x5a, 0x2c, 0x6a, 0xbd, 0x55, 0xfa, 0x90, 0x16, 0x97, 0xf5, 0x7e,
+	0xc1, 0x7f, 0x34, 0xac, 0x7a, 0x08, 0xd8, 0x64, 0xf5, 0x01, 0x4e, 0x9f,
+	0x14, 0x3d, 0x6e, 0x16, 0x73, 0xd8, 0x4a, 0xce, 0x11, 0xbe, 0x2f, 0x86,
+	0x9e, 0x99, 0xfb, 0x00, 0x7b, 0xde, 0x23, 0x77, 0x4c, 0x62, 0x4e, 0x7d,
+	0xff, 0xe7, 0x51, 0xed, 0xdb, 0x63, 0x3e, 0xfb, 0xf6, 0xd1, 0xa0, 0x8c,
+	0x73, 0x3d, 0xa7, 0xc6, 0xf8, 0xe5, 0x99, 0xfe, 0xf3, 0x0b, 0xf0, 0x1f,
+	0xd5, 0xea, 0x25, 0xee, 0x09, 0xbe, 0xd2, 0xe8, 0xc3, 0x8e, 0x30, 0x3f,
+	0x95, 0x74, 0x7c, 0xd2, 0x87, 0x8e, 0xfb, 0x78, 0x8f, 0x4f, 0x3c, 0x04,
+	0x1d, 0x9f, 0x68, 0x4a, 0xc7, 0x87, 0xa2, 0xd2, 0x87, 0xda, 0x48, 0xc7,
+	0xa8, 0xd9, 0x39, 0x59, 0x6e, 0xe6, 0xaf, 0xc2, 0x3e, 0xa0, 0xf6, 0x1c,
+	0xfe, 0x04, 0xc0, 0x4a, 0xfb, 0x14, 0x10, 0xdb, 0x03, 0x3e, 0x22, 0x56,
+	0xf2, 0x17, 0x94, 0x9a, 0xf7, 0xc6, 0x38, 0x37, 0xba, 0xe7, 0x7d, 0x9f,
+	0x7b, 0xa0, 0x6b, 0x83, 0x16, 0xec, 0x88, 0xb4, 0xd5, 0x35, 0xbc, 0xde,
+	0x0d, 0x1c, 0x29, 0xda, 0xd9, 0x12, 0x18, 0x63, 0x4f, 0x98, 0xce, 0x23,
+	0x8e, 0xaf, 0x7c, 0xbe, 0xc7, 0xf3, 0x72, 0xdd, 0xe6, 0xb8, 0xc0, 0x07,
+	0xe8, 0xa3, 0x91, 0x74, 0x30, 0xcd, 0x7b, 0x2a, 0xfd, 0xbd, 0x99, 0xe5,
+	0x88, 0xda, 0x27, 0x1e, 0x8b, 0xe7, 0xf9, 0xd6, 0xf3, 0x61, 0x7f, 0xec,
+	0x57, 0x57, 0xab, 0x79, 0xc1, 0x90, 0x05, 0x15, 0xfa, 0x05, 0xcb, 0xb9,
+	0xe0, 0xb8, 0x29, 0xfa, 0x28, 0xdc, 0x2a, 0x8f, 0xb3, 0x7e, 0x88, 0x3d,
+	0x84, 0xaf, 0x50, 0xfb, 0x72, 0x7f, 0x31, 0x44, 0x3d, 0x87, 0x58, 0xea,
+	0x1b, 0xe4, 0xb0, 0x7e, 0x68, 0x8c, 0x23, 0xbf, 0xdb, 0xe2, 0x7b, 0xd0,
+	0xff, 0x69, 0xbf, 0x95, 0xa2, 0x2e, 0xf8, 0x09, 0xd0, 0xa7, 0xd9, 0xca,
+	0xd5, 0xd1, 0xd4, 0x69, 0x41, 0x53, 0xa9, 0x95, 0xd3, 0x8a, 0xa6, 0x4e,
+	0x2b, 0x7f, 0xf9, 0x69, 0x45, 0x53, 0xa7, 0x15, 0x4d, 0x9d, 0x56, 0x34,
+	0x75, 0x9a, 0xf1, 0x7a, 0xc4, 0xec, 0x13, 0x3a, 0xbb, 0xf6, 0x57, 0xf6,
+	0x50, 0xa6, 0x88, 0xf3, 0x90, 0xc7, 0x5e, 0xba, 0x7a, 0x75, 0x48, 0xd2,
+	0xd5, 0x24, 0x2d, 0xca, 0x3c, 0x39, 0x7e, 0x17, 0xf6, 0xe0, 0xeb, 0x83,
+	0xd4, 0x73, 0x2f, 0x70, 0x76, 0x1e, 0x73, 0x0d, 0xd0, 0xb4, 0xe8, 0xe1,
+	0xda, 0x42, 0x49, 0xb7, 0x2e, 0x6b, 0xa2, 0x7e, 0x4b, 0xda, 0x6a, 0xd9,
+	0xa6, 0xb5, 0x5c, 0x1a, 0x2f, 0xa6, 0xd4, 0x7e, 0x79, 0xed, 0x98, 0x36,
+	0x4a, 0x17, 0x00, 0x57, 0xe4, 0x32, 0x5a, 0xbc, 0x37, 0x02, 0x4e, 0x59,
+	0xd3, 0x07, 0x06, 0xc7, 0x15, 0x0c, 0xbe, 0x22, 0xd6, 0x88, 0x5c, 0x40,
+	0xf8, 0x1c, 0x9b, 0xc3, 0x21, 0x97, 0x1f, 0xe1, 0xe7, 0x30, 0xee, 0x8f,
+	0x47, 0x98, 0x07, 0x6d, 0x1d, 0x0e, 0xb5, 0xb5, 0x37, 0xe3, 0x35, 0x5b,
+	0xad, 0x87, 0xb9, 0xef, 0x92, 0x1d, 0x11, 0x25, 0x37, 0xa4, 0x9e, 0xfb,
+	0x98, 0x63, 0xa7, 0xb3, 0x3c, 0xb7, 0xbf, 0x8f, 0xb7, 0xef, 0xa5, 0x8e,
+	0x0a, 0x1d, 0x8b, 0x03, 0x9f, 0x7b, 0xd8, 0x6e, 0xe4, 0x39, 0xec, 0xaf,
+	0xd0, 0xd5, 0xf8, 0x01, 0xb6, 0x4d, 0xf0, 0x2d, 0xa6, 0x11, 0xfe, 0xef,
+	0x24, 0x82, 0x01, 0xcc, 0xab, 0x8b, 0xef, 0x0d, 0x93, 0xd1, 0x9b, 0xe8,
+	0x6d, 0x57, 0xba, 0x29, 0xfc, 0x6e, 0xac, 0x9b, 0x1a, 0x33, 0xf1, 0x1d,
+	0xaa, 0xa6, 0x0c, 0xbe, 0x6a, 0xc4, 0xb1, 0x7e, 0x56, 0x91, 0xbd, 0x00,
+	0xa2, 0xea, 0xf8, 0xa7, 0x95, 0x44, 0x14, 0xc7, 0x26, 0xdd, 0x60, 0x7b,
+	0x39, 0x11, 0x18, 0xd9, 0x2b, 0x74, 0xf6, 0x80, 0x7d, 0x4c, 0xe6, 0x30,
+	0xd8, 0xa6, 0x15, 0xf0, 0xc3, 0x77, 0xa9, 0xeb, 0xd4, 0xf2, 0x4c, 0x81,
+	0xff, 0x15, 0xfa, 0x4f, 0xa6, 0x55, 0x93, 0x10, 0xb3, 0x98, 0x14, 0xb5,
+	0xce, 0xc8, 0x33, 0x3e, 0x3b, 0x0f, 0x9a, 0x85, 0xdf, 0xd0, 0x51, 0x7b,
+	0xfc, 0x29, 0xe4, 0x89, 0x15, 0x16, 0x69, 0x63, 0x59, 0x01, 0xbf, 0xd8,
+	0xc8, 0xc2, 0x5a, 0x6f, 0x58, 0xd4, 0x5e, 0xc3, 0xcf, 0xa9, 0xf3, 0x89,
+	0xf7, 0xf3, 0xf3, 0x43, 0xe2, 0xdb, 0x72, 0xd3, 0xd7, 0x30, 0xae, 0x95,
+	0x86, 0x17, 0x2a, 0x4f, 0xf1, 0x75, 0x11, 0x2f, 0xcc, 0x50, 0xbb, 0x8a,
+	0x05, 0x74, 0xa9, 0xf8, 0x51, 0x84, 0x69, 0xa8, 0x56, 0x53, 0x3c, 0x5c,
+	0xf5, 0x9d, 0x01, 0xb7, 0xbd, 0xbe, 0xb3, 0xaf, 0x6d, 0x22, 0x67, 0x36,
+	0xc3, 0x67, 0xe4, 0x82, 0xb6, 0x91, 0xf2, 0x09, 0x5a, 0xb3, 0xb4, 0xd5,
+	0xda, 0xb9, 0x6d, 0xdf, 0xd3, 0xde, 0x3a, 0xb5, 0x7a, 0xf1, 0xae, 0xd3,
+	0xa1, 0xf0, 0xa8, 0x95, 0xce, 0x16, 0x3b, 0x58, 0x56, 0xa3, 0xce, 0x09,
+	0xf0, 0x0a, 0x46, 0x51, 0x27, 0xf2, 0x5c, 0xa8, 0x95, 0x96, 0x97, 0x91,
+	0xd3, 0xf0, 0x67, 0x7b, 0x65, 0x7e, 0x6e, 0x9a, 0xe1, 0x72, 0x88, 0xe5,
+	0x9a, 0xa1, 0x62, 0x35, 0x38, 0x07, 0x9e, 0x20, 0x7a, 0x78, 0x86, 0x9e,
+	0x1e, 0xed, 0x60, 0x7d, 0x5e, 0xfa, 0xfa, 0x0f, 0xf3, 0xb3, 0xbf, 0x57,
+	0x4c, 0xc3, 0x4f, 0x65, 0x1e, 0xe5, 0xe7, 0x4f, 0xb3, 0x1e, 0x90, 0xa0,
+	0x56, 0x5a, 0x5a, 0x6e, 0x65, 0x7d, 0xbe, 0x95, 0xf5, 0x80, 0x11, 0x73,
+	0x38, 0x20, 0xde, 0x25, 0x6a, 0x52, 0x3e, 0x1b, 0x3a, 0x64, 0x1e, 0x13,
+	0x79, 0x36, 0x7f, 0xa5, 0xde, 0xe5, 0x7d, 0xc7, 0x07, 0x15, 0x1c, 0x1f,
+	0x0d, 0xae, 0x5e, 0xbc, 0xe3, 0x98, 0x8c, 0x7f, 0x93, 0xac, 0xf3, 0x86,
+	0xc5, 0xf7, 0x17, 0x8d, 0xa9, 0x29, 0xd6, 0xff, 0xf1, 0x8d, 0xb7, 0x67,
+	0x28, 0x5b, 0x3e, 0x45, 0x5f, 0x2f, 0xbb, 0x7d, 0xaf, 0xcf, 0xf0, 0x9c,
+	0x65, 0xed, 0x7c, 0x1b, 0xcf, 0xeb, 0x3d, 0xc7, 0xcb, 0x2b, 0x3a, 0x28,
+	0xf8, 0xad, 0x30, 0xb5, 0x7e, 0x03, 0x3e, 0x8f, 0x0a, 0x15, 0xe2, 0xf6,
+	0xd5, 0xfb, 0x24, 0xfd, 0xbc, 0x37, 0x44, 0x5e, 0x2a, 0xdf, 0xcf, 0xcf,
+	0x9c, 0xc3, 0xb8, 0x1b, 0x16, 0xdd, 0x76, 0x24, 0xbc, 0xff, 0x36, 0x14,
+	0xa6, 0xe0, 0x1b, 0xc8, 0xf5, 0x82, 0x8e, 0xb5, 0x7a, 0xd1, 0x39, 0xc0,
+	0x7c, 0xfa, 0x1b, 0xb8, 0x8f, 0xff, 0xbe, 0x81, 0xe3, 0x0e, 0x5e, 0x27,
+	0xe4, 0x2c, 0x72, 0x4a, 0xc0, 0xdf, 0x0e, 0x45, 0x4c, 0x81, 0x7f, 0xcf,
+	0x30, 0x4e, 0xb5, 0x08, 0x1f, 0x5f, 0x1f, 0xc6, 0x3a, 0x83, 0xac, 0x13,
+	0xac, 0x5e, 0x1c, 0x3d, 0x80, 0xe3, 0x44, 0x6f, 0x90, 0x61, 0x24, 0x71,
+	0xa8, 0xe1, 0x9b, 0x75, 0xa1, 0xc3, 0xa3, 0xe4, 0xfa, 0x6e, 0x1d, 0x7a,
+	0x26, 0x75, 0x50, 0x8a, 0xdf, 0x31, 0x5d, 0x94, 0xeb, 0x9e, 0x2b, 0x07,
+	0x49, 0xfa, 0x87, 0x52, 0x43, 0xfa, 0xfb, 0x84, 0xd4, 0x8f, 0x67, 0x6b,
+	0x5a, 0xc1, 0xef, 0x1e, 0x7a, 0x50, 0xec, 0xa2, 0x75, 0x15, 0x43, 0x7a,
+	0x20, 0xec, 0x29, 0xe6, 0xc5, 0xe9, 0x1e, 0xba, 0xbf, 0xdc, 0x42, 0xd4,
+	0xd7, 0x21, 0x62, 0xbc, 0x0f, 0x8a, 0x8b, 0x94, 0x7c, 0xed, 0xc9, 0x21,
+	0xe9, 0x4f, 0xa9, 0xe1, 0xc8, 0x03, 0x1f, 0x1c, 0x79, 0x57, 0xe0, 0xc8,
+	0xf0, 0xd0, 0xc6, 0x38, 0xb2, 0x47, 0xe7, 0x22, 0x52, 0xab, 0xc2, 0x8f,
+	0xd7, 0x19, 0x3f, 0x5e, 0x66, 0xfc, 0x38, 0xd2, 0x04, 0x3f, 0x0c, 0x0f,
+	0x7e, 0x1c, 0x15, 0xf8, 0xf1, 0xeb, 0x43, 0x1b, 0xe1, 0xc7, 0x91, 0xe0,
+	0x46, 0x3e, 0x1e, 0x8d, 0x9b, 0x03, 0xb4, 0x54, 0x74, 0x68, 0x79, 0xde,
+	0x8e, 0x27, 0x68, 0x35, 0x22, 0x63, 0x83, 0x53, 0xa2, 0x4e, 0x65, 0x51,
+	0xe0, 0x55, 0x5a, 0xf8, 0x2f, 0xfd, 0xbf, 0x1b, 0x68, 0x29, 0xf8, 0xcb,
+	0x3d, 0x99, 0xce, 0xaf, 0x5e, 0xfc, 0x3b, 0xde, 0xc7, 0xdb, 0x2b, 0xa1,
+	0x10, 0xae, 0x05, 0xa7, 0xc2, 0xb4, 0xb6, 0x82, 0xef, 0x12, 0x46, 0xe8,
+	0x4e, 0x31, 0x4a, 0xb7, 0x8b, 0x03, 0xb4, 0x56, 0x1c, 0xa2, 0xbb, 0x45,
+	0xbc, 0x03, 0x30, 0xe7, 0x63, 0x01, 0x73, 0x83, 0x0e, 0x87, 0x79, 0xcc,
+	0xf2, 0x00, 0xad, 0x2e, 0x6b, 0x7c, 0x05, 0xae, 0x62, 0xff, 0xe1, 0x27,
+	0xf0, 0xc7, 0x81, 0xe9, 0x3a, 0x1c, 0x90, 0xf7, 0x60, 0xef, 0x67, 0x1b,
+	0x6b, 0x64, 0x45, 0x9e, 0xa5, 0xc9, 0x38, 0xd2, 0x32, 0x65, 0x0b, 0x5f,
+	0xea, 0xe1, 0x20, 0x74, 0xd9, 0xc4, 0x3e, 0xea, 0xe1, 0x3d, 0x70, 0x90,
+	0x27, 0x34, 0xc4, 0x7a, 0xe9, 0x0e, 0xa1, 0x87, 0x26, 0x9d, 0x50, 0x64,
+	0x9a, 0x2a, 0x97, 0x0c, 0x07, 0x3d, 0x0f, 0xd3, 0xfc, 0x3c, 0x43, 0xf9,
+	0x71, 0xba, 0x5d, 0xf8, 0xe4, 0xd5, 0x39, 0x11, 0x8b, 0x7d, 0x96, 0xe7,
+	0x0c, 0xf9, 0x58, 0x8b, 0x73, 0x50, 0x35, 0xce, 0xd1, 0xce, 0xeb, 0x96,
+	0xb4, 0x34, 0xe3, 0xf0, 0xb8, 0x32, 0x8f, 0x2b, 0x23, 0x76, 0xc6, 0xe7,
+	0x97, 0x11, 0xb7, 0x8d, 0xd2, 0xda, 0x3c, 0x68, 0x0e, 0x7e, 0x89, 0x5a,
+	0xac, 0x74, 0x6d, 0x05, 0xe7, 0xe1, 0x9b, 0xa8, 0xc5, 0x4a, 0xd7, 0x54,
+	0xac, 0x74, 0x6d, 0x65, 0x4a, 0xf0, 0xe1, 0xd9, 0xff, 0xdd, 0x14, 0x60,
+	0x19, 0x30, 0x85, 0x19, 0xba, 0x4e, 0x53, 0x0d, 0x7a, 0xbf, 0x4e, 0x0c,
+	0x78, 0x6c, 0x58, 0x50, 0x05, 0x7f, 0x18, 0xba, 0x62, 0x84, 0xa1, 0x0d,
+	0xb8, 0xfd, 0xe3, 0x02, 0x34, 0xd3, 0x79, 0x4a, 0x0c, 0x30, 0x3c, 0x23,
+	0x80, 0x79, 0x49, 0x18, 0x9a, 0x97, 0x60, 0x73, 0xaf, 0xfc, 0x0c, 0x90,
+	0xbb, 0x7a, 0x6c, 0xc0, 0x6d, 0x7c, 0x48, 0xf9, 0x23, 0x83, 0x56, 0xfe,
+	0x30, 0xb0, 0x38, 0xa9, 0x43, 0xf4, 0x37, 0xad, 0x7f, 0x2c, 0x07, 0x1b,
+	0x5f, 0x6b, 0x02, 0x9a, 0xdb, 0x3c, 0x85, 0x94, 0xb9, 0x5b, 0x60, 0xbd,
+	0x89, 0x75, 0x5d, 0x26, 0xb1, 0x76, 0xc3, 0xd2, 0x42, 0x0c, 0x19, 0xe9,
+	0x09, 0x62, 0x06, 0x22, 0x3d, 0xd9, 0x00, 0xcb, 0x4e, 0x16, 0x60, 0x5e,
+	0x11, 0x02, 0xd6, 0x0f, 0x0c, 0xd0, 0x3a, 0xe6, 0x00, 0x78, 0x2c, 0xa1,
+	0x89, 0x01, 0x74, 0x07, 0x27, 0xd0, 0xfe, 0x7e, 0x65, 0xf0, 0xba, 0xe3,
+	0x06, 0x09, 0x88, 0xa1, 0x8b, 0x7a, 0x14, 0xe5, 0x41, 0x79, 0xd4, 0x49,
+	0x85, 0x81, 0xc4, 0xfc, 0x04, 0xf2, 0x1f, 0xd0, 0x1f, 0x20, 0x3f, 0x02,
+	0xf3, 0x93, 0x33, 0x50, 0x0e, 0xb4, 0x36, 0xaa, 0x79, 0x0d, 0x48, 0x1f,
+	0x28, 0x0c, 0x41, 0x65, 0x2a, 0x68, 0x8c, 0x03, 0xc8, 0x5e, 0x22, 0x04,
+	0x0d, 0x3b, 0x20, 0x0d, 0x64, 0x37, 0x4f, 0x11, 0x01, 0xf3, 0x93, 0x02,
+	0x84, 0x18, 0x1a, 0xe0, 0xf9, 0x89, 0x1d, 0xe8, 0x52, 0x98, 0x9b, 0xfe,
+	0xff, 0x3f, 0xa6, 0xc2, 0x02, 0x4c, 0x7b, 0xa0, 0xb5, 0xb5, 0xbf, 0xff,
+	0x1f, 0x10, 0x61, 0x61, 0x68, 0x81, 0xaf, 0xd1, 0x0b, 0x94, 0x07, 0x95,
+	0x73, 0x0b, 0x80, 0xac, 0x36, 0x78, 0xbd, 0x0d, 0x92, 0x07, 0x89, 0xfd,
+	0x02, 0x96, 0x2b, 0xff, 0xff, 0x2f, 0x85, 0xab, 0x05, 0x01, 0x00, 0xb3,
+	0x28, 0x79, 0xae, 0x58, 0x7d, 0x00, 0x00, 0x00 };
 
-static u32 bnx2_COM_b06FwData[(0x0/4) + 1] = { 0x0 };
-static u32 bnx2_COM_b06FwRodata[(0x58/4) + 1] = {
-	0x08002428, 0x0800245c, 0x0800245c, 0x0800245c, 0x0800245c, 0x0800245c,
-	0x08002380, 0x0800245c, 0x080023e4, 0x0800245c, 0x0800231c, 0x0800245c,
-	0x0800245c, 0x0800245c, 0x08002328, 0x00000000, 0x08003240, 0x08003270,
-	0x080032a0, 0x080032d0, 0x08003300, 0x00000000, 0x00000000 };
-static u32 bnx2_COM_b06FwBss[(0x88/4) + 1] = { 0x0 };
-static u32 bnx2_COM_b06FwSbss[(0x1c/4) + 1] = { 0x0 };
+static const u32 bnx2_COM_b06FwData[(0x0/4) + 1] = { 0x0 };
+static const u32 bnx2_COM_b06FwRodata[(0x88/4) + 1] = {
+	0x08001c1c, 0x08001c4c, 0x08001c4c, 0x08001c4c, 0x08001c4c, 0x08001c4c,
+	0x08001b74, 0x08001c4c, 0x08001bdc, 0x08001c4c, 0x08001b08, 0x08001c4c,
+	0x08001c4c, 0x08001c4c, 0x08001b14, 0x00000000, 0x08002b58, 0x08002ba8,
+	0x08002bd8, 0x08002c08, 0x08002c38, 0x00000000, 0x080060cc, 0x080060cc,
+	0x080060cc, 0x080060cc, 0x080060cc, 0x08006100, 0x08006100, 0x08006140,
+	0x0800614c, 0x0800614c, 0x080060cc, 0x00000000, 0x00000000 };
+static const u32 bnx2_COM_b06FwBss[(0x88/4) + 1] = { 0x0 };
+static const u32 bnx2_COM_b06FwSbss[(0x60/4) + 1] = { 0x0 };
 
 static struct fw_info bnx2_com_fw_06 = {
-	.ver_major			= 0x1,
-	.ver_minor			= 0x0,
-	.ver_fix			= 0x0,
+	.ver_major			= 0x3,
+	.ver_minor			= 0x4,
+	.ver_fix			= 0x3,
 
-	.start_addr			= 0x080008b4,
+	.start_addr			= 0x080000b4,
 
 	.text_addr			= 0x08000000,
-	.text_len			= 0x57bc,
+	.text_len			= 0x7d54,
 	.text_index			= 0x0,
 	.gz_text			= bnx2_COM_b06FwText,
 	.gz_text_len			= sizeof(bnx2_COM_b06FwText),
 
-	.data_addr			= 0x08005840,
+	.data_addr			= 0x08007e00,
 	.data_len			= 0x0,
 	.data_index			= 0x0,
 	.data				= bnx2_COM_b06FwData,
 
-	.sbss_addr			= 0x08005840,
-	.sbss_len			= 0x1c,
+	.sbss_addr			= 0x08007e00,
+	.sbss_len			= 0x60,
 	.sbss_index			= 0x0,
 	.sbss				= bnx2_COM_b06FwSbss,
 
-	.bss_addr			= 0x08005860,
+	.bss_addr			= 0x08007e60,
 	.bss_len			= 0x88,
 	.bss_index			= 0x0,
 	.bss				= bnx2_COM_b06FwBss,
 
-	.rodata_addr			= 0x080057c0,
-	.rodata_len			= 0x58,
+	.rodata_addr			= 0x08007d58,
+	.rodata_len			= 0x88,
 	.rodata_index			= 0x0,
 	.rodata				= bnx2_COM_b06FwRodata,
 };
diff --git a/drivers/net/bnx2_fw2.h b/drivers/net/bnx2_fw2.h
index 680c769..2c06753 100644
--- a/drivers/net/bnx2_fw2.h
+++ b/drivers/net/bnx2_fw2.h
@@ -1,13 +1,13 @@
 /* bnx2_fw2.h: Broadcom NX2 network driver.
  *
- * Copyright (c) 2006 Broadcom Corporation
+ * Copyright (c) 2004, 2005, 2006, 2007 Broadcom 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, except as noted below.
  *
  * This file contains firmware data derived from proprietary unpublished
- * source code, Copyright (c) 2006 Broadcom Corporation.
+ * source code, Copyright (c) 2004, 2005, 2006, 2007 Broadcom Corporation.
  *
  * Permission is hereby granted for the distribution of this firmware data
  * in hexadecimal or equivalent format, provided this copyright notice is
@@ -15,3289 +15,3260 @@
  */
 
 static u8 bnx2_COM_b09FwText[] = {
-	0x1f, 0x8b, 0x08, 0x08, 0xac, 0xfb, 0x2f, 0x45, 0x00, 0x03, 0x74, 0x65,
-	0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, 0xdc, 0x5b, 0x6b, 0x70,
-	0x1b, 0xd7, 0x75, 0x3e, 0xfb, 0x00, 0x09, 0x91, 0x10, 0xb5, 0xa4, 0x60,
-	0x1a, 0x96, 0x68, 0x07, 0x20, 0x57, 0x22, 0x6a, 0xb1, 0x29, 0x4c, 0x33,
-	0x16, 0x9b, 0xc2, 0x12, 0x02, 0x50, 0xae, 0x26, 0xc3, 0x3a, 0x94, 0xcd,
-	0xd8, 0x4a, 0xaa, 0xc9, 0x30, 0x00, 0xa5, 0xf4, 0x61, 0xb7, 0x92, 0xab,
-	0xa9, 0x5d, 0xd7, 0xaa, 0x21, 0x92, 0x6a, 0xf5, 0x83, 0xe5, 0x2a, 0x16,
-	0x43, 0xa9, 0xd3, 0x74, 0xc2, 0x12, 0x56, 0xac, 0x4e, 0x31, 0x85, 0xfc,
-	0xd6, 0x38, 0xb1, 0xc9, 0x4a, 0x76, 0xeb, 0xf4, 0xe1, 0xa6, 0x33, 0xcd,
-	0xa3, 0x9d, 0x36, 0xf6, 0xa8, 0x3f, 0xea, 0xe9, 0xd3, 0x33, 0x6e, 0xa7,
-	0xea, 0xd8, 0x0e, 0xfa, 0x7d, 0x77, 0x77, 0x81, 0x25, 0x48, 0xbd, 0xfc,
-	0xc8, 0x8f, 0x70, 0x06, 0xb3, 0x7b, 0xef, 0xde, 0xbd, 0xf7, 0xdc, 0xf3,
-	0xf8, 0xce, 0x63, 0x2f, 0xfb, 0x44, 0x5a, 0xc4, 0xfb, 0x5b, 0x8b, 0x5f,
-	0xfc, 0xfe, 0x5f, 0x2d, 0x7c, 0x7c, 0xf0, 0xe3, 0xfd, 0x22, 0xb7, 0xdc,
-	0xa2, 0xb7, 0x86, 0x75, 0xf6, 0x1b, 0xf8, 0x45, 0xf1, 0xeb, 0xf7, 0xee,
-	0x57, 0xfb, 0xb3, 0xf0, 0x7b, 0x13, 0x0f, 0xc7, 0xfe, 0x55, 0x44, 0xbb,
-	0xc4, 0x98, 0xe0, 0x5f, 0xb5, 0x7a, 0xf9, 0xe7, 0x5c, 0x38, 0x7e, 0x89,
-	0x67, 0x86, 0xbb, 0x9c, 0xa2, 0x97, 0x3f, 0x09, 0xeb, 0x69, 0x39, 0x94,
-	0xb5, 0x25, 0x6c, 0xa4, 0xdf, 0x3c, 0x54, 0xb0, 0x45, 0x32, 0xe5, 0x2d,
-	0xf1, 0x9c, 0xbc, 0x57, 0x2d, 0x46, 0x4d, 0x61, 0xff, 0x8d, 0xe9, 0x77,
-	0xbf, 0xf6, 0xe2, 0xd6, 0xc4, 0x5b, 0xf3, 0x86, 0x84, 0xad, 0xf4, 0x19,
-	0xb1, 0x36, 0x4b, 0xb8, 0x0b, 0xef, 0x7c, 0xb5, 0xf7, 0x3d, 0x91, 0x36,
-	0x7f, 0xae, 0x37, 0xab, 0x2f, 0xf6, 0x4a, 0x71, 0x43, 0x3a, 0x2c, 0x7a,
-	0x7a, 0xd3, 0xf7, 0xb3, 0x86, 0x35, 0x66, 0xa4, 0x2d, 0x59, 0xac, 0xc8,
-	0xc8, 0xde, 0x69, 0x09, 0x87, 0xd3, 0x47, 0x9b, 0x9b, 0x37, 0x49, 0xd8,
-	0x4c, 0x8f, 0x1d, 0xfa, 0x6d, 0xfb, 0xd1, 0xaa, 0x6e, 0xdb, 0xc9, 0x05,
-	0x89, 0x0c, 0x9e, 0x1a, 0xc0, 0xf3, 0x72, 0x22, 0x29, 0xb2, 0x55, 0x74,
-	0xbb, 0x18, 0x31, 0xec, 0xb0, 0x64, 0x2b, 0xb6, 0xe4, 0x2a, 0x22, 0x7f,
-	0x5e, 0xd6, 0xe4, 0x94, 0xdd, 0x29, 0x0b, 0x7d, 0xef, 0x56, 0x33, 0xa0,
-	0xe5, 0xcf, 0xec, 0xb1, 0x43, 0x53, 0x36, 0xe9, 0x9d, 0x6d, 0x76, 0xe9,
-	0x9d, 0x6a, 0x2a, 0xd8, 0xa6, 0x4c, 0x94, 0xd9, 0x37, 0xa2, 0xb3, 0x2f,
-	0x94, 0x7e, 0x68, 0xcd, 0x29, 0x3b, 0xe2, 0xf5, 0xed, 0xdc, 0x9e, 0xc5,
-	0x7c, 0x93, 0x65, 0x8e, 0x3d, 0x93, 0x2a, 0xd8, 0x51, 0xaf, 0x3f, 0x79,
-	0x5b, 0xd6, 0x8e, 0xa1, 0xbf, 0xcb, 0x7b, 0x76, 0xf2, 0xbe, 0x82, 0x6d,
-	0x7b, 0xcf, 0xbe, 0x8a, 0xb9, 0x93, 0x5e, 0xff, 0x7d, 0xdb, 0x0a, 0x76,
-	0x9f, 0xd7, 0x3f, 0xbd, 0x2d, 0x6b, 0xa7, 0xbc, 0xfe, 0xe4, 0xee, 0x82,
-	0x3d, 0xe0, 0xf5, 0x9f, 0xbd, 0x3d, 0x6b, 0x0f, 0x7a, 0xfd, 0x0f, 0x6d,
-	0x2d, 0xd8, 0x69, 0xf4, 0x1f, 0x6d, 0xd6, 0x37, 0x59, 0x72, 0xa4, 0x1c,
-	0xc7, 0x2f, 0x83, 0x67, 0x43, 0xe8, 0xdb, 0x89, 0xdf, 0x30, 0x7e, 0xbf,
-	0xb8, 0x4e, 0xda, 0x46, 0x70, 0xfd, 0xc6, 0x46, 0x97, 0x77, 0xe0, 0x91,
-	0x13, 0x96, 0x37, 0x8c, 0x98, 0xbc, 0xd8, 0xfb, 0x06, 0x78, 0x68, 0xc9,
-	0x99, 0x8a, 0x68, 0x23, 0xbd, 0x31, 0xf0, 0x2e, 0x2a, 0x4f, 0x56, 0x5a,
-	0xc5, 0x78, 0xcc, 0x00, 0x6f, 0x3e, 0x2f, 0xf9, 0x68, 0x58, 0xda, 0xe7,
-	0x34, 0xe9, 0xee, 0x0f, 0x4b, 0xc6, 0x52, 0x72, 0x13, 0x7d, 0x26, 0x2a,
-	0xc6, 0x5c, 0x66, 0xbd, 0x2e, 0x9b, 0xac, 0x9c, 0x14, 0xc1, 0xbb, 0xef,
-	0x51, 0x27, 0xf1, 0x2c, 0x2e, 0xb9, 0xe9, 0x9b, 0x65, 0xcc, 0x22, 0x5d,
-	0x3b, 0x6f, 0x74, 0xd7, 0x0a, 0x6b, 0xd9, 0x13, 0x23, 0x72, 0xc4, 0x89,
-	0x68, 0xb9, 0x13, 0xdb, 0x24, 0x9b, 0x92, 0x28, 0xde, 0x8b, 0xe5, 0xf1,
-	0xa4, 0x54, 0x1e, 0x91, 0x29, 0x47, 0xb4, 0xac, 0x43, 0x7e, 0x76, 0xe2,
-	0x79, 0x9b, 0x1a, 0x8b, 0xbe, 0x2e, 0x43, 0xcd, 0x1d, 0x46, 0xbf, 0x85,
-	0xfe, 0x0e, 0x6d, 0x48, 0xcd, 0xa1, 0xfa, 0xe3, 0x93, 0x12, 0x91, 0xc7,
-	0xcb, 0x51, 0x6f, 0x6c, 0xb5, 0x9a, 0x4d, 0x59, 0x18, 0x37, 0x22, 0x93,
-	0x4e, 0x54, 0xc6, 0x70, 0x9d, 0x70, 0xb8, 0x7e, 0x0c, 0x3a, 0xf5, 0xda,
-	0xa1, 0xfc, 0xac, 0x9a, 0x2f, 0x6e, 0xa4, 0x39, 0x5f, 0x17, 0xc6, 0x4d,
-	0x80, 0x2e, 0x4d, 0x4c, 0x25, 0xcb, 0x8c, 0xe4, 0xa7, 0x35, 0xe8, 0x1b,
-	0xae, 0x8a, 0xaf, 0x43, 0xa0, 0xdf, 0x14, 0xbb, 0x5f, 0x93, 0x02, 0x64,
-	0x55, 0xb4, 0xd0, 0x2e, 0x9f, 0xd5, 0xb3, 0x4e, 0xb3, 0xe4, 0xcc, 0xb8,
-	0x18, 0x33, 0x4a, 0x97, 0x64, 0x12, 0xef, 0xe8, 0x36, 0xc7, 0x5c, 0xc4,
-	0xbe, 0xc7, 0x94, 0x1c, 0x9a, 0xd2, 0x45, 0x3d, 0x57, 0xe9, 0x14, 0x7d,
-	0x6e, 0x8f, 0xbc, 0x3c, 0x2d, 0x96, 0x91, 0x7e, 0xb7, 0x9a, 0xb5, 0xa7,
-	0xf4, 0xec, 0x13, 0xa6, 0x84, 0x66, 0x34, 0x99, 0xb2, 0x13, 0xb0, 0x80,
-	0xa3, 0xfa, 0x8e, 0xca, 0x59, 0x8c, 0xe3, 0x7b, 0x18, 0x57, 0xd6, 0xc1,
-	0x57, 0xde, 0x6f, 0xb1, 0x74, 0xa5, 0xcf, 0x1c, 0x03, 0x19, 0x60, 0x1f,
-	0x4f, 0x3a, 0x90, 0x89, 0x92, 0x51, 0x1c, 0x32, 0x7a, 0x15, 0x32, 0x1a,
-	0x80, 0x6c, 0x52, 0xf2, 0x52, 0xa5, 0x4f, 0x9e, 0xaf, 0x24, 0xe5, 0x39,
-	0xe8, 0xeb, 0xb3, 0x95, 0xb8, 0x3c, 0x53, 0xe9, 0x92, 0xa7, 0x2b, 0x31,
-	0x79, 0x4a, 0xc9, 0x2d, 0x07, 0xdb, 0x50, 0xb2, 0x0c, 0x5f, 0x9f, 0x96,
-	0x70, 0x27, 0xe4, 0xd1, 0x01, 0xfd, 0x69, 0x87, 0x6e, 0x7e, 0xa5, 0x37,
-	0x2c, 0xb3, 0xbd, 0x92, 0x59, 0x8f, 0xfe, 0x9b, 0xd2, 0xa6, 0xe2, 0x91,
-	0x89, 0xe7, 0x93, 0xd3, 0x21, 0xc9, 0x59, 0x8f, 0xcb, 0x85, 0x19, 0x53,
-	0x26, 0x2b, 0xdb, 0x6f, 0x72, 0x65, 0xc6, 0xf6, 0xbc, 0x9c, 0x9f, 0x69,
-	0xc2, 0xb3, 0x79, 0x79, 0x79, 0xb3, 0x2e, 0x13, 0xb3, 0x6f, 0x89, 0x09,
-	0x1e, 0x0e, 0x29, 0x79, 0x3f, 0x2e, 0xff, 0xfc, 0x27, 0x22, 0x23, 0xe0,
-	0x8b, 0xde, 0xff, 0xef, 0xd5, 0x8c, 0x05, 0x7e, 0xf4, 0xf7, 0x41, 0x3f,
-	0x74, 0x5c, 0x29, 0xcf, 0x38, 0xc6, 0x98, 0x5a, 0xce, 0x39, 0x0d, 0x9b,
-	0x6a, 0xd5, 0xb2, 0xc7, 0x45, 0x0a, 0xc7, 0xab, 0x52, 0x48, 0x85, 0xe4,
-	0x01, 0xab, 0x2a, 0x43, 0xa9, 0x26, 0x39, 0x60, 0x75, 0xca, 0x44, 0xdf,
-	0xcf, 0x68, 0x3e, 0x96, 0x7d, 0xa5, 0x92, 0xc6, 0x3d, 0xfb, 0x44, 0x66,
-	0xd5, 0xbd, 0xdb, 0x5f, 0xac, 0x84, 0x24, 0x13, 0x2d, 0xc6, 0x4c, 0xb9,
-	0xa0, 0xb9, 0xb4, 0xed, 0xf4, 0x9f, 0x41, 0x5e, 0x63, 0xc0, 0x90, 0x84,
-	0xd2, 0xa5, 0xfc, 0xf4, 0x9a, 0x8b, 0x19, 0xd5, 0x1d, 0x52, 0x7a, 0x6a,
-	0xa4, 0x4d, 0xd2, 0x31, 0xa6, 0xa5, 0xa3, 0xd2, 0xad, 0xec, 0x64, 0x00,
-	0x63, 0x06, 0xb5, 0xbb, 0x2b, 0x94, 0x37, 0xee, 0xcb, 0xa4, 0x75, 0x03,
-	0xc6, 0x9a, 0xb8, 0x66, 0x3c, 0x9a, 0x83, 0x74, 0x72, 0x2e, 0xd2, 0xc9,
-	0xeb, 0xde, 0x00, 0x9d, 0xfb, 0x6a, 0xf7, 0xb3, 0x81, 0xfb, 0x62, 0xe5,
-	0xd7, 0x5b, 0x5c, 0xfa, 0xc8, 0xd7, 0x41, 0x99, 0x98, 0x7e, 0xc8, 0x5b,
-	0x0b, 0xf7, 0x65, 0xae, 0xb1, 0x00, 0x3e, 0xa9, 0x91, 0x57, 0x58, 0xab,
-	0x18, 0x58, 0xeb, 0x70, 0x60, 0xad, 0xc3, 0x81, 0xb5, 0x8a, 0xe0, 0xad,
-	0xac, 0xd3, 0x81, 0x33, 0x79, 0xc2, 0xbc, 0x1c, 0xc5, 0x9c, 0x6f, 0x88,
-	0x91, 0xa6, 0x2d, 0xf8, 0x36, 0xf9, 0x07, 0x18, 0x9f, 0x96, 0x73, 0x0e,
-	0x78, 0x73, 0x3c, 0x24, 0x77, 0xa9, 0x71, 0xff, 0xb1, 0xc6, 0xa5, 0x31,
-	0xf8, 0x2c, 0x2c, 0xbb, 0xa2, 0xbc, 0xf7, 0x9f, 0x99, 0xe0, 0x37, 0xdb,
-	0x93, 0x37, 0xb8, 0x6d, 0xde, 0x9f, 0xf5, 0xf6, 0xd2, 0xee, 0xbe, 0x57,
-	0x79, 0x53, 0x61, 0xc6, 0x62, 0x85, 0xb6, 0x2d, 0x29, 0xc3, 0x96, 0xfd,
-	0x43, 0xa9, 0x4e, 0x99, 0xb4, 0xb4, 0xd4, 0x44, 0xb2, 0x99, 0xfc, 0xcf,
-	0xe8, 0x76, 0x2b, 0xec, 0x47, 0xe2, 0x3a, 0x71, 0x51, 0xed, 0xeb, 0x5b,
-	0x1e, 0xfd, 0x16, 0xdb, 0x23, 0xba, 0xdd, 0xd1, 0xd0, 0x4f, 0xfd, 0xff,
-	0x4b, 0xdc, 0xd3, 0x06, 0xfa, 0x75, 0x77, 0xed, 0xbf, 0x42, 0x9b, 0x58,
-	0x15, 0xf1, 0xda, 0xfe, 0xf3, 0xff, 0x32, 0x96, 0xb7, 0x8f, 0x6d, 0x5c,
-	0xde, 0xf6, 0x6d, 0x29, 0x88, 0x73, 0xdc, 0x2b, 0x6c, 0xd8, 0xa6, 0xfe,
-	0x85, 0x40, 0x6b, 0x0a, 0x36, 0xdc, 0xec, 0xd1, 0xf0, 0xba, 0x47, 0x03,
-	0x68, 0xc5, 0xb8, 0x89, 0x0a, 0xdf, 0x51, 0xa2, 0x6c, 0x68, 0x93, 0xf7,
-	0xfe, 0xfd, 0x5a, 0xf5, 0xfc, 0x0d, 0x83, 0xeb, 0xf8, 0x57, 0xd1, 0x86,
-	0x60, 0x67, 0x93, 0xb3, 0xa6, 0xe4, 0x53, 0x31, 0x65, 0x0f, 0xf9, 0x54,
-	0x1d, 0x3f, 0x26, 0xa7, 0x1b, 0xf1, 0x83, 0xef, 0x11, 0x3f, 0x5c, 0xec,
-	0x98, 0x98, 0x25, 0x8e, 0xd4, 0x71, 0xe3, 0xc8, 0xb4, 0x8f, 0x25, 0x9c,
-	0x9b, 0x18, 0xe2, 0xe3, 0x07, 0xdf, 0x23, 0x7e, 0x18, 0x90, 0x15, 0xe7,
-	0xf4, 0xd7, 0x9f, 0x6a, 0x98, 0x7b, 0x4a, 0x61, 0x93, 0x8b, 0xcb, 0x6f,
-	0x06, 0x70, 0xbe, 0x0b, 0x18, 0x1d, 0x85, 0xfc, 0x7c, 0x8c, 0x26, 0x76,
-	0xc6, 0x80, 0xeb, 0xe0, 0x91, 0xc2, 0xe4, 0x08, 0x70, 0xcc, 0xf4, 0x30,
-	0x35, 0xec, 0x61, 0x6a, 0x04, 0x78, 0xca, 0xb6, 0xe5, 0xb5, 0xa3, 0x5e,
-	0x3b, 0x86, 0x36, 0xfc, 0xef, 0x1c, 0x6d, 0xec, 0xb5, 0x43, 0xe3, 0xb3,
-	0x0a, 0xa7, 0x89, 0xf1, 0xc0, 0x0a, 0xe2, 0x2c, 0xf1, 0xb6, 0x4b, 0x16,
-	0xca, 0x58, 0xaf, 0x86, 0x69, 0x94, 0x47, 0x90, 0x1e, 0xd2, 0xb2, 0x46,
-	0xf4, 0xc7, 0xdc, 0xfd, 0xe8, 0xe9, 0xcf, 0xeb, 0xd2, 0xc2, 0x7d, 0x90,
-	0xee, 0x1b, 0x41, 0x2b, 0xf7, 0xf6, 0xa3, 0xa4, 0x95, 0xeb, 0x35, 0xd2,
-	0x7b, 0x1a, 0xf4, 0x66, 0x80, 0xb7, 0xa2, 0x8d, 0xf6, 0x8e, 0x82, 0xde,
-	0x11, 0x60, 0xf1, 0x30, 0xb0, 0x78, 0x27, 0xb0, 0x78, 0x08, 0x58, 0x9c,
-	0x06, 0x0e, 0x0f, 0x02, 0x87, 0x07, 0x80, 0xc3, 0x29, 0xec, 0x2b, 0x2a,
-	0xf3, 0xc0, 0xe5, 0x79, 0xe0, 0xf3, 0x3c, 0xe4, 0x35, 0x31, 0x27, 0xda,
-	0x17, 0xb0, 0xfe, 0x63, 0x33, 0x89, 0xd3, 0xd0, 0xcd, 0x58, 0x51, 0x87,
-	0x3d, 0xa5, 0x06, 0xa1, 0x23, 0x49, 0x29, 0x55, 0x46, 0xa5, 0x40, 0x3f,
-	0xb6, 0xb9, 0x07, 0xb6, 0x0b, 0xfb, 0x89, 0xf9, 0x71, 0xd3, 0x5a, 0xef,
-	0xfa, 0xf7, 0x22, 0xf6, 0x1f, 0x83, 0x27, 0x89, 0xb8, 0xc8, 0xb0, 0xe4,
-	0x9d, 0x1e, 0x2b, 0xab, 0x27, 0x31, 0x8e, 0xed, 0xb8, 0xb6, 0xf7, 0x78,
-	0x42, 0x1b, 0x3f, 0xce, 0x3d, 0x4d, 0x03, 0xe3, 0xaa, 0x32, 0x95, 0xa2,
-	0xad, 0x56, 0xe5, 0x54, 0x2a, 0x31, 0x58, 0x94, 0x56, 0x39, 0x12, 0x9d,
-	0x56, 0xfe, 0xcd, 0x4c, 0x1f, 0x53, 0xfa, 0x51, 0xb0, 0x71, 0x2d, 0x77,
-	0x6b, 0xf9, 0xe3, 0xf4, 0x3b, 0x3d, 0xf8, 0x85, 0x40, 0x0b, 0xe7, 0x37,
-	0x65, 0x68, 0x40, 0xb4, 0x7d, 0xbd, 0x45, 0xa0, 0x62, 0xc2, 0x3a, 0x87,
-	0x95, 0x73, 0xd3, 0x3d, 0xb1, 0x9c, 0x6e, 0xca, 0x98, 0xa9, 0xc9, 0x04,
-	0xec, 0x65, 0x28, 0xf5, 0x7f, 0xd5, 0x23, 0x51, 0x3e, 0x6f, 0x96, 0xdf,
-	0x51, 0x38, 0x8b, 0xb5, 0x4b, 0xb3, 0x58, 0x37, 0x04, 0xfe, 0x71, 0x5d,
-	0xce, 0x83, 0x36, 0x30, 0xcf, 0xb4, 0x13, 0xa7, 0x8b, 0xb2, 0x1d, 0x76,
-	0xb7, 0x4e, 0xb2, 0x7d, 0x4d, 0x92, 0x19, 0x89, 0xcb, 0xc4, 0xcc, 0x76,
-	0xe0, 0x1e, 0x64, 0x60, 0xb7, 0x48, 0x7e, 0x34, 0x2e, 0x5f, 0x9e, 0x61,
-	0x5f, 0x06, 0xfb, 0x4f, 0x1c, 0xcd, 0x08, 0xf7, 0x1f, 0x52, 0xfb, 0x8a,
-	0xeb, 0x19, 0x39, 0xe0, 0xbc, 0xa4, 0xbb, 0x76, 0xe9, 0xb6, 0xf7, 0x42,
-	0x1e, 0xa7, 0xc0, 0xef, 0xbc, 0x63, 0xcb, 0x02, 0xfc, 0x4a, 0xee, 0x38,
-	0x70, 0xd5, 0x6e, 0x03, 0x06, 0x26, 0xce, 0xd2, 0x3e, 0x0c, 0xc4, 0x5a,
-	0x25, 0xc5, 0xeb, 0x2e, 0x39, 0x3e, 0xa3, 0xcb, 0xb3, 0xb7, 0xc5, 0xd1,
-	0x06, 0xd6, 0xa6, 0x12, 0x67, 0xc6, 0xf4, 0x2e, 0xb9, 0xb5, 0x23, 0x86,
-	0xf7, 0x52, 0x5a, 0xde, 0xf9, 0x37, 0xf2, 0xf2, 0x64, 0x5c, 0xe7, 0x58,
-	0x5d, 0x72, 0x29, 0x03, 0x3a, 0x56, 0xc4, 0xf8, 0x7f, 0x40, 0x7f, 0x97,
-	0xcc, 0x21, 0xbe, 0x99, 0x03, 0x4d, 0xd9, 0x14, 0xb1, 0x30, 0x71, 0x72,
-	0x49, 0x07, 0x66, 0xcd, 0x41, 0x37, 0x47, 0x11, 0x3f, 0xcc, 0xfc, 0x37,
-	0xc6, 0xc4, 0x21, 0xd3, 0x1e, 0x6b, 0x02, 0xf8, 0x92, 0xe9, 0xe2, 0x3d,
-	0xe7, 0xb4, 0xe5, 0x94, 0x43, 0x1d, 0x8a, 0xcb, 0xe3, 0x15, 0xbe, 0xd7,
-	0x73, 0xf6, 0x69, 0xb1, 0xe5, 0x41, 0xe7, 0x7f, 0x30, 0xfe, 0x1d, 0xc4,
-	0x9e, 0x96, 0x94, 0x20, 0xb7, 0x02, 0x78, 0x99, 0x89, 0xb9, 0xed, 0x89,
-	0xb9, 0xc4, 0xd9, 0x0b, 0x3a, 0xef, 0xed, 0xe2, 0x82, 0x7e, 0xb3, 0x48,
-	0x07, 0xf9, 0x99, 0x02, 0x2f, 0x6d, 0x4b, 0xd7, 0x37, 0x7b, 0xf1, 0x16,
-	0x6d, 0xc0, 0x06, 0x7d, 0xa6, 0x2c, 0xf4, 0x07, 0x6d, 0x80, 0x7e, 0xd6,
-	0xb7, 0x81, 0x44, 0x6c, 0x49, 0xd7, 0xf1, 0xdc, 0x94, 0x63, 0xaa, 0xad,
-	0x81, 0xd6, 0x44, 0x8c, 0xfb, 0x9b, 0x2c, 0x27, 0xe5, 0x71, 0x87, 0xe3,
-	0xc1, 0xe7, 0xe9, 0x88, 0x37, 0x1e, 0xf1, 0x8e, 0xc3, 0x98, 0x29, 0x09,
-	0x9a, 0x5d, 0xbb, 0x58, 0x98, 0x8e, 0xaa, 0x67, 0x47, 0x1c, 0x37, 0x36,
-	0xd2, 0x11, 0x3f, 0xcd, 0x23, 0x7e, 0xca, 0x29, 0x1b, 0xb1, 0x32, 0x88,
-	0xaf, 0xe1, 0x67, 0x5d, 0xfb, 0x28, 0x95, 0x49, 0xcb, 0x3d, 0xa0, 0x2f,
-	0x51, 0x04, 0x31, 0xc7, 0x74, 0xb8, 0xeb, 0xec, 0x80, 0x14, 0x19, 0x63,
-	0x9d, 0x33, 0x1e, 0x91, 0xb1, 0x12, 0xfd, 0x1b, 0x7e, 0x8e, 0x6d, 0x31,
-	0xa6, 0xcf, 0x28, 0xdf, 0xd3, 0x03, 0x3d, 0x80, 0x5f, 0x4a, 0xb5, 0x8b,
-	0xeb, 0x07, 0xf7, 0x40, 0x9e, 0xc3, 0x90, 0x7b, 0x5a, 0xc6, 0x4f, 0x8c,
-	0x53, 0xa7, 0x93, 0x25, 0x49, 0x24, 0x8f, 0xc8, 0x16, 0x6b, 0x01, 0xbe,
-	0x30, 0x33, 0x5a, 0xdd, 0xae, 0xa7, 0xf9, 0xce, 0xa3, 0x78, 0x07, 0xd7,
-	0xd2, 0xb8, 0x3c, 0x50, 0x61, 0xdf, 0x9d, 0x86, 0xb4, 0xc0, 0x56, 0x06,
-	0xf6, 0x78, 0x76, 0x80, 0xf9, 0x4c, 0x7f, 0xbe, 0x71, 0x6f, 0x3e, 0x8e,
-	0xe3, 0x18, 0xbe, 0x53, 0x9f, 0x77, 0x07, 0x7d, 0x1b, 0xb0, 0x64, 0x87,
-	0x5e, 0xdd, 0x1e, 0xc2, 0xf3, 0x53, 0x03, 0xbc, 0xc7, 0x3c, 0xf0, 0x6d,
-	0x96, 0x3d, 0x8c, 0xb1, 0xa3, 0x98, 0x73, 0x8d, 0x64, 0x3b, 0x7d, 0x7a,
-	0xa9, 0x03, 0x8c, 0x3f, 0xd8, 0x8e, 0xae, 0x77, 0x79, 0xff, 0x25, 0xc3,
-	0xd5, 0xc9, 0x11, 0xb4, 0x69, 0x7f, 0x07, 0x25, 0xe7, 0x24, 0xb0, 0x4f,
-	0xf0, 0xb6, 0x32, 0xe1, 0xed, 0x11, 0xfc, 0x1f, 0x39, 0x0c, 0x3e, 0x48,
-	0xd1, 0xe5, 0x0d, 0xf9, 0x42, 0x9e, 0xfc, 0x16, 0x74, 0xff, 0x61, 0x8c,
-	0x81, 0x7f, 0x50, 0x3c, 0x58, 0xea, 0x70, 0x63, 0xd1, 0x44, 0x31, 0xc3,
-	0xfc, 0xa9, 0x83, 0x98, 0x07, 0xfc, 0xa9, 0x40, 0xb1, 0x30, 0xf7, 0x92,
-	0xbe, 0x86, 0xf4, 0xc6, 0x97, 0x0c, 0x83, 0xed, 0xe4, 0x12, 0x74, 0xb8,
-	0x04, 0xf9, 0x64, 0xfb, 0x68, 0xb3, 0x36, 0xe4, 0x31, 0x63, 0x50, 0x5f,
-	0x4b, 0x88, 0x05, 0xf3, 0xce, 0x16, 0xeb, 0x5e, 0xf2, 0xcd, 0xb2, 0xe4,
-	0x69, 0x27, 0x88, 0x1d, 0x3b, 0x30, 0x94, 0x7a, 0x18, 0x85, 0x1e, 0x98,
-	0xf0, 0xc9, 0x31, 0xc8, 0xfc, 0xc5, 0x0e, 0x77, 0x2f, 0xbc, 0x37, 0x65,
-	0xde, 0xc2, 0x9a, 0xce, 0xef, 0xaf, 0x73, 0xfb, 0x78, 0xcf, 0xb8, 0xc8,
-	0x97, 0xab, 0x4f, 0x3b, 0xe5, 0xdb, 0x28, 0xd3, 0x43, 0xd8, 0x0b, 0xfb,
-	0x71, 0x2d, 0x1d, 0x94, 0x71, 0xd0, 0x56, 0x18, 0xd8, 0x14, 0x3b, 0x8f,
-	0xf1, 0x39, 0xe0, 0x79, 0xd1, 0xe4, 0xb3, 0x8b, 0x5a, 0xfd, 0x1d, 0xc4,
-	0x5c, 0x36, 0xfd, 0xd9, 0x92, 0xf6, 0x85, 0xca, 0xcb, 0x5a, 0xb6, 0x74,
-	0x51, 0xcb, 0x41, 0x4f, 0x4a, 0x0e, 0x73, 0x06, 0xda, 0x8f, 0x85, 0xb5,
-	0x13, 0xb1, 0xb7, 0xf5, 0x9e, 0xf8, 0x02, 0xb0, 0x60, 0x2f, 0x6c, 0x3a,
-	0x67, 0xee, 0x94, 0x02, 0xb0, 0x35, 0x7f, 0x62, 0x0b, 0xec, 0x2d, 0x1e,
-	0xa0, 0x8b, 0x78, 0x56, 0xa4, 0x4f, 0xd5, 0x76, 0x38, 0x52, 0x6c, 0x4a,
-	0x13, 0xd7, 0x36, 0x41, 0x77, 0xd0, 0x57, 0xae, 0xeb, 0xdf, 0x1d, 0x2b,
-	0x68, 0x45, 0x7e, 0x39, 0xb0, 0x9c, 0xde, 0x92, 0x5c, 0x99, 0xde, 0x1d,
-	0x35, 0x7a, 0x89, 0x19, 0xc0, 0x7f, 0xd8, 0xcd, 0x4b, 0xd0, 0xdf, 0xe7,
-	0x1d, 0xe0, 0xbf, 0x03, 0xfc, 0x87, 0x4d, 0x3d, 0x03, 0xdd, 0x7b, 0xda,
-	0x81, 0x0f, 0x70, 0xe0, 0x03, 0x1c, 0xf8, 0x00, 0x27, 0x0b, 0x39, 0x11,
-	0xe7, 0xe9, 0x43, 0x76, 0xd7, 0x7c, 0x9e, 0x1b, 0x37, 0xdd, 0xe0, 0xc5,
-	0x22, 0xa3, 0x88, 0x45, 0x36, 0xc8, 0x44, 0xf2, 0x7a, 0xec, 0xad, 0x05,
-	0xd7, 0x56, 0x5c, 0xb1, 0x46, 0xf2, 0x76, 0xcf, 0x4e, 0x1e, 0x06, 0x5d,
-	0x88, 0xbf, 0x93, 0x3f, 0x0d, 0x3d, 0x6c, 0x02, 0x3d, 0x3f, 0xe5, 0xc5,
-	0x2c, 0x0f, 0x9a, 0xae, 0x1e, 0xb6, 0xa2, 0xef, 0x93, 0xe8, 0x6b, 0xc5,
-	0x98, 0x03, 0x18, 0xc3, 0x98, 0xa7, 0xcd, 0xeb, 0x0b, 0x8e, 0x63, 0xec,
-	0xf3, 0x19, 0xac, 0x95, 0xc0, 0xb8, 0x36, 0xcc, 0xdd, 0x85, 0x31, 0xdb,
-	0x30, 0xe6, 0x46, 0xb4, 0x19, 0x33, 0x6f, 0x44, 0xfb, 0x13, 0x0d, 0xef,
-	0x7c, 0x0c, 0x7d, 0xb7, 0x37, 0xf4, 0x9d, 0x43, 0x1f, 0xf2, 0x50, 0xeb,
-	0xbc, 0xf7, 0x5e, 0x11, 0xed, 0xce, 0x86, 0x31, 0xaf, 0xa2, 0x0f, 0x71,
-	0xaf, 0xf5, 0x2d, 0x5c, 0x91, 0x7f, 0x5a, 0xa4, 0xc9, 0x7f, 0xc6, 0xb8,
-	0x37, 0x8e, 0xfe, 0x90, 0x17, 0xbb, 0xfe, 0xa6, 0x09, 0xbd, 0xd3, 0x86,
-	0x9c, 0xdf, 0x30, 0xdd, 0x58, 0xef, 0x4e, 0xcb, 0xd5, 0x43, 0xbf, 0xfd,
-	0x70, 0x43, 0x9b, 0x63, 0x17, 0x1a, 0xfa, 0xfe, 0xa5, 0xa1, 0xfd, 0xdd,
-	0xd0, 0xca, 0x77, 0x06, 0xdb, 0x97, 0xf7, 0x15, 0x3a, 0x96, 0xb7, 0xed,
-	0xa6, 0x95, 0xef, 0xe8, 0xeb, 0x96, 0xf7, 0xdd, 0xb8, 0xbe, 0x61, 0x0c,
-	0x74, 0x2a, 0x8a, 0x1c, 0xc9, 0x1f, 0x1f, 0xbe, 0xce, 0x7d, 0x4e, 0xfe,
-	0x36, 0xea, 0x92, 0xda, 0x3a, 0xda, 0x3a, 0xe4, 0xb0, 0xa4, 0xc1, 0x9e,
-	0x2c, 0x3d, 0xfd, 0xb2, 0x96, 0x83, 0x4e, 0x65, 0x2b, 0xfe, 0x7c, 0xb4,
-	0xd9, 0xc6, 0xdc, 0xdc, 0xcf, 0xc9, 0x19, 0x2b, 0x45, 0xa0, 0x37, 0xf7,
-	0xd0, 0x27, 0x1d, 0x2d, 0x4a, 0xdd, 0x3e, 0xbb, 0xf5, 0x4b, 0xd9, 0xe7,
-	0xed, 0x1e, 0x46, 0x1d, 0x06, 0x9d, 0x55, 0x19, 0x49, 0x35, 0xd3, 0xc7,
-	0x78, 0xd8, 0x45, 0xdc, 0xa9, 0x56, 0x8d, 0xcd, 0x55, 0xd9, 0x9f, 0x7a,
-	0xa7, 0x2a, 0x0a, 0xf3, 0x06, 0x15, 0xee, 0xc4, 0xf5, 0x1e, 0xc8, 0xc8,
-	0x42, 0x6e, 0x82, 0x7c, 0x3a, 0x4a, 0x9f, 0x74, 0x90, 0xf1, 0xc9, 0xa3,
-	0x2e, 0xa6, 0x12, 0x77, 0xd0, 0x46, 0x5e, 0x96, 0x3f, 0xce, 0xf5, 0x71,
-	0x2d, 0x11, 0xc7, 0x47, 0x95, 0x4f, 0xc9, 0x5b, 0x9c, 0x77, 0x35, 0x6c,
-	0x3c, 0x6b, 0x32, 0xa6, 0x33, 0xed, 0xd3, 0xf0, 0x6f, 0x7c, 0xc6, 0x58,
-	0xe1, 0x34, 0xe3, 0x92, 0x00, 0x56, 0x6d, 0x35, 0xe0, 0x32, 0x8b, 0xcb,
-	0xf7, 0xb5, 0x81, 0x79, 0xc4, 0x55, 0xec, 0x75, 0x75, 0x2c, 0xea, 0xd1,
-	0xaf, 0x6c, 0xdb, 0xbb, 0x6a, 0xb6, 0xed, 0xeb, 0xde, 0x6a, 0x39, 0xf8,
-	0xf7, 0x95, 0x2c, 0x9e, 0xaa, 0x24, 0x8e, 0x15, 0x61, 0x4b, 0x8b, 0x2a,
-	0xef, 0xf6, 0xe5, 0xc2, 0x18, 0x27, 0x71, 0x72, 0x1e, 0x6f, 0x8e, 0xab,
-	0x1c, 0x83, 0xf9, 0x45, 0x55, 0x76, 0xa4, 0x5a, 0xa3, 0xe4, 0x43, 0x46,
-	0xff, 0x76, 0x88, 0x31, 0xc3, 0xa2, 0x43, 0x9e, 0xa5, 0xf0, 0x3c, 0x05,
-	0x4c, 0xf8, 0x27, 0xc9, 0x45, 0xd9, 0xf7, 0x76, 0x75, 0x01, 0x71, 0x95,
-	0x8a, 0x8f, 0x94, 0xbf, 0x67, 0x7c, 0xb7, 0x1f, 0xfc, 0x22, 0x4f, 0x47,
-	0xc0, 0x67, 0x3f, 0x06, 0x78, 0x8d, 0x75, 0x15, 0x59, 0x1e, 0x07, 0x8b,
-	0x3c, 0x50, 0x7e, 0x19, 0x73, 0xea, 0x6e, 0xac, 0xc2, 0x3c, 0xdc, 0x66,
-	0x7f, 0x47, 0x88, 0xb1, 0x9c, 0xeb, 0xeb, 0x0d, 0xac, 0x87, 0xdc, 0xbe,
-	0xfc, 0x8f, 0x2a, 0x6e, 0x2a, 0x28, 0x79, 0x20, 0x86, 0xaa, 0xf0, 0x19,
-	0xfb, 0xc2, 0x5e, 0xec, 0x1c, 0xf1, 0x62, 0x65, 0xcb, 0x8b, 0x95, 0x49,
-	0x07, 0x6b, 0x6f, 0x7e, 0x5c, 0x40, 0x99, 0x2d, 0x1d, 0xd2, 0x37, 0x33,
-	0x2e, 0x68, 0x93, 0xd5, 0xe3, 0x02, 0x9f, 0xa6, 0x6d, 0xa0, 0x89, 0x71,
-	0x9e, 0xaa, 0xbd, 0x74, 0xb8, 0xf5, 0x1e, 0xd2, 0xe0, 0xfb, 0x47, 0xe5,
-	0x87, 0x8f, 0xc2, 0xe5, 0x61, 0x6f, 0x69, 0xd0, 0xba, 0x53, 0xb2, 0xd3,
-	0xdb, 0x3c, 0x7f, 0xcb, 0x1c, 0x80, 0xf1, 0xb7, 0xab, 0xb3, 0xd9, 0xd4,
-	0x84, 0x3f, 0x4f, 0x27, 0x3c, 0x64, 0xa0, 0x2e, 0xc4, 0xb5, 0x18, 0xc7,
-	0xf8, 0x31, 0xcd, 0x4e, 0x2f, 0xa6, 0x19, 0x96, 0xfd, 0x8e, 0x1b, 0xf3,
-	0x8f, 0xa0, 0x3f, 0xef, 0x28, 0xda, 0x63, 0x8c, 0x2d, 0x75, 0xc4, 0xdc,
-	0x99, 0x3d, 0x09, 0x24, 0x0f, 0xee, 0x5e, 0xba, 0xb1, 0x97, 0x52, 0x6d,
-	0x2f, 0xad, 0x4b, 0xcb, 0xf7, 0x32, 0xaa, 0xde, 0x9d, 0x5a, 0xf1, 0xae,
-	0x60, 0x1f, 0xbb, 0x2f, 0xf1, 0x8c, 0x7b, 0x64, 0xdc, 0x60, 0x79, 0x7b,
-	0xf4, 0xe5, 0x74, 0x00, 0x7b, 0x4c, 0x6a, 0x79, 0x15, 0x6b, 0xed, 0x51,
-	0x3c, 0xcf, 0x97, 0xc7, 0x70, 0xa5, 0x7d, 0xa8, 0x79, 0x94, 0x8d, 0x4c,
-	0x28, 0x3e, 0x8f, 0xab, 0x7d, 0x2c, 0x94, 0x7f, 0x41, 0x0a, 0x27, 0x7e,
-	0x09, 0x7e, 0x2f, 0x58, 0x0f, 0x63, 0x2d, 0x91, 0xfc, 0x28, 0x06, 0xf0,
-	0x93, 0x7b, 0x65, 0xad, 0xeb, 0x0f, 0x43, 0x6e, 0x7e, 0x10, 0x81, 0x8c,
-	0x35, 0xf7, 0xb9, 0x5a, 0xdf, 0xe7, 0x6b, 0x53, 0x80, 0x9e, 0x2a, 0x62,
-	0xce, 0x18, 0x68, 0x08, 0xbe, 0x73, 0x50, 0x86, 0x1c, 0xca, 0xa3, 0x27,
-	0x36, 0x2e, 0xb6, 0x95, 0x17, 0x3f, 0xce, 0xe0, 0xfa, 0xb4, 0xf9, 0x5c,
-	0xcc, 0x10, 0xd6, 0x2f, 0x7d, 0xde, 0xf9, 0x7c, 0x8b, 0x2c, 0x35, 0xea,
-	0xc0, 0x14, 0xe8, 0x29, 0x38, 0xe4, 0x93, 0xaf, 0x9b, 0xfe, 0xda, 0xaf,
-	0xaa, 0xfd, 0x4c, 0xaa, 0x9a, 0xdd, 0x73, 0x35, 0x1d, 0x9d, 0x40, 0x0c,
-	0xe2, 0xea, 0xdc, 0x7d, 0x1e, 0x6f, 0x7c, 0xdd, 0x8c, 0x78, 0x72, 0x66,
-	0x1e, 0x47, 0xdb, 0xf1, 0xf5, 0x60, 0x93, 0x75, 0xb7, 0xe2, 0x05, 0x9f,
-	0x11, 0x53, 0x5c, 0x59, 0x8e, 0xd5, 0x64, 0xb9, 0xb6, 0x41, 0x2f, 0xbf,
-	0xb7, 0xce, 0xb5, 0x43, 0xda, 0x1b, 0xec, 0x16, 0xf4, 0x3d, 0xb5, 0xcc,
-	0xbe, 0x93, 0x97, 0xa8, 0x83, 0x46, 0xc4, 0x98, 0xfb, 0x53, 0xf0, 0xf2,
-	0x63, 0xc8, 0x55, 0x44, 0xcc, 0x19, 0xe2, 0x10, 0xe3, 0x8d, 0x7a, 0xbc,
-	0xbb, 0x20, 0xab, 0xc5, 0xba, 0x57, 0x8a, 0x35, 0x7e, 0xf2, 0x2a, 0x63,
-	0x8d, 0x78, 0x93, 0xb4, 0x10, 0x8b, 0x86, 0x11, 0xdb, 0x6a, 0xd2, 0x64,
-	0x3f, 0x08, 0x1f, 0x76, 0xc6, 0x6c, 0xb6, 0x7d, 0x4c, 0x88, 0x48, 0xfb,
-	0xdc, 0x06, 0x85, 0x0b, 0xd6, 0x4c, 0x1d, 0x17, 0x26, 0xc0, 0xfb, 0x11,
-	0xb7, 0xb6, 0x1a, 0x6d, 0x97, 0xab, 0xcd, 0x8d, 0xeb, 0x71, 0xff, 0x58,
-	0x2d, 0xee, 0xbf, 0xa1, 0x81, 0x8f, 0xab, 0xe1, 0xe2, 0x19, 0xf0, 0x2d,
-	0x8d, 0xfc, 0x97, 0x79, 0xed, 0x10, 0xf2, 0x61, 0xe6, 0x62, 0x19, 0xe4,
-	0xc4, 0x89, 0x33, 0xc0, 0x2a, 0xe4, 0xc8, 0x89, 0xb7, 0xe0, 0x57, 0x90,
-	0x37, 0x27, 0xe6, 0x99, 0xbb, 0x2e, 0x22, 0x3f, 0x7e, 0x1a, 0xf9, 0xf1,
-	0x53, 0x95, 0x3e, 0xf0, 0x37, 0xa9, 0xb0, 0x73, 0xef, 0x71, 0xd1, 0xee,
-	0x52, 0xf5, 0x61, 0xda, 0x73, 0x14, 0x7e, 0xb4, 0x5a, 0x3d, 0x90, 0xea,
-	0x41, 0x4e, 0x1e, 0x97, 0x4f, 0x99, 0xcc, 0x63, 0x35, 0xb3, 0xbb, 0x7f,
-	0xc1, 0x08, 0xc6, 0xa4, 0xd9, 0x2b, 0xfa, 0x81, 0x95, 0xbc, 0xcf, 0x29,
-	0x5f, 0x70, 0xcc, 0xb8, 0x1c, 0xef, 0xef, 0xaa, 0xf1, 0xfe, 0xc2, 0x1a,
-	0x69, 0x19, 0x56, 0x35, 0x80, 0xee, 0xfe, 0x03, 0xc4, 0xab, 0x14, 0xfc,
-	0x3a, 0xfc, 0x6f, 0x55, 0xee, 0x48, 0x5d, 0xac, 0x9e, 0xb7, 0xd7, 0x49,
-	0xbe, 0xef, 0x8b, 0x1e, 0x66, 0x8f, 0x3d, 0x92, 0xb5, 0x8b, 0xb0, 0x0f,
-	0xb7, 0x16, 0x39, 0x3e, 0x1d, 0x46, 0x14, 0xca, 0xbf, 0x0e, 0x59, 0x18,
-	0xfc, 0x1b, 0xc8, 0x70, 0xcb, 0x69, 0x16, 0xb0, 0x74, 0xe0, 0xf0, 0x42,
-	0x34, 0xa2, 0xea, 0x33, 0xd7, 0xd9, 0xec, 0xb7, 0x20, 0xd3, 0x51, 0x59,
-	0x40, 0xfc, 0x50, 0x1a, 0x04, 0x8d, 0x7d, 0x9d, 0x18, 0x4f, 0xbb, 0x23,
-	0xcf, 0x47, 0xe1, 0x7b, 0xc9, 0xd3, 0x28, 0xc6, 0xef, 0xc2, 0x98, 0x0e,
-	0x5c, 0xbf, 0x68, 0x2c, 0x58, 0xcc, 0x9d, 0x7f, 0x0e, 0x6d, 0xce, 0x11,
-	0xf4, 0x9d, 0x9f, 0x0e, 0x89, 0x9a, 0x93, 0xef, 0x74, 0x2a, 0xfb, 0xaf,
-	0xaf, 0xc5, 0x75, 0xf8, 0xec, 0xbd, 0xea, 0x2d, 0xfd, 0x83, 0x81, 0xf5,
-	0xda, 0x02, 0xeb, 0x0d, 0x06, 0xd6, 0x23, 0x9d, 0x1d, 0x01, 0x3a, 0x3b,
-	0xf0, 0x7e, 0x0e, 0x6b, 0x0f, 0xab, 0x98, 0xa7, 0xbe, 0xe6, 0xfd, 0x81,
-	0x35, 0xfd, 0xfd, 0x75, 0x06, 0xde, 0x7b, 0x07, 0xeb, 0xb1, 0x2f, 0x1a,
-	0xe8, 0x23, 0x0d, 0xeb, 0xd1, 0xc7, 0x76, 0x47, 0x80, 0x2e, 0xd2, 0xba,
-	0x16, 0xfd, 0x2a, 0x7e, 0x02, 0x9f, 0x5b, 0xe0, 0xb7, 0x74, 0xf8, 0x0e,
-	0xd6, 0xa0, 0x1b, 0xf7, 0xfa, 0x65, 0xac, 0xeb, 0xcf, 0x17, 0xc5, 0x1c,
-	0x1c, 0xcf, 0xb1, 0x86, 0xf7, 0x3e, 0xfb, 0xf9, 0xfc, 0x1b, 0xd5, 0xaf,
-	0x2b, 0xbe, 0xad, 0x07, 0xed, 0xaa, 0xee, 0x22, 0xf3, 0x1d, 0x26, 0xe4,
-	0xc9, 0xfc, 0x58, 0x93, 0x9b, 0x6c, 0x5d, 0xeb, 0xe9, 0xa7, 0xec, 0xd7,
-	0x79, 0x58, 0xda, 0xa2, 0x65, 0x8f, 0xb3, 0x5e, 0xd0, 0xea, 0xe5, 0x7c,
-	0xc8, 0x3d, 0x94, 0x8f, 0x31, 0xbd, 0xe7, 0xf4, 0x31, 0x8c, 0x5b, 0xe8,
-	0x3f, 0x33, 0xde, 0x3d, 0xae, 0xd0, 0xe1, 0x7d, 0xa5, 0x0e, 0x39, 0xaf,
-	0x78, 0x6a, 0xc9, 0xb9, 0x1a, 0x4f, 0x43, 0xde, 0xb7, 0x90, 0x83, 0xde,
-	0x77, 0x06, 0x03, 0x71, 0x11, 0xee, 0xcb, 0x19, 0xd0, 0x10, 0x97, 0x9e,
-	0x7e, 0xe6, 0x6e, 0x45, 0x5c, 0x59, 0xa7, 0xd0, 0x70, 0x75, 0xeb, 0x17,
-	0x3d, 0xfd, 0xf0, 0x4b, 0xc0, 0xa1, 0x9e, 0xfe, 0xef, 0xa8, 0x7c, 0xae,
-	0x54, 0xb1, 0xb4, 0x3b, 0x1c, 0xb7, 0x46, 0x74, 0xce, 0xbe, 0x5c, 0x8d,
-	0x68, 0xa0, 0x99, 0x75, 0x0d, 0xbf, 0x46, 0x74, 0x4e, 0x54, 0x8d, 0xe8,
-	0xe4, 0x15, 0x6a, 0x44, 0x99, 0xab, 0xaf, 0x11, 0x71, 0x7e, 0x53, 0xee,
-	0x1e, 0x10, 0xed, 0x4b, 0x5e, 0x8d, 0xe8, 0x82, 0xb8, 0x35, 0xa2, 0xf3,
-	0xb2, 0x7a, 0x8d, 0xe8, 0x68, 0x43, 0x8d, 0x68, 0xbd, 0xaa, 0x11, 0x71,
-	0x1e, 0xb7, 0x46, 0xc4, 0x76, 0xbe, 0x7f, 0x30, 0x50, 0xeb, 0x00, 0xfe,
-	0x3a, 0xb7, 0x82, 0x6f, 0x96, 0x36, 0xea, 0xf8, 0x98, 0x46, 0xec, 0xbf,
-	0xbe, 0xe6, 0xbf, 0xea, 0xf8, 0xa6, 0x29, 0x9d, 0xbb, 0x12, 0xbe, 0x8d,
-	0xba, 0x71, 0xc9, 0x32, 0x6c, 0x9b, 0xaa, 0xc5, 0x2e, 0xbf, 0xdc, 0xcc,
-	0x1c, 0x7a, 0xb2, 0x5c, 0x9f, 0x77, 0x12, 0xf2, 0x1e, 0xab, 0xd5, 0x49,
-	0x2e, 0x15, 0x1f, 0x45, 0xe5, 0xe0, 0xaa, 0xdf, 0x9a, 0x62, 0x99, 0x95,
-	0xdf, 0x9a, 0x34, 0x89, 0x82, 0xce, 0x7c, 0x7f, 0x5e, 0xe5, 0x5d, 0x0b,
-	0xce, 0xcf, 0xcb, 0xd2, 0xbd, 0x16, 0xf0, 0xc7, 0xaf, 0x9f, 0x50, 0xbe,
-	0x75, 0x9f, 0x92, 0xd5, 0x3f, 0xba, 0x1a, 0xca, 0x3e, 0x55, 0x43, 0xf9,
-	0x5a, 0x73, 0xb0, 0x86, 0x72, 0x4e, 0x2e, 0x5f, 0x43, 0xd9, 0xb7, 0x4a,
-	0x0d, 0xe5, 0x15, 0xa9, 0xd7, 0x50, 0x5e, 0x11, 0xbf, 0x86, 0x62, 0xc8,
-	0xd2, 0x7a, 0xce, 0xb3, 0x1f, 0xef, 0x8c, 0xe0, 0x37, 0x8c, 0x9f, 0x5b,
-	0x53, 0x39, 0x57, 0xa3, 0x7f, 0xb5, 0x9a, 0xca, 0x37, 0x9b, 0xdf, 0x4f,
-	0x4d, 0xc5, 0xf5, 0x01, 0x7e, 0x4d, 0xa5, 0x05, 0xf1, 0x0e, 0x7c, 0x8e,
-	0x1e, 0xac, 0xa9, 0xfc, 0x2d, 0xed, 0x01, 0x7d, 0x2a, 0x46, 0x40, 0x3f,
-	0xec, 0x02, 0x7e, 0x29, 0xa3, 0x6a, 0x1c, 0x9f, 0xf6, 0x78, 0xb8, 0x1b,
-	0x7b, 0x8e, 0x43, 0x16, 0xe4, 0x63, 0x8f, 0x8a, 0x2d, 0x33, 0x66, 0x4c,
-	0xcb, 0xf6, 0xc2, 0x9b, 0x4d, 0xf3, 0x5b, 0x74, 0x4c, 0xc6, 0x2b, 0xd4,
-	0xf1, 0x2e, 0xc4, 0xe2, 0x26, 0xfa, 0x76, 0xa3, 0xed, 0xc7, 0x54, 0xfd,
-	0xb5, 0x39, 0x68, 0x9b, 0x0b, 0xc0, 0x59, 0xe0, 0xc4, 0x55, 0xf8, 0xa8,
-	0x6d, 0xa0, 0x39, 0xb8, 0x8f, 0x22, 0xfc, 0x13, 0xfa, 0x94, 0xcc, 0x19,
-	0x5b, 0xfa, 0xb4, 0xc4, 0x69, 0xe7, 0x57, 0x31, 0x1f, 0xfb, 0xb6, 0xa9,
-	0x7c, 0xac, 0x30, 0xc0, 0xbd, 0xd2, 0xd7, 0x2d, 0x82, 0x3e, 0xf4, 0x95,
-	0x98, 0x03, 0xd2, 0xef, 0xf9, 0x39, 0x5a, 0x44, 0xe5, 0x68, 0x9d, 0x8a,
-	0x1f, 0xe4, 0xf5, 0x8d, 0x61, 0x62, 0x65, 0xa7, 0xcd, 0x3d, 0x0c, 0x7b,
-	0x58, 0xc7, 0xb6, 0x9b, 0x0b, 0x66, 0x74, 0xde, 0x3f, 0x02, 0xb9, 0xb2,
-	0x4e, 0xe3, 0xcb, 0xef, 0x21, 0x6f, 0xdf, 0x83, 0x52, 0xec, 0x94, 0xf0,
-	0x7a, 0xd0, 0x93, 0x9f, 0x61, 0xdc, 0xfd, 0x09, 0x95, 0x83, 0x44, 0xed,
-	0x4b, 0xdb, 0xed, 0x5d, 0xd7, 0x60, 0xb7, 0x23, 0x97, 0xb5, 0xdb, 0xcf,
-	0x85, 0x83, 0x76, 0x7b, 0xd7, 0x35, 0xd8, 0xed, 0xfe, 0x6b, 0xb2, 0x5b,
-	0xee, 0x8d, 0x98, 0xe4, 0xd7, 0xc4, 0x56, 0xc6, 0x59, 0xfe, 0xba, 0x13,
-	0x58, 0x33, 0x73, 0x89, 0x35, 0xc7, 0x2e, 0x59, 0x5b, 0x6d, 0x8c, 0xb1,
-	0xae, 0x46, 0xde, 0xcc, 0xad, 0xe8, 0x6f, 0x23, 0x9e, 0x5f, 0xba, 0xdd,
-	0xcb, 0xe7, 0xfd, 0xbc, 0x3e, 0x68, 0x3f, 0xd4, 0x0b, 0xea, 0xc2, 0x63,
-	0xe0, 0x17, 0xf5, 0xc1, 0xb7, 0xb9, 0x9e, 0x06, 0x1d, 0x5c, 0x44, 0xbe,
-	0xdf, 0xe3, 0xe9, 0x20, 0x65, 0xdd, 0xab, 0xbe, 0x11, 0x95, 0x9c, 0x47,
-	0xdc, 0x3c, 0x1f, 0x3a, 0x90, 0x2f, 0xf9, 0xb6, 0x06, 0x9e, 0x44, 0xfd,
-	0x67, 0xe4, 0xa3, 0x8d, 0x98, 0x67, 0x0b, 0xe2, 0x35, 0xf0, 0x48, 0xf5,
-	0x2f, 0xaf, 0x09, 0x5f, 0x1e, 0xcf, 0xa4, 0x18, 0xc2, 0xd8, 0x53, 0x03,
-	0xb0, 0xf1, 0x01, 0x62, 0x54, 0x1a, 0x79, 0x0f, 0xf5, 0x90, 0xba, 0xb9,
-	0x29, 0xb9, 0x43, 0x67, 0x4c, 0xb5, 0x07, 0xb6, 0x47, 0x7d, 0x8d, 0xcb,
-	0x8e, 0xca, 0xa6, 0x33, 0xe7, 0x74, 0xae, 0x51, 0xad, 0xe6, 0x99, 0x2b,
-	0x5a, 0xa2, 0x77, 0xf7, 0xff, 0x45, 0x98, 0x7e, 0xe9, 0x7a, 0xdb, 0xf0,
-	0x74, 0x2d, 0x83, 0x7b, 0xea, 0xed, 0xeb, 0xf0, 0xf7, 0xfc, 0xc6, 0xfe,
-	0x03, 0xf4, 0xc7, 0x60, 0xf3, 0xf4, 0xef, 0xcc, 0x47, 0xb6, 0x7a, 0xe3,
-	0x7a, 0xd4, 0xf7, 0xcf, 0x6c, 0xea, 0x56, 0xef, 0xbb, 0x13, 0xfd, 0x4f,
-	0x82, 0x3e, 0x7b, 0x99, 0x9c, 0x79, 0x46, 0x21, 0xa7, 0xf2, 0x19, 0xbe,
-	0xaf, 0x74, 0x12, 0x39, 0x88, 0x19, 0xa8, 0xa5, 0x87, 0xbd, 0xdc, 0x8d,
-	0x36, 0x16, 0x81, 0x0c, 0xb7, 0x7b, 0xb9, 0x0a, 0xf3, 0xd7, 0xe5, 0x67,
-	0x13, 0x56, 0xd7, 0x81, 0x0d, 0xef, 0x43, 0x07, 0x1a, 0xe5, 0x17, 0x86,
-	0xed, 0xfb, 0xf2, 0xf3, 0xe3, 0x98, 0x79, 0x6f, 0xdf, 0x3d, 0xae, 0x0c,
-	0x7f, 0x2c, 0xf6, 0xa9, 0x05, 0xf6, 0xe9, 0xe3, 0xd1, 0x3e, 0x6f, 0x9f,
-	0x5b, 0x1b, 0xf0, 0x68, 0xa4, 0xc1, 0x66, 0x3f, 0x4a, 0x3c, 0x3a, 0xb4,
-	0xe6, 0xa3, 0xc7, 0x23, 0xee, 0x6b, 0xe3, 0xaa, 0x38, 0xe4, 0xee, 0xe3,
-	0x77, 0x45, 0x4f, 0x7f, 0x98, 0xf9, 0xde, 0xfb, 0x91, 0x4f, 0x10, 0x47,
-	0x28, 0x93, 0x36, 0x15, 0xc3, 0xba, 0xb6, 0x07, 0x5f, 0x5e, 0x0a, 0xc9,
-	0x1b, 0xf7, 0x84, 0xe5, 0x7f, 0x6f, 0xe3, 0xf7, 0x30, 0xd3, 0xab, 0x69,
-	0xb1, 0xfd, 0xc2, 0x1a, 0xd7, 0x0f, 0xbd, 0xd0, 0xee, 0xfa, 0x1d, 0xbe,
-	0xe3, 0xdb, 0xb3, 0x85, 0xe7, 0x7c, 0xb6, 0x91, 0x5f, 0x4c, 0xae, 0x21,
-	0x07, 0xdc, 0x64, 0x5d, 0xd0, 0x57, 0xcb, 0x01, 0x2f, 0x5f, 0x0f, 0xac,
-	0xe7, 0x80, 0xc4, 0xd9, 0x0e, 0xa5, 0x1b, 0xf9, 0x28, 0x73, 0x1f, 0xc3,
-	0xc3, 0x4e, 0xde, 0x23, 0xb7, 0x75, 0x90, 0xef, 0x42, 0xb6, 0xcf, 0x21,
-	0x5e, 0x7a, 0xd6, 0x41, 0x8e, 0xeb, 0x20, 0xb7, 0x75, 0x90, 0xdb, 0x3a,
-	0xc8, 0x6d, 0x9d, 0xa4, 0x97, 0x23, 0x8f, 0x78, 0x75, 0x7f, 0x7e, 0xe3,
-	0x66, 0x7d, 0xa1, 0x08, 0x5f, 0x32, 0xc5, 0x73, 0x13, 0x7a, 0x36, 0xb5,
-	0xc6, 0xdb, 0x9f, 0x5f, 0x13, 0xef, 0xf2, 0x6a, 0x36, 0xdf, 0x54, 0x75,
-	0x43, 0xd1, 0x1f, 0x68, 0x71, 0xbf, 0x83, 0xf3, 0x7c, 0xc7, 0xaf, 0x21,
-	0x2e, 0x51, 0x67, 0x88, 0x68, 0xa3, 0x55, 0x3d, 0xcd, 0x9a, 0x8c, 0xe8,
-	0x7a, 0xfa, 0x16, 0xbc, 0xb3, 0xc5, 0xcd, 0x09, 0xa2, 0x62, 0xe8, 0xe9,
-	0x56, 0xf2, 0x54, 0xd3, 0xd3, 0x6b, 0xbd, 0xb9, 0xf6, 0xb7, 0xb8, 0xb1,
-	0x55, 0x2f, 0xdb, 0xa6, 0xce, 0x38, 0x41, 0xc5, 0xda, 0x7e, 0xff, 0xc5,
-	0xf6, 0xe5, 0x6b, 0x85, 0x14, 0xbe, 0x67, 0x53, 0xf7, 0x62, 0x3e, 0xb6,
-	0xeb, 0xfc, 0xd6, 0x2f, 0xc9, 0xef, 0x90, 0xc7, 0x6f, 0x97, 0xc7, 0x06,
-	0xc7, 0xa9, 0xba, 0x30, 0x79, 0xed, 0xcf, 0xa7, 0xea, 0x7a, 0x58, 0x47,
-	0x9d, 0xcd, 0xc0, 0xf5, 0x07, 0xa6, 0xb4, 0x8d, 0xee, 0x0e, 0xd9, 0xc1,
-	0x75, 0xfd, 0x6f, 0xe2, 0x57, 0xb3, 0x66, 0x8f, 0xfa, 0x8e, 0xe6, 0xfa,
-	0x8c, 0x90, 0xd2, 0x41, 0x33, 0xcd, 0x7d, 0xfd, 0x50, 0x9d, 0xa9, 0xa1,
-	0xfe, 0xe5, 0x90, 0xc7, 0x4c, 0x0d, 0x6c, 0x8a, 0x9b, 0xfa, 0x48, 0x0b,
-	0xeb, 0xaf, 0x43, 0x15, 0x1f, 0xf7, 0xb8, 0x5e, 0xa3, 0x1f, 0x67, 0x5d,
-	0xcd, 0xc7, 0x33, 0xd9, 0xe0, 0xd6, 0xdb, 0x3e, 0x88, 0x2d, 0xb5, 0x34,
-	0xd8, 0x92, 0xbf, 0x4f, 0xee, 0x9f, 0xd7, 0xd5, 0xcf, 0x43, 0x2c, 0x56,
-	0x02, 0xdf, 0x47, 0x6a, 0xba, 0xc1, 0xb3, 0x2a, 0x9f, 0x85, 0x0e, 0xf2,
-	0xdb, 0xc0, 0x4e, 0xd8, 0x51, 0xb5, 0x3a, 0xc4, 0x1a, 0x73, 0xdf, 0x67,
-	0x54, 0x7e, 0xa9, 0xa7, 0xe7, 0x55, 0xfd, 0xc1, 0x5c, 0x51, 0x7f, 0x18,
-	0x82, 0xae, 0x20, 0x06, 0x70, 0xda, 0x54, 0x4c, 0xa7, 0xe2, 0x85, 0x4a,
-	0xe3, 0xf7, 0x97, 0xfb, 0x5b, 0x5d, 0x3e, 0xfc, 0x5d, 0x8b, 0xfb, 0x0d,
-	0xe2, 0x8f, 0xa2, 0xcb, 0xdb, 0x7c, 0xff, 0xaf, 0x5b, 0xfc, 0xb3, 0x3b,
-	0x85, 0x13, 0x43, 0xd0, 0x45, 0xe4, 0xe4, 0x6a, 0x3e, 0xc4, 0xbb, 0x4f,
-	0xcc, 0x76, 0x2c, 0x1f, 0x8f, 0xbe, 0x13, 0xfe, 0xf8, 0x8e, 0x86, 0xf1,
-	0x1d, 0x18, 0xff, 0x7b, 0x0d, 0xe3, 0x3b, 0x02, 0xe3, 0xa3, 0x0d, 0xe3,
-	0xa3, 0x18, 0xff, 0x7c, 0xc3, 0xf8, 0x68, 0x60, 0x7c, 0x67, 0xc3, 0xf8,
-	0x4e, 0x8c, 0x7f, 0xa1, 0x61, 0x3c, 0xfa, 0x4e, 0x34, 0x79, 0xdf, 0xc5,
-	0x88, 0xb1, 0xfb, 0xbd, 0x5c, 0x1c, 0xd7, 0x72, 0xe3, 0xb7, 0x16, 0xea,
-	0x5d, 0x17, 0x64, 0xe0, 0x9f, 0xa7, 0xa3, 0xbd, 0x66, 0x60, 0xaf, 0xf5,
-	0x58, 0xc6, 0xd5, 0xc7, 0xa0, 0x2e, 0x12, 0x1f, 0x8a, 0x62, 0xd8, 0xd0,
-	0x9d, 0x12, 0x74, 0xa8, 0xe4, 0xfb, 0x24, 0x9e, 0x83, 0xe2, 0x19, 0x53,
-	0xd7, 0xf7, 0x86, 0xec, 0x45, 0x2f, 0x07, 0x7b, 0x9b, 0xb4, 0x03, 0x2f,
-	0x7d, 0xcc, 0x94, 0x63, 0xae, 0xdd, 0x50, 0x7f, 0x39, 0xbf, 0x67, 0x3f,
-	0xd4, 0x55, 0x6f, 0x9d, 0xa1, 0x15, 0xb8, 0x16, 0x5f, 0x51, 0xdb, 0x32,
-	0xae, 0x02, 0xd7, 0x46, 0x6a, 0xb8, 0xf6, 0x59, 0x99, 0xaf, 0xe5, 0xdb,
-	0xc3, 0x72, 0xc0, 0xd9, 0xc5, 0x33, 0x36, 0xc7, 0x32, 0xf2, 0xe1, 0xe4,
-	0xdb, 0xbb, 0x6a, 0x7e, 0x92, 0x67, 0x3a, 0x96, 0x0e, 0x31, 0x87, 0xf2,
-	0x6b, 0xb3, 0x53, 0xce, 0xcf, 0xb6, 0x42, 0x2e, 0xb0, 0x8d, 0x6b, 0xcd,
-	0xb7, 0x39, 0x5f, 0x54, 0x0e, 0xb8, 0xe7, 0x1d, 0x6a, 0xf3, 0x16, 0x6b,
-	0xf3, 0xc6, 0x3c, 0x7b, 0xa3, 0x0f, 0xae, 0xfb, 0xcb, 0x1c, 0xfc, 0xe5,
-	0x18, 0x72, 0xee, 0x45, 0x67, 0xb5, 0xfa, 0xe8, 0xb5, 0xfa, 0xcb, 0xc6,
-	0x3a, 0x73, 0xa3, 0xbf, 0xe4, 0x3a, 0x8d, 0xb5, 0xe5, 0x78, 0x03, 0xfe,
-	0x53, 0x9f, 0x0e, 0x7b, 0x31, 0x35, 0xae, 0xa5, 0xc3, 0xb0, 0x47, 0x5d,
-	0xc6, 0x94, 0xfe, 0xb2, 0xed, 0xe7, 0x96, 0xbb, 0x6b, 0xb9, 0x65, 0x3d,
-	0x1f, 0x44, 0xec, 0x9a, 0xfc, 0xa4, 0x87, 0x8f, 0x8c, 0x91, 0xa7, 0xd0,
-	0x7f, 0x0c, 0x3a, 0xc0, 0x67, 0xac, 0x97, 0xde, 0x2c, 0x9f, 0x32, 0x5d,
-	0xff, 0xe4, 0xd6, 0xa6, 0x76, 0xab, 0xf8, 0x9f, 0xdf, 0x0b, 0x0a, 0xa9,
-	0x76, 0x2f, 0xde, 0xbb, 0x12, 0xae, 0x2e, 0xcf, 0x4d, 0x75, 0xfd, 0x51,
-	0xbc, 0xcb, 0xdc, 0xd4, 0x8c, 0x10, 0x43, 0xb3, 0x95, 0xcb, 0xbe, 0x5f,
-	0xa4, 0x7f, 0x29, 0xa8, 0xef, 0x82, 0x2a, 0x0f, 0xc5, 0xb8, 0x45, 0xef,
-	0x7d, 0x37, 0x0f, 0xcd, 0x56, 0xbe, 0xdd, 0xea, 0xe2, 0xe0, 0xe5, 0x72,
-	0x96, 0x9f, 0x88, 0xb0, 0xae, 0xb7, 0xe8, 0x5c, 0x89, 0xd6, 0x95, 0x79,
-	0xaf, 0xb1, 0x22, 0xef, 0x1d, 0xf5, 0xf2, 0xda, 0xcf, 0xa9, 0xbc, 0xd7,
-	0xe5, 0x31, 0xf7, 0x12, 0xcc, 0xa3, 0x6c, 0x60, 0x21, 0xbf, 0xa9, 0x10,
-	0x1f, 0x26, 0x94, 0xdf, 0xca, 0x4f, 0xdf, 0x09, 0x3e, 0x47, 0x57, 0xd1,
-	0x9b, 0x8f, 0xda, 0x4f, 0xf8, 0x7b, 0x3f, 0x2c, 0x6e, 0xbd, 0x6e, 0x27,
-	0x68, 0x61, 0x6e, 0x15, 0xf2, 0xf4, 0xe1, 0xbb, 0xde, 0x39, 0x53, 0x7f,
-	0x9c, 0x9f, 0xc7, 0xd7, 0xbe, 0xbb, 0x16, 0x33, 0xcb, 0xea, 0x27, 0x1b,
-	0x09, 0xc3, 0x90, 0x7b, 0xe6, 0x1a, 0xbe, 0x5b, 0x7c, 0x90, 0xf3, 0x11,
-	0x8d, 0x7e, 0x8d, 0xdf, 0x4d, 0xf9, 0xad, 0x54, 0xb4, 0xbb, 0x7b, 0x6d,
-	0xd8, 0x00, 0xcf, 0x2c, 0x07, 0xf1, 0x35, 0x2c, 0xf9, 0x39, 0x09, 0x47,
-	0xd3, 0xfc, 0x06, 0x40, 0xff, 0xff, 0xba, 0xb7, 0xcf, 0x98, 0xec, 0x9f,
-	0x71, 0x6b, 0x9e, 0xfa, 0x65, 0xcf, 0xc5, 0x1d, 0x00, 0x1f, 0x12, 0x47,
-	0xfd, 0x9a, 0xa7, 0xee, 0x9e, 0x8b, 0x3b, 0xfa, 0xe1, 0x9d, 0x8b, 0xe3,
-	0xfc, 0xa6, 0xec, 0x5a, 0xe5, 0x5c, 0x9c, 0x71, 0x95, 0xe7, 0xe2, 0xda,
-	0x55, 0xcd, 0x93, 0xf3, 0xb8, 0x35, 0x4f, 0xb6, 0xbb, 0xfb, 0x59, 0x2b,
-	0xe1, 0xd9, 0xb7, 0x01, 0x75, 0x06, 0xb9, 0xbb, 0xff, 0x47, 0x91, 0xa3,
-	0x7c, 0x3d, 0xf2, 0xd1, 0xe7, 0x28, 0xdc, 0xcb, 0xaf, 0xb8, 0xdf, 0x77,
-	0xe5, 0x5a, 0xea, 0x00, 0x1f, 0xac, 0xae, 0xb9, 0x5f, 0xd5, 0x35, 0xbf,
-	0x13, 0x09, 0xd6, 0x35, 0xf5, 0x2b, 0x9c, 0x0d, 0xdb, 0xbf, 0x4a, 0x5d,
-	0x33, 0x14, 0x38, 0x1b, 0x16, 0xf2, 0xce, 0x86, 0xb5, 0xdb, 0xc8, 0x25,
-	0xbd, 0x3a, 0xa6, 0x7e, 0xd9, 0xb3, 0x61, 0xff, 0x19, 0xf9, 0xe0, 0x75,
-	0xcc, 0x15, 0x67, 0xc3, 0xe0, 0xeb, 0x36, 0x48, 0xfc, 0x9a, 0xf2, 0x9e,
-	0x0f, 0x92, 0xf3, 0xf0, 0xbc, 0x7e, 0x13, 0xf6, 0x1c, 0x92, 0x5d, 0x51,
-	0xea, 0x27, 0xcf, 0x36, 0xf6, 0xc2, 0x16, 0x70, 0xad, 0xb0, 0x9d, 0xa4,
-	0x8c, 0xb4, 0x91, 0xde, 0xe5, 0xe7, 0x10, 0xea, 0xe7, 0x71, 0xc3, 0xb5,
-	0xf3, 0xb8, 0x47, 0xa0, 0x37, 0xfa, 0x4c, 0x58, 0x16, 0x02, 0x3a, 0x35,
-	0x85, 0x78, 0x4f, 0x9f, 0xb3, 0xbc, 0xe7, 0xfc, 0x9f, 0x8a, 0x28, 0x30,
-	0x8f, 0x67, 0x78, 0xdb, 0xc4, 0x98, 0x73, 0xbf, 0x59, 0xba, 0xff, 0x57,
-	0x12, 0xc3, 0x18, 0x9e, 0xf1, 0x0c, 0xc9, 0x01, 0x55, 0xb3, 0xf0, 0x75,
-	0x79, 0xc7, 0x5a, 0x69, 0x59, 0x9f, 0xa9, 0xb7, 0xa3, 0xab, 0xf8, 0x7d,
-	0xc4, 0x91, 0x33, 0xd4, 0xe7, 0x5b, 0x25, 0xe7, 0xd5, 0x83, 0x0a, 0x95,
-	0x6d, 0x5e, 0x7e, 0xa1, 0xbe, 0xed, 0x80, 0x97, 0xdd, 0x9e, 0x0f, 0xc6,
-	0xb5, 0xd4, 0x4d, 0x9f, 0x87, 0x35, 0x4e, 0xca, 0xd0, 0xf4, 0x96, 0xd8,
-	0x38, 0xf0, 0x6e, 0x4c, 0xad, 0x79, 0x2d, 0x3c, 0xd7, 0x2e, 0xf1, 0xbd,
-	0xf1, 0x6a, 0xf9, 0xee, 0xc7, 0xc7, 0x8f, 0x62, 0x7f, 0xdd, 0xd0, 0x8f,
-	0x87, 0x25, 0x77, 0xe2, 0x66, 0x19, 0x9a, 0x4d, 0x80, 0x9e, 0x1f, 0x56,
-	0x0b, 0x29, 0xc4, 0xd2, 0x4f, 0xf0, 0xdc, 0x18, 0x30, 0x14, 0x7c, 0x7b,
-	0x66, 0xc5, 0x77, 0xec, 0xe0, 0x59, 0xb3, 0x64, 0xed, 0xec, 0xd0, 0x53,
-	0x15, 0x09, 0x77, 0x90, 0xe6, 0x99, 0xfa, 0xd9, 0xef, 0xc5, 0xca, 0x0e,
-	0xe5, 0xdb, 0x9e, 0xac, 0x2c, 0xab, 0xfd, 0x28, 0x19, 0x4e, 0x94, 0x9f,
-	0x04, 0x2f, 0x5e, 0x51, 0xfe, 0xed, 0x88, 0x23, 0x37, 0x19, 0x42, 0x79,
-	0x88, 0x06, 0x1e, 0xa8, 0x33, 0x1c, 0xee, 0xf7, 0xfd, 0x2e, 0x25, 0x57,
-	0x17, 0x2b, 0x76, 0x06, 0xce, 0x60, 0xd4, 0x65, 0xeb, 0x9e, 0xcd, 0x70,
-	0x65, 0xe1, 0x9e, 0x1f, 0x21, 0x3f, 0x97, 0x0e, 0xed, 0xb2, 0xdd, 0xf3,
-	0x23, 0x3d, 0x73, 0xec, 0xeb, 0x6c, 0xf0, 0x7d, 0x61, 0xe8, 0x00, 0xcf,
-	0x1d, 0xf1, 0xcc, 0x37, 0x69, 0x56, 0xb5, 0x8e, 0x55, 0xbf, 0x6d, 0x5f,
-	0x5b, 0xcd, 0xd5, 0x5d, 0xb3, 0x5b, 0xad, 0x79, 0x9d, 0x87, 0x59, 0xfe,
-	0x59, 0xef, 0x94, 0xf6, 0xff, 0xd4, 0x5d, 0x7b, 0x6c, 0x1b, 0xf7, 0x7d,
-	0xff, 0xf2, 0x48, 0x3d, 0xac, 0xe7, 0x49, 0xa6, 0x64, 0x5a, 0x52, 0x94,
-	0x3b, 0xe9, 0x64, 0x29, 0xb1, 0x12, 0x70, 0x9e, 0xba, 0x0a, 0x88, 0x9a,
-	0xb0, 0x24, 0xfd, 0x58, 0x10, 0x0c, 0xb4, 0xad, 0x64, 0xee, 0x92, 0xad,
-	0x0e, 0x25, 0xa7, 0x1d, 0x30, 0x60, 0x6e, 0xd6, 0x02, 0x69, 0x07, 0xc7,
-	0x0c, 0x65, 0x27, 0xc6, 0xaa, 0x88, 0x4c, 0xcc, 0x6a, 0x1d, 0xb0, 0x62,
-	0x1c, 0xa5, 0x38, 0x69, 0xa7, 0x80, 0x69, 0xda, 0x04, 0xc5, 0xfe, 0xb1,
-	0x26, 0x3b, 0x7b, 0x61, 0x7f, 0x04, 0xdb, 0x80, 0x1a, 0x5b, 0x81, 0xba,
-	0x76, 0x8a, 0x65, 0x1b, 0xe0, 0x34, 0xdb, 0xb0, 0x75, 0x58, 0x0b, 0xee,
-	0xfb, 0xf9, 0x3d, 0xc8, 0x23, 0x79, 0xd4, 0xc3, 0x71, 0x06, 0x4c, 0x80,
-	0x40, 0xde, 0xf1, 0x77, 0x77, 0xbf, 0xdf, 0xf7, 0xf7, 0x7d, 0xbf, 0x6e,
-	0x2e, 0x33, 0x1e, 0xf2, 0x33, 0x7e, 0xcf, 0x15, 0x61, 0x5f, 0x37, 0xd2,
-	0xe1, 0x36, 0x83, 0x67, 0xa4, 0x0e, 0x9e, 0xd5, 0x34, 0xc1, 0xf6, 0x78,
-	0x99, 0x77, 0x4b, 0xd8, 0xc9, 0xf3, 0xc8, 0x63, 0xd7, 0x39, 0x0e, 0x12,
-	0x76, 0x65, 0x1a, 0x5a, 0x72, 0xe7, 0x37, 0x54, 0x60, 0x77, 0xb2, 0x0c,
-	0xbb, 0x3d, 0xff, 0x8f, 0x60, 0x77, 0x4d, 0xe8, 0xbf, 0xdf, 0x2e, 0x22,
-	0x6f, 0x4d, 0xeb, 0x00, 0xba, 0x6e, 0x09, 0x70, 0x04, 0x3f, 0xb5, 0xf3,
-	0xeb, 0x04, 0x9e, 0x8a, 0xbc, 0xe2, 0x52, 0xe9, 0x3b, 0xe1, 0xb2, 0x9f,
-	0x92, 0xed, 0x12, 0xd8, 0x27, 0xf0, 0xe7, 0x35, 0x96, 0x91, 0x47, 0x6f,
-	0x4b, 0x46, 0x42, 0x57, 0xaa, 0xb5, 0x4f, 0x7e, 0xbb, 0xcb, 0x6d, 0x9f,
-	0x1c, 0xdd, 0xa1, 0x7d, 0x72, 0x5a, 0xda, 0x27, 0xa9, 0xed, 0xdb, 0x27,
-	0x03, 0x75, 0x79, 0x5d, 0x95, 0xf5, 0xec, 0xdc, 0x3e, 0x31, 0x36, 0xb5,
-	0x4f, 0x46, 0x5d, 0xbe, 0x18, 0xcc, 0xf7, 0x57, 0x29, 0x75, 0x0c, 0x3c,
-	0x4e, 0xc3, 0x19, 0x30, 0x3e, 0x56, 0xe3, 0x17, 0xfe, 0x38, 0x61, 0xfd,
-	0xd7, 0xff, 0xc7, 0xb0, 0x1e, 0xac, 0xf3, 0x79, 0x57, 0xd6, 0x03, 0x21,
-	0xfe, 0x51, 0x60, 0x3d, 0xd8, 0xd0, 0x77, 0xda, 0x38, 0x67, 0xb1, 0xda,
-	0x77, 0x3a, 0x62, 0x34, 0xe2, 0xed, 0x7f, 0xe4, 0xf2, 0xa9, 0xba, 0xf9,
-	0x3b, 0x68, 0x8a, 0x7c, 0x47, 0xc7, 0xf5, 0xb3, 0x40, 0x4b, 0x76, 0x2a,
-	0x45, 0xb0, 0x99, 0xf0, 0xbc, 0x90, 0xa0, 0xb5, 0x1a, 0x7d, 0x8b, 0x9f,
-	0xc7, 0xeb, 0x7b, 0xf5, 0x09, 0x21, 0xa7, 0xa4, 0xff, 0x01, 0xe3, 0x27,
-	0x7c, 0xf3, 0x62, 0xac, 0xcc, 0x6f, 0x52, 0xfe, 0x08, 0xa5, 0xfb, 0x37,
-	0xf2, 0x43, 0xd4, 0xcb, 0xbc, 0x9d, 0xd9, 0x0a, 0x9a, 0xc6, 0xef, 0xe6,
-	0x7d, 0x09, 0x55, 0xd9, 0x5a, 0xe0, 0x9f, 0xa7, 0x59, 0x2f, 0x18, 0x29,
-	0xeb, 0x04, 0xd5, 0x7b, 0x73, 0x4e, 0xd8, 0x74, 0x9a, 0x77, 0x26, 0x64,
-	0xee, 0xa9, 0x38, 0x0f, 0x3d, 0x4d, 0xf3, 0xce, 0x5a, 0x3d, 0xf8, 0x6e,
-	0x0f, 0xbc, 0xf0, 0xca, 0x69, 0x2a, 0xef, 0x9d, 0x85, 0x9c, 0xf3, 0xb8,
-	0xe7, 0xde, 0x95, 0x6b, 0xc2, 0x52, 0x95, 0xb1, 0xf2, 0xfa, 0xb8, 0x58,
-	0xd7, 0x0f, 0x8e, 0x44, 0x51, 0xfb, 0x56, 0xae, 0x17, 0xab, 0xad, 0x77,
-	0x82, 0x1c, 0xd0, 0x74, 0xa8, 0x6b, 0xa2, 0x01, 0x8b, 0x61, 0x8f, 0x7a,
-	0x27, 0xb7, 0x2c, 0xc1, 0x75, 0xb5, 0xb0, 0xa8, 0xc8, 0x91, 0xf3, 0x4a,
-	0x8e, 0x14, 0x5c, 0x7c, 0xbc, 0x5e, 0x6f, 0xef, 0xf5, 0xd0, 0xdb, 0xbd,
-	0x6a, 0x9e, 0x30, 0xa7, 0x67, 0x58, 0x0f, 0xb9, 0x1f, 0x7a, 0x88, 0x89,
-	0xba, 0x25, 0xa9, 0x8b, 0xe0, 0x77, 0x96, 0x35, 0xaf, 0x86, 0x18, 0x57,
-	0x8e, 0xd0, 0x53, 0xac, 0x6b, 0x5f, 0xa2, 0x7b, 0x94, 0x7d, 0x16, 0x71,
-	0xe5, 0x99, 0x22, 0x8f, 0xdf, 0x47, 0xa9, 0x27, 0xec, 0x89, 0x08, 0x1d,
-	0xa1, 0x53, 0x22, 0x67, 0x06, 0xf1, 0x3d, 0xe4, 0x1c, 0xdc, 0x2b, 0x9e,
-	0x2f, 0x7d, 0x19, 0x77, 0x22, 0xa7, 0x6e, 0xfb, 0xf9, 0xfb, 0xba, 0x56,
-	0x2f, 0x2a, 0x9e, 0xb9, 0xaa, 0x68, 0x4a, 0x9c, 0xe3, 0xeb, 0x9f, 0x31,
-	0xea, 0xaf, 0x8f, 0x18, 0xf1, 0x62, 0xdc, 0x88, 0xae, 0x60, 0xdc, 0x33,
-	0x46, 0xac, 0x08, 0x1b, 0x52, 0xe3, 0x88, 0x1d, 0x06, 0xbd, 0x6d, 0xd0,
-	0xd6, 0xb1, 0x88, 0x02, 0xd5, 0xd4, 0x49, 0x6c, 0x63, 0xde, 0x87, 0xaa,
-	0xe6, 0xad, 0xe1, 0x8b, 0xef, 0xf0, 0xf7, 0x44, 0x18, 0xa6, 0x5a, 0xaf,
-	0x6d, 0x83, 0x7f, 0x7d, 0x22, 0x45, 0x9b, 0xe9, 0xb5, 0x76, 0x9d, 0x5e,
-	0x5b, 0xd8, 0x72, 0xde, 0x1f, 0x95, 0xc6, 0x65, 0x3d, 0xa2, 0xdf, 0x11,
-	0xfa, 0x2b, 0xcf, 0xbb, 0x4a, 0xb7, 0xad, 0xc1, 0x29, 0x8c, 0xd1, 0x7e,
-	0x70, 0xed, 0x07, 0xeb, 0x52, 0xf9, 0xc0, 0x3a, 0x3f, 0xa1, 0x0d, 0xf5,
-	0x5e, 0xa6, 0xcc, 0x6b, 0x85, 0x8d, 0xb5, 0xce, 0xf3, 0x83, 0xbd, 0xf5,
-	0xa0, 0x98, 0x23, 0xdb, 0x5b, 0x56, 0x8c, 0xa4, 0xaf, 0x7b, 0xbe, 0x58,
-	0x55, 0xff, 0xe9, 0x51, 0x07, 0x39, 0xe2, 0x51, 0x07, 0xe9, 0xa6, 0xb5,
-	0x80, 0x8b, 0xd6, 0x42, 0x2e, 0xbd, 0x6d, 0x88, 0xed, 0x96, 0x0e, 0xe6,
-	0x21, 0xb0, 0x5b, 0xda, 0xc8, 0xff, 0xb2, 0xdb, 0x6e, 0xa9, 0xad, 0x45,
-	0x07, 0xdd, 0x41, 0x37, 0x93, 0x36, 0x4c, 0x3c, 0x57, 0xae, 0x63, 0xe7,
-	0x75, 0x57, 0x6a, 0x0e, 0x57, 0xea, 0xea, 0x23, 0xbd, 0xe6, 0x3b, 0x5c,
-	0x37, 0x5f, 0xc8, 0xaf, 0x48, 0x43, 0x9d, 0xce, 0xcb, 0xae, 0xba, 0x53,
-	0xf3, 0xab, 0xe5, 0x67, 0x78, 0xd6, 0x88, 0xf0, 0x79, 0xa7, 0xca, 0xbc,
-	0x6c, 0x5a, 0xce, 0x37, 0x53, 0x6d, 0x67, 0xf8, 0x97, 0x48, 0xc1, 0xce,
-	0x9b, 0xb7, 0xef, 0xcc, 0x7f, 0xd6, 0x5e, 0x23, 0x77, 0xdf, 0x33, 0xa5,
-	0x5f, 0xac, 0x49, 0xe5, 0x61, 0xf7, 0x29, 0x7b, 0x6f, 0x2b, 0x7c, 0xc7,
-	0xb9, 0x26, 0xe5, 0x4b, 0xb4, 0xad, 0x3c, 0x01, 0xcf, 0x8f, 0x9d, 0x68,
-	0x72, 0x4c, 0x15, 0xcb, 0x42, 0xbc, 0x0a, 0x78, 0xaf, 0xef, 0x0f, 0x9e,
-	0xbd, 0x9d, 0x3d, 0xb3, 0xea, 0xf6, 0x4c, 0xe2, 0x15, 0x6c, 0x2d, 0xe4,
-	0x17, 0x4f, 0xd6, 0xe4, 0x78, 0x7f, 0x14, 0x58, 0x74, 0x79, 0xe4, 0x3d,
-	0x23, 0x6f, 0xb9, 0xd1, 0x3c, 0xaf, 0xbb, 0xf4, 0x72, 0xcc, 0xb7, 0x54,
-	0x7a, 0x23, 0x3c, 0x20, 0x65, 0x71, 0xd1, 0x5b, 0x47, 0x32, 0xb7, 0x3d,
-	0xbf, 0x5a, 0xd9, 0xbb, 0x77, 0x9b, 0xb2, 0x57, 0xf4, 0xf4, 0xf0, 0x1d,
-	0x14, 0x3c, 0xa0, 0x83, 0x56, 0x72, 0xc8, 0xbf, 0xfe, 0x05, 0xd0, 0x3c,
-	0xf3, 0x59, 0x57, 0x4d, 0x9a, 0xf7, 0x3e, 0x96, 0x63, 0x2a, 0x81, 0x19,
-	0xc4, 0xfe, 0x90, 0x5b, 0xd2, 0xcb, 0xbc, 0x07, 0xe3, 0xc7, 0xac, 0xab,
-	0xf0, 0xf7, 0x2a, 0xff, 0x53, 0x5c, 0xc9, 0x97, 0x83, 0xdb, 0x88, 0xad,
-	0xec, 0x8c, 0x4f, 0xdb, 0xd6, 0x3a, 0x21, 0xee, 0x83, 0x7c, 0xe1, 0xfb,
-	0xba, 0xa8, 0xeb, 0x33, 0x2d, 0x2d, 0xce, 0x97, 0x7a, 0x64, 0x2c, 0x0a,
-	0xbf, 0x75, 0xd0, 0x2b, 0x39, 0xe4, 0x72, 0xe3, 0xb7, 0xdf, 0xe0, 0xdf,
-	0xbc, 0x78, 0x94, 0xce, 0x45, 0x87, 0x2e, 0x27, 0xf7, 0x27, 0x4f, 0xb0,
-	0x95, 0x4a, 0xf4, 0xb7, 0xe1, 0x5f, 0x94, 0xf1, 0x8c, 0xe2, 0x9d, 0x8e,
-	0xd5, 0x78, 0xf9, 0x0b, 0xdf, 0xec, 0xb9, 0xdd, 0xdc, 0xc8, 0x2f, 0x6c,
-	0xcb, 0x5f, 0x88, 0x38, 0xff, 0x76, 0x62, 0x26, 0x3a, 0x36, 0x3c, 0x25,
-	0x6a, 0x4e, 0xdd, 0x78, 0x70, 0x67, 0xe2, 0xc3, 0xc0, 0x87, 0xe1, 0x3a,
-	0x5e, 0xf5, 0xd1, 0xfd, 0xfd, 0xb5, 0x70, 0x6d, 0xf3, 0xf4, 0x55, 0x79,
-	0xc7, 0x81, 0x11, 0xf3, 0x87, 0x9f, 0xfa, 0x21, 0x9a, 0xbf, 0x08, 0x1c,
-	0x36, 0x18, 0xdb, 0x46, 0x69, 0x21, 0x88, 0xba, 0x22, 0x51, 0x9b, 0xa3,
-	0xe2, 0x86, 0xb2, 0x56, 0x68, 0x5e, 0xd4, 0x40, 0x8e, 0x85, 0x6e, 0xf2,
-	0xbc, 0xe7, 0x8b, 0x29, 0x3a, 0xc5, 0x32, 0xf6, 0xd4, 0x4a, 0x45, 0x77,
-	0xaf, 0xaf, 0x83, 0xac, 0xc6, 0xf1, 0x9b, 0x02, 0xc7, 0x87, 0x36, 0xc5,
-	0xf1, 0xc3, 0x65, 0x1c, 0xff, 0x44, 0xaf, 0xc4, 0xe7, 0x67, 0xf9, 0x5e,
-	0x5d, 0x74, 0x50, 0xdc, 0x37, 0xc5, 0xdf, 0xdb, 0xe9, 0xa0, 0xec, 0x61,
-	0xc1, 0xcf, 0x66, 0x1e, 0x9f, 0x49, 0xd1, 0x53, 0x17, 0x53, 0xbe, 0xb8,
-	0xa8, 0x5f, 0x70, 0xf7, 0xe8, 0xd0, 0xd7, 0x63, 0x5c, 0x23, 0xfc, 0xd7,
-	0x7c, 0x49, 0xd6, 0x5c, 0xe5, 0x25, 0x7f, 0xa2, 0x77, 0xc3, 0x83, 0x35,
-	0xf8, 0x5f, 0x6d, 0x3b, 0x9e, 0x56, 0x32, 0xf0, 0xd8, 0x26, 0x7e, 0x8d,
-	0x7a, 0xbc, 0xec, 0xf1, 0xd0, 0x87, 0x7f, 0xbd, 0x57, 0xc6, 0xa9, 0x36,
-	0xf3, 0x6b, 0xb8, 0x71, 0xb4, 0x2a, 0x6e, 0xcf, 0x7c, 0xff, 0xbf, 0x55,
-	0x1c, 0xfd, 0xa5, 0x5e, 0x29, 0x2f, 0x50, 0x1f, 0x98, 0x60, 0x38, 0x9c,
-	0x64, 0x5d, 0x65, 0x90, 0x9a, 0x5f, 0xd6, 0x6b, 0x1d, 0x14, 0xfc, 0xd6,
-	0xed, 0xa7, 0x39, 0xa7, 0x6a, 0xbb, 0xd3, 0xae, 0x35, 0x9d, 0x13, 0x36,
-	0x4e, 0x63, 0x7a, 0x6b, 0x9c, 0x73, 0x35, 0x54, 0x23, 0x13, 0x6a, 0xf1,
-	0x0d, 0xbd, 0x4f, 0xb0, 0xbf, 0x64, 0x48, 0x3d, 0x78, 0x9a, 0xf5, 0xdb,
-	0x9d, 0xc6, 0x8b, 0x3e, 0xaa, 0x8e, 0x58, 0xdb, 0x53, 0xa3, 0xf6, 0x3b,
-	0xf6, 0x41, 0xda, 0x1c, 0xc9, 0x57, 0x1f, 0x12, 0xbc, 0xe0, 0xdc, 0x64,
-	0x89, 0x62, 0xe1, 0x4e, 0x4a, 0x4e, 0xf2, 0xb3, 0xa7, 0x1d, 0xb6, 0xbd,
-	0xfc, 0x94, 0x62, 0xfa, 0x4d, 0x4e, 0xee, 0x52, 0xfa, 0xa2, 0xf6, 0xa7,
-	0xb7, 0xa8, 0x3c, 0x87, 0x67, 0x45, 0x5c, 0x52, 0xf6, 0xc6, 0xe0, 0xef,
-	0x2b, 0xfa, 0xde, 0xcf, 0x8a, 0xf8, 0x68, 0xf2, 0x62, 0xb3, 0x1a, 0xd7,
-	0xee, 0x1a, 0x87, 0x31, 0xed, 0x6a, 0x2c, 0xee, 0xa9, 0x75, 0x8a, 0x56,
-	0xc5, 0x6f, 0x1f, 0x11, 0x75, 0x60, 0xb2, 0x56, 0x0f, 0xbf, 0x9f, 0xa6,
-	0xb9, 0xf2, 0x5a, 0xda, 0x79, 0xec, 0xcf, 0x4a, 0x11, 0x61, 0xcb, 0xb5,
-	0xb3, 0xce, 0x8b, 0x79, 0xd7, 0xcf, 0x09, 0x6b, 0xf1, 0x8b, 0xf8, 0x10,
-	0x7f, 0x57, 0xcf, 0x39, 0x59, 0x9e, 0x13, 0x72, 0x34, 0xec, 0x90, 0xbc,
-	0x97, 0x1e, 0xd7, 0xee, 0x1a, 0xa7, 0x79, 0x85, 0x8e, 0x3f, 0xfc, 0x80,
-	0xe7, 0xf1, 0x37, 0x2a, 0x87, 0xd7, 0x14, 0xf1, 0x53, 0x99, 0xa3, 0xa1,
-	0xbf, 0xc3, 0xbf, 0x8c, 0x9c, 0x0a, 0xe4, 0x49, 0xb8, 0xf9, 0x8d, 0x5c,
-	0x6f, 0x00, 0xb2, 0xa8, 0x88, 0xb8, 0x29, 0xe2, 0x15, 0x8d, 0x74, 0xe7,
-	0xbd, 0xc8, 0xcd, 0xdf, 0x81, 0x0e, 0xba, 0x1d, 0xfa, 0xb3, 0x3c, 0xe8,
-	0xcf, 0xfd, 0x7c, 0xd4, 0xc1, 0xa1, 0x1e, 0x2e, 0x35, 0x61, 0x50, 0x89,
-	0x6d, 0x05, 0x83, 0xf2, 0xa6, 0x8f, 0x9e, 0x72, 0xec, 0xf0, 0x0a, 0xc9,
-	0x9a, 0xc9, 0xd8, 0xa2, 0x3d, 0xb1, 0x4e, 0xfb, 0x45, 0xcd, 0x38, 0x7a,
-	0x1f, 0xe4, 0x59, 0x06, 0x9f, 0xa4, 0x09, 0xb6, 0x8f, 0xd8, 0xfe, 0x9c,
-	0x45, 0xbc, 0x45, 0xef, 0x0b, 0x6a, 0xe0, 0xf1, 0x39, 0xc1, 0x70, 0x7a,
-	0x6c, 0x37, 0xb5, 0x45, 0xf8, 0x9e, 0x13, 0xe0, 0x4f, 0xe8, 0xe7, 0x45,
-	0x51, 0xb6, 0x93, 0x60, 0xb3, 0x9e, 0x9c, 0xb5, 0xcd, 0x3c, 0x19, 0x3c,
-	0x16, 0xb6, 0x2b, 0xee, 0x83, 0xeb, 0x23, 0x66, 0x13, 0xd5, 0xd6, 0xe4,
-	0x3e, 0x2b, 0xea, 0x14, 0xdf, 0x0d, 0xdf, 0x47, 0x46, 0x3f, 0xf8, 0x15,
-	0xf6, 0xed, 0x5e, 0x15, 0x27, 0x3a, 0xcb, 0xdf, 0xc7, 0xd5, 0xf7, 0xaf,
-	0x88, 0xfd, 0x94, 0xdf, 0x35, 0x7e, 0xe3, 0xef, 0x5f, 0x5a, 0xc8, 0xf9,
-	0xa1, 0xca, 0x59, 0xa9, 0xca, 0x05, 0x09, 0x8d, 0x1a, 0x5f, 0xa1, 0xd3,
-	0x2b, 0x9b, 0xf9, 0x5f, 0xbc, 0x6a, 0x5d, 0xbb, 0xb7, 0x59, 0xeb, 0xfa,
-	0x07, 0xbb, 0x65, 0x6d, 0x99, 0x7b, 0x2e, 0xff, 0xc9, 0x73, 0xf1, 0xd2,
-	0xc9, 0xea, 0xf4, 0x44, 0x5e, 0x6f, 0x89, 0xfe, 0x29, 0xfc, 0x49, 0xba,
-	0x1e, 0x0c, 0xa9, 0x9c, 0x25, 0xe4, 0x28, 0xdd, 0xa7, 0xf0, 0x5a, 0xf3,
-	0x7e, 0xf2, 0xe0, 0xfd, 0x8f, 0x89, 0x5c, 0x4d, 0x29, 0x3b, 0x06, 0x15,
-	0x3c, 0x00, 0xb3, 0x90, 0x0b, 0x66, 0x7d, 0x2e, 0x98, 0x19, 0xea, 0x7b,
-	0xa7, 0x38, 0x3e, 0xbd, 0xf2, 0x99, 0x6e, 0x59, 0x2f, 0x8e, 0x58, 0xe2,
-	0xbc, 0xfa, 0xbe, 0xd5, 0x7a, 0x7f, 0xce, 0x6b, 0x15, 0xfe, 0x26, 0xd7,
-	0x5a, 0x5f, 0x27, 0x72, 0x5a, 0x82, 0xf5, 0x30, 0xf8, 0x8e, 0xeb, 0x3c,
-	0xe6, 0x38, 0xe6, 0x9a, 0xe3, 0x88, 0x6b, 0x8e, 0x77, 0x37, 0x98, 0x23,
-	0xf3, 0xf8, 0xe2, 0x69, 0xfe, 0xbf, 0xdd, 0xb9, 0xca, 0x79, 0xce, 0x0b,
-	0x78, 0xb6, 0x53, 0x3a, 0x18, 0x52, 0xb2, 0xe3, 0xfb, 0xaa, 0x16, 0xdd,
-	0x6b, 0xce, 0xff, 0x40, 0x8d, 0xf7, 0xcd, 0x8d, 0xab, 0xee, 0xfa, 0xe3,
-	0x97, 0x28, 0x26, 0xeb, 0xc8, 0x15, 0x6d, 0x7f, 0xb5, 0x81, 0x1f, 0xfa,
-	0x41, 0xa1, 0xff, 0xcc, 0xcb, 0x78, 0xd0, 0x80, 0xec, 0xbf, 0x16, 0xa0,
-	0xd5, 0x72, 0x2d, 0xaf, 0x5f, 0xd5, 0xee, 0xdc, 0x1f, 0xbc, 0xb3, 0x75,
-	0xbc, 0x38, 0xff, 0x88, 0xf0, 0xe5, 0xc9, 0xf8, 0x51, 0x42, 0xd5, 0x23,
-	0xdb, 0x16, 0x72, 0x03, 0x0a, 0x6b, 0xf0, 0xbf, 0x36, 0xaa, 0xdd, 0xc5,
-	0xb5, 0xf0, 0x03, 0x6a, 0x3b, 0xfe, 0x84, 0xe0, 0x89, 0xd2, 0x3f, 0x26,
-	0xeb, 0x6f, 0x0b, 0x6b, 0x27, 0x45, 0xcd, 0x6b, 0x54, 0xd5, 0xf1, 0x26,
-	0xa9, 0x43, 0xe8, 0xb9, 0xb7, 0x5f, 0x7f, 0xfb, 0x5c, 0x70, 0xe7, 0xf5,
-	0xb7, 0xee, 0x6b, 0x76, 0x56, 0x7f, 0x6b, 0xf2, 0xda, 0x8d, 0x65, 0x59,
-	0x7f, 0x5b, 0x1d, 0x93, 0x91, 0xfe, 0xc0, 0xa4, 0x4b, 0x7f, 0x90, 0xfa,
-	0xfa, 0x6f, 0xb9, 0xf2, 0xb7, 0x65, 0x6d, 0x6d, 0xa1, 0xac, 0xb3, 0xca,
-	0xda, 0x5a, 0x99, 0xef, 0xed, 0xee, 0x03, 0x23, 0x63, 0x3f, 0xf2, 0x39,
-	0x9d, 0x35, 0xb1, 0x1f, 0x59, 0x53, 0x6b, 0x19, 0x8d, 0x6c, 0x38, 0xd1,
-	0xe7, 0xa2, 0x8f, 0xba, 0x22, 0x8c, 0xbb, 0xed, 0x0d, 0xfa, 0x21, 0x44,
-	0x1a, 0xf4, 0x43, 0x70, 0xf3, 0x7e, 0xb7, 0x8e, 0x05, 0x9d, 0x18, 0xb2,
-	0x11, 0xba, 0x30, 0xfa, 0x19, 0x84, 0xe9, 0x74, 0x59, 0xf7, 0xbc, 0x8f,
-	0x12, 0x4a, 0xf7, 0x3c, 0xbd, 0xa2, 0xf9, 0xd1, 0x48, 0x0d, 0x3f, 0xf2,
-	0xd2, 0x45, 0x6d, 0x95, 0xe7, 0xa3, 0xe9, 0x35, 0xe5, 0xa2, 0xd7, 0x94,
-	0x07, 0xbd, 0x8a, 0x67, 0x34, 0x98, 0xf7, 0xf7, 0xd5, 0x35, 0xf8, 0x4f,
-	0x84, 0xd0, 0xb3, 0x85, 0x79, 0x6a, 0x50, 0xe9, 0x7f, 0x2e, 0x7a, 0x3d,
-	0xc5, 0xf4, 0xaa, 0xcf, 0x63, 0xbe, 0x0d, 0x73, 0x41, 0x95, 0xce, 0x38,
-	0xe8, 0x3b, 0x74, 0xf1, 0x1b, 0x22, 0x4f, 0xaa, 0xda, 0x5e, 0xd4, 0xfa,
-	0xc4, 0x3e, 0x41, 0x4b, 0xd7, 0xfd, 0xc8, 0x5b, 0xd1, 0xe7, 0x4c, 0xe5,
-	0x27, 0xd3, 0xb0, 0x68, 0xae, 0xd2, 0x39, 0x2a, 0xfa, 0x86, 0xc8, 0xf1,
-	0x75, 0xcd, 0xed, 0x43, 0x9e, 0x9b, 0x3e, 0xaf, 0x65, 0xe6, 0xb5, 0x2a,
-	0x7f, 0xc6, 0xe5, 0xaa, 0x9e, 0x83, 0xf0, 0x1d, 0x75, 0x26, 0x0c, 0x27,
-	0x2e, 0x72, 0x4c, 0x7b, 0x1c, 0xf8, 0xc9, 0xa2, 0x4c, 0xfb, 0x3d, 0x09,
-	0xe4, 0x33, 0xf7, 0x2c, 0x59, 0x74, 0x3c, 0x73, 0xff, 0x5d, 0x12, 0x57,
-	0xce, 0x8a, 0x3e, 0x92, 0xe8, 0x67, 0x16, 0x63, 0xf9, 0x1c, 0xf5, 0x4f,
-	0xd3, 0xf9, 0x62, 0x0b, 0x15, 0x58, 0xbb, 0xf7, 0x3b, 0x79, 0xe1, 0xeb,
-	0x63, 0x9e, 0x94, 0x45, 0x2f, 0x51, 0x63, 0xb9, 0x99, 0xef, 0xdb, 0x4f,
-	0xab, 0xb9, 0x31, 0xd1, 0x13, 0x4a, 0xf6, 0x17, 0xc1, 0x58, 0x1f, 0xf5,
-	0x3a, 0x07, 0xfb, 0xa8, 0xed, 0xb3, 0x22, 0xc7, 0xb2, 0x90, 0x3d, 0x2b,
-	0x3f, 0xf3, 0x0f, 0xa8, 0x67, 0xf0, 0xf3, 0x8a, 0x7f, 0x4a, 0x91, 0x5e,
-	0xcb, 0x65, 0xcb, 0xb9, 0xff, 0xbc, 0xf5, 0x95, 0xa3, 0x3b, 0xd2, 0x57,
-	0x52, 0x89, 0x8a, 0xbe, 0xe2, 0xbe, 0x77, 0x39, 0x07, 0xa6, 0x5f, 0xf6,
-	0x7b, 0x00, 0x0c, 0xda, 0xa1, 0x8b, 0x25, 0x00, 0x4b, 0x63, 0xc6, 0x0e,
-	0x45, 0xfd, 0x53, 0xb4, 0x50, 0x1c, 0x32, 0x92, 0x59, 0xe8, 0xcc, 0xfc,
-	0x99, 0x8f, 0xee, 0x91, 0x3e, 0x1a, 0x7d, 0x0d, 0xf8, 0xca, 0x6e, 0x1e,
-	0xff, 0x7a, 0xbf, 0xcc, 0xcb, 0x76, 0x9f, 0xef, 0xe2, 0xf3, 0x7b, 0x42,
-	0xd5, 0xe7, 0x77, 0xf1, 0xf9, 0xde, 0x04, 0xf6, 0xd0, 0x58, 0x82, 0x5f,
-	0xd2, 0xa1, 0x34, 0xef, 0xcd, 0x42, 0x91, 0x65, 0xeb, 0xcb, 0xcc, 0x47,
-	0x57, 0xf4, 0xb8, 0x3e, 0xd4, 0xec, 0x88, 0x3d, 0x31, 0x78, 0xcc, 0xb9,
-	0xcc, 0x04, 0x8f, 0x1b, 0x24, 0xff, 0xcb, 0x6c, 0x8b, 0xae, 0x68, 0x5c,
-	0xd5, 0xf9, 0xf6, 0xdf, 0xe8, 0x93, 0x39, 0x55, 0xdf, 0xdd, 0x23, 0xe1,
-	0xe7, 0x08, 0x9e, 0x72, 0x9e, 0xe1, 0xf2, 0xbc, 0xc0, 0x43, 0x7b, 0xda,
-	0x2a, 0x3f, 0xbf, 0x13, 0x78, 0xd5, 0x8a, 0xbc, 0xd9, 0xc0, 0x12, 0xf3,
-	0xc5, 0x19, 0xc7, 0x4c, 0x97, 0x73, 0xd5, 0x1e, 0x1f, 0x90, 0xd7, 0xbf,
-	0xd9, 0x27, 0xfb, 0x83, 0x7e, 0x6b, 0x40, 0xf7, 0x48, 0x94, 0x32, 0x07,
-	0xf9, 0xcb, 0x3e, 0x01, 0x1b, 0xff, 0x32, 0xf8, 0xa5, 0xc1, 0xdf, 0x79,
-	0x3d, 0x09, 0xcc, 0xf1, 0x4a, 0x9f, 0xee, 0x17, 0x23, 0xd7, 0x15, 0xe7,
-	0xf9, 0x46, 0x78, 0x5d, 0xfa, 0xfc, 0x0c, 0x1f, 0x7b, 0xed, 0x2f, 0xee,
-	0xd5, 0x96, 0x90, 0xfd, 0xc5, 0xda, 0x12, 0xc9, 0x09, 0xb9, 0xcf, 0x15,
-	0x9f, 0x6e, 0xa8, 0xec, 0xd3, 0x3d, 0x9f, 0xb9, 0xd5, 0x07, 0xff, 0x86,
-	0xb1, 0xc4, 0xfb, 0x1d, 0x7c, 0x9e, 0xc7, 0xa2, 0x56, 0x21, 0xcd, 0x9f,
-	0x1d, 0x2a, 0xaf, 0xa7, 0x1e, 0x57, 0x64, 0x9e, 0x84, 0x96, 0x5b, 0xb8,
-	0xf6, 0x43, 0xbe, 0x87, 0x94, 0x5d, 0x8d, 0x9f, 0x43, 0x75, 0x79, 0x30,
-	0xf5, 0x38, 0xb6, 0x99, 0x1f, 0x56, 0xc4, 0x13, 0x3d, 0xf0, 0x6c, 0xb3,
-	0x7e, 0x06, 0xd7, 0x84, 0x1f, 0x2d, 0x56, 0x47, 0xaf, 0xa0, 0xe3, 0x00,
-	0xfd, 0xce, 0x62, 0x8a, 0x76, 0xf1, 0x5e, 0xfd, 0xa6, 0xf1, 0x00, 0xe2,
-	0xed, 0x24, 0x73, 0x9e, 0x18, 0xc6, 0x19, 0x67, 0xe2, 0x94, 0x11, 0x01,
-	0xbf, 0x2c, 0x05, 0x9c, 0x0e, 0x6a, 0x66, 0x5a, 0xfd, 0x65, 0x1a, 0x65,
-	0xfb, 0x0f, 0x34, 0xeb, 0x84, 0xe2, 0x04, 0x7a, 0xb3, 0xcd, 0x43, 0xac,
-	0x13, 0xc7, 0x8a, 0xc0, 0x67, 0x83, 0x3e, 0x9f, 0x23, 0xfa, 0x5c, 0x6e,
-	0xd4, 0xfc, 0x26, 0x39, 0x56, 0xe5, 0x77, 0xdb, 0x8c, 0xf2, 0x3c, 0xe2,
-	0xc5, 0x2f, 0xd3, 0xfb, 0xa2, 0xcf, 0x09, 0xe0, 0xa8, 0xf7, 0xfd, 0x4b,
-	0x74, 0x32, 0x81, 0x79, 0x6f, 0x9f, 0x3e, 0x8f, 0xef, 0x88, 0x3e, 0xdb,
-	0x3c, 0xe8, 0xf3, 0xc5, 0x7e, 0x89, 0x37, 0x25, 0xc6, 0xd1, 0x36, 0x9a,
-	0xcb, 0x22, 0x07, 0xec, 0xd3, 0xe8, 0x3b, 0x95, 0x4d, 0x32, 0x5f, 0x4a,
-	0x56, 0xf8, 0xd2, 0x85, 0x28, 0x1b, 0xc3, 0x4c, 0xe3, 0xe8, 0xcb, 0xa6,
-	0xf2, 0x7e, 0xb0, 0x8e, 0x01, 0x1a, 0x5d, 0x6e, 0xe7, 0x6b, 0x69, 0x3d,
-	0x3a, 0x15, 0x51, 0xb5, 0xfe, 0xb6, 0x15, 0x63, 0xfe, 0x78, 0x9e, 0x69,
-	0x39, 0x9d, 0xbd, 0x97, 0x0a, 0xc1, 0x21, 0x1a, 0x59, 0xd6, 0xfd, 0x4d,
-	0x44, 0xce, 0xc6, 0xa0, 0xe4, 0x49, 0x7a, 0xdd, 0x9f, 0x10, 0xbe, 0x0b,
-	0xeb, 0xd2, 0xc7, 0xb5, 0xee, 0xf6, 0x2d, 0xf8, 0xd2, 0x25, 0x45, 0xb3,
-	0xa5, 0xcb, 0xd1, 0x30, 0xa5, 0xa2, 0x53, 0xaf, 0xf4, 0x03, 0xff, 0x47,
-	0x2e, 0xc1, 0x0f, 0x07, 0x1e, 0x6d, 0x51, 0x22, 0x53, 0x0b, 0x8b, 0x21,
-	0x5e, 0x37, 0x7e, 0x2f, 0x7d, 0x30, 0x17, 0x7e, 0x40, 0xc8, 0xfe, 0xd1,
-	0x4b, 0x3c, 0x4e, 0xca, 0x26, 0xc5, 0x37, 0xbc, 0xf0, 0x50, 0xf7, 0xc5,
-	0xd4, 0xb8, 0x28, 0x73, 0x3d, 0x59, 0x7f, 0x33, 0x13, 0xfe, 0x5a, 0x9c,
-	0xbc, 0xe6, 0x3b, 0xba, 0x68, 0xd1, 0xb1, 0x8c, 0xfd, 0xf5, 0x14, 0x4d,
-	0x31, 0x5d, 0xbb, 0xe5, 0x05, 0x8f, 0x27, 0xe0, 0xd9, 0x34, 0xd3, 0x3e,
-	0xdb, 0xcd, 0x59, 0x4b, 0xe6, 0xdd, 0x89, 0xde, 0x73, 0x38, 0x46, 0xdd,
-	0xf1, 0x5f, 0xf5, 0x6b, 0x79, 0x90, 0xcc, 0xa2, 0x8e, 0x90, 0x3f, 0xf3,
-	0x3c, 0x1e, 0xb9, 0xff, 0x39, 0xdc, 0x07, 0xf2, 0x0e, 0x73, 0xe7, 0xe3,
-	0x55, 0xb9, 0xaf, 0x23, 0x7c, 0x6f, 0xd4, 0xdd, 0x1f, 0x2b, 0x4e, 0xf2,
-	0xfe, 0x76, 0x09, 0xde, 0x2c, 0xf7, 0x73, 0x9a, 0xce, 0x79, 0xf2, 0x15,
-	0xb9, 0x2f, 0x49, 0x17, 0x7d, 0x27, 0x05, 0x7d, 0x4f, 0x8b, 0xfd, 0x48,
-	0xe6, 0x0c, 0xd6, 0xd7, 0xb4, 0xef, 0x81, 0xed, 0xec, 0x5c, 0x40, 0xe7,
-	0x06, 0xf2, 0xf7, 0x0f, 0xfb, 0x45, 0x5e, 0x22, 0xec, 0xef, 0x1c, 0x3e,
-	0xa7, 0xe9, 0x79, 0x96, 0xeb, 0x2f, 0x64, 0x5a, 0xe8, 0x6a, 0xb6, 0x85,
-	0xde, 0xc9, 0x0e, 0xd1, 0x95, 0xc5, 0x6e, 0x3a, 0xc7, 0x3a, 0xf3, 0x39,
-	0x27, 0x60, 0xa5, 0xa9, 0x1b, 0xf1, 0x45, 0xe4, 0x0c, 0x31, 0xdd, 0x61,
-	0x3c, 0xf4, 0xbf, 0xe8, 0x5e, 0xc6, 0x39, 0xd6, 0xbd, 0x5b, 0xe9, 0x3d,
-	0x7e, 0x66, 0x3a, 0xa3, 0x73, 0x1d, 0xe0, 0x93, 0x1f, 0x2b, 0xeb, 0xaf,
-	0x5b, 0xe3, 0x88, 0xb9, 0x05, 0x8e, 0x4c, 0x8b, 0xf8, 0xd6, 0xc2, 0x22,
-	0xff, 0xbe, 0x08, 0xff, 0x39, 0xc3, 0x9b, 0xf9, 0xf3, 0x93, 0x01, 0x8c,
-	0xc7, 0x39, 0x47, 0xe6, 0x4a, 0x8a, 0xb5, 0x85, 0xf8, 0xd8, 0x27, 0x6a,
-	0xa4, 0x25, 0x1c, 0x5a, 0x79, 0x7d, 0x3e, 0x31, 0x3e, 0xb9, 0xda, 0x4a,
-	0xf3, 0x39, 0xd6, 0x41, 0x72, 0x7e, 0xb6, 0x61, 0x30, 0xf6, 0xef, 0x54,
-	0x6f, 0x61, 0xdc, 0xbf, 0x8b, 0xd2, 0x62, 0x1c, 0x7f, 0xae, 0x76, 0xd1,
-	0x42, 0xae, 0x43, 0x1d, 0xdf, 0x2b, 0x72, 0xdc, 0x65, 0x1f, 0x23, 0xfc,
-	0xb6, 0x19, 0x7f, 0x7b, 0x97, 0x71, 0x0a, 0x32, 0x55, 0xda, 0xa5, 0xe0,
-	0x35, 0x97, 0xeb, 0x7a, 0x22, 0x03, 0xe7, 0xa6, 0xe8, 0x25, 0x96, 0xb7,
-	0x23, 0x2f, 0xc3, 0x7f, 0xfc, 0x38, 0xf0, 0x26, 0x9f, 0xa2, 0x41, 0x3e,
-	0x46, 0x5f, 0x24, 0xbf, 0xa8, 0x73, 0x8a, 0x05, 0x27, 0x44, 0x6d, 0x88,
-	0xa4, 0xd1, 0x59, 0xd1, 0x8b, 0xee, 0x2d, 0xc1, 0x9b, 0xec, 0x94, 0x65,
-	0x40, 0x1f, 0x81, 0x0f, 0x46, 0xe6, 0x60, 0x1d, 0x77, 0x7a, 0xde, 0xed,
-	0x9b, 0x19, 0xa7, 0x48, 0x3f, 0xf0, 0x5e, 0xd2, 0xac, 0xea, 0x2f, 0x20,
-	0xf8, 0xbd, 0xb9, 0x4f, 0xd7, 0x4b, 0xea, 0x63, 0x2d, 0x2b, 0xf4, 0x71,
-	0x47, 0xcd, 0xef, 0x66, 0xcd, 0xef, 0xe5, 0x7c, 0x39, 0x96, 0x79, 0x2c,
-	0xe7, 0x49, 0xf6, 0x28, 0x4a, 0x2e, 0x4b, 0xfc, 0x33, 0xf7, 0x8d, 0x99,
-	0x8f, 0x2a, 0x1d, 0x3c, 0xb9, 0x36, 0x1a, 0xea, 0x31, 0x26, 0x8c, 0xe4,
-	0xe4, 0x3f, 0x96, 0x22, 0x09, 0xe8, 0x45, 0x4f, 0xee, 0x51, 0xf9, 0xa7,
-	0x3c, 0xaf, 0x54, 0x18, 0xaa, 0xdb, 0xec, 0x5a, 0x07, 0xad, 0x8b, 0x9e,
-	0x5c, 0x42, 0xc7, 0xe0, 0xeb, 0x71, 0x9f, 0x94, 0xd9, 0x44, 0xe8, 0x73,
-	0x0e, 0x1a, 0xdf, 0x1f, 0xba, 0xc4, 0xfb, 0x19, 0x5f, 0xfb, 0x69, 0xe9,
-	0xa4, 0xe8, 0x71, 0x83, 0xb1, 0x5d, 0x34, 0x27, 0x74, 0x7e, 0xd6, 0x5f,
-	0xaa, 0xec, 0xaa, 0x29, 0xcc, 0x33, 0x85, 0xd8, 0x8a, 0xe1, 0xfc, 0xbe,
-	0x2f, 0x99, 0x97, 0xb1, 0xf2, 0x78, 0x4d, 0xac, 0x7c, 0x56, 0xc4, 0xca,
-	0x11, 0x27, 0x07, 0x5c, 0x01, 0x4b, 0xaf, 0x9c, 0x16, 0xec, 0x63, 0x98,
-	0x90, 0x1b, 0x7e, 0xee, 0xa2, 0xe0, 0x37, 0xe1, 0x98, 0x5f, 0xe6, 0x57,
-	0xc7, 0x79, 0xc6, 0x06, 0x5d, 0x60, 0x7c, 0xb0, 0x27, 0x36, 0x58, 0x97,
-	0x58, 0xc9, 0x7e, 0x99, 0xae, 0xe4, 0x9b, 0x58, 0xd7, 0x5b, 0xa0, 0x8d,
-	0x3c, 0xb1, 0x4e, 0xd8, 0x4d, 0x0b, 0x61, 0xc6, 0xb1, 0x89, 0x36, 0xde,
-	0x4f, 0xd6, 0x6b, 0x27, 0x98, 0xee, 0x78, 0xee, 0x2b, 0xb9, 0xd2, 0x8f,
-	0xd2, 0xe1, 0x88, 0x15, 0x9d, 0xea, 0x60, 0xbb, 0xc5, 0xe4, 0x7f, 0x87,
-	0xff, 0x77, 0x85, 0x00, 0x93, 0xc2, 0x2a, 0x7e, 0x67, 0x9d, 0x27, 0x53,
-	0xfa, 0xd1, 0x1c, 0x8f, 0x99, 0x9b, 0x82, 0xfd, 0x03, 0x3b, 0xcf, 0xe1,
-	0x7f, 0x39, 0x66, 0x65, 0x95, 0xf1, 0xfb, 0x62, 0x2a, 0x64, 0x08, 0xde,
-	0xbe, 0xce, 0x3c, 0xfe, 0x02, 0xcd, 0xf1, 0x1c, 0xae, 0x10, 0xae, 0xb5,
-	0x28, 0x19, 0xde, 0xc7, 0x78, 0xdf, 0xcd, 0x9f, 0xa8, 0xbf, 0x6a, 0xa7,
-	0x85, 0xc9, 0x31, 0x55, 0x7f, 0xf5, 0xbd, 0x06, 0xf5, 0x57, 0xb8, 0x8e,
-	0xe5, 0xfe, 0x62, 0xe9, 0xe6, 0x5c, 0xd8, 0xfd, 0x3c, 0x32, 0x92, 0xe1,
-	0x4e, 0xa1, 0x23, 0xad, 0xac, 0xfa, 0xf8, 0xd9, 0x11, 0x2b, 0x39, 0xc5,
-	0x73, 0xcc, 0xb9, 0xe7, 0x5d, 0xba, 0x19, 0x0b, 0x63, 0x9c, 0xbf, 0x66,
-	0x1c, 0xdb, 0xca, 0x53, 0x72, 0x3d, 0x85, 0x5c, 0xe9, 0xe7, 0xd1, 0xb0,
-	0x5e, 0x9f, 0xfb, 0x5a, 0xac, 0x03, 0xf4, 0xc4, 0x9f, 0x2b, 0x5d, 0xbe,
-	0x2b, 0x59, 0xd8, 0xdf, 0x06, 0xe3, 0x39, 0x66, 0x34, 0x44, 0xa9, 0x15,
-	0xa6, 0xef, 0x8b, 0x1d, 0xbe, 0x8d, 0xec, 0x95, 0x52, 0xb2, 0x2a, 0x97,
-	0xa5, 0xda, 0xef, 0x2e, 0x6d, 0xae, 0x21, 0x72, 0x96, 0x20, 0x33, 0x21,
-	0x2f, 0x53, 0x25, 0xbf, 0x03, 0xfd, 0x0e, 0xb6, 0xd0, 0x59, 0xe6, 0x57,
-	0x32, 0x1f, 0x89, 0x79, 0x27, 0xf3, 0x2c, 0x49, 0x2f, 0xf1, 0xaa, 0xd7,
-	0x0d, 0x48, 0x9c, 0x1d, 0xa9, 0xe4, 0x41, 0xba, 0xe2, 0xe9, 0x01, 0x57,
-	0x3c, 0xdd, 0x74, 0xe5, 0x41, 0x06, 0x85, 0x3e, 0x56, 0xd1, 0xa1, 0x82,
-	0x4a, 0x87, 0x82, 0xae, 0x25, 0x79, 0x59, 0xa1, 0xcc, 0xcb, 0x76, 0x6f,
-	0xc1, 0xcb, 0xbc, 0x6c, 0xd3, 0x75, 0xc5, 0x37, 0xec, 0x30, 0xe4, 0xfc,
-	0xe5, 0xe2, 0x34, 0xbd, 0xcd, 0x3c, 0xe2, 0xad, 0x62, 0x98, 0xf9, 0xc6,
-	0x24, 0xf3, 0x8d, 0x09, 0xe6, 0x1b, 0x0e, 0xc3, 0xc0, 0xe2, 0xb5, 0x5f,
-	0xf3, 0x5d, 0x59, 0x84, 0xbc, 0x98, 0xa2, 0xe7, 0x8b, 0xe0, 0xc1, 0x93,
-	0xac, 0xf3, 0x5c, 0xf3, 0x6d, 0x2c, 0x76, 0x31, 0xbe, 0x4a, 0x3d, 0xa7,
-	0xda, 0x8e, 0x41, 0xaf, 0x15, 0xf8, 0x87, 0xaf, 0x82, 0xcf, 0xbc, 0x91,
-	0xa2, 0x4e, 0x86, 0x3d, 0xe0, 0xbc, 0x8e, 0xde, 0x14, 0xaf, 0x81, 0x96,
-	0xd1, 0x13, 0xf8, 0xbb, 0xe3, 0x53, 0x3c, 0xf7, 0x4e, 0xdf, 0x02, 0xef,
-	0xcb, 0xd3, 0xe1, 0x94, 0xd9, 0xcb, 0x38, 0x7f, 0xac, 0x82, 0xf3, 0xa9,
-	0x34, 0xaf, 0xa0, 0x67, 0xb9, 0x9b, 0xc6, 0x0e, 0x44, 0xf7, 0xf6, 0x30,
-	0x9d, 0x22, 0x37, 0xa2, 0xd2, 0xa7, 0xc7, 0x4f, 0x27, 0x83, 0x6d, 0xaa,
-	0xbf, 0x8f, 0xc5, 0xf2, 0xf1, 0x03, 0xbe, 0xcf, 0x2d, 0x5f, 0x3a, 0xfb,
-	0x2a, 0x3f, 0x03, 0xc7, 0x5f, 0x85, 0xff, 0x93, 0xed, 0x83, 0x56, 0xe1,
-	0x3f, 0x2a, 0x88, 0xb1, 0x38, 0xb6, 0x27, 0x98, 0x97, 0x85, 0xd7, 0x0d,
-	0x7b, 0x3a, 0x62, 0x30, 0xd1, 0x75, 0x99, 0xbc, 0xde, 0xd2, 0xa0, 0x8c,
-	0xc1, 0xed, 0xdd, 0x2b, 0xf9, 0x06, 0xe3, 0x66, 0x30, 0x22, 0x6c, 0xb4,
-	0xa6, 0x25, 0x29, 0x27, 0x0b, 0xbc, 0xcf, 0x2b, 0xe1, 0x09, 0xde, 0xe7,
-	0x0e, 0x25, 0x23, 0x53, 0xfc, 0xbb, 0x90, 0xbf, 0x2c, 0x2b, 0x87, 0xd0,
-	0xb3, 0xda, 0x14, 0xfd, 0x20, 0x66, 0xd1, 0x6f, 0xa7, 0x83, 0xef, 0x6b,
-	0x33, 0xd6, 0x82, 0x4f, 0x7c, 0xe0, 0x4b, 0x66, 0xf1, 0x5c, 0xe0, 0x21,
-	0x7f, 0xcf, 0x4f, 0xd1, 0x85, 0x8c, 0x9e, 0xc3, 0x80, 0x61, 0xbc, 0x84,
-	0x79, 0xf8, 0x68, 0xb7, 0xf3, 0x43, 0x86, 0x17, 0x1f, 0xff, 0x71, 0xed,
-	0x9c, 0x86, 0xd5, 0x9c, 0xd0, 0xd3, 0xb2, 0x05, 0x3d, 0x7c, 0x08, 0xbd,
-	0x8f, 0x0a, 0xa2, 0xe7, 0x64, 0xb3, 0xb0, 0x4d, 0x0b, 0xc2, 0xc6, 0x28,
-	0x85, 0x2a, 0x7d, 0x30, 0xef, 0xa9, 0x39, 0xf7, 0x13, 0x5f, 0x7a, 0xf1,
-	0xa0, 0xd0, 0xc5, 0x46, 0x0e, 0xec, 0x55, 0xf5, 0xa7, 0x5d, 0xe2, 0xbe,
-	0xc6, 0x32, 0x7e, 0x7b, 0x50, 0xfd, 0xf6, 0x49, 0xa1, 0x03, 0x23, 0x2f,
-	0x2e, 0xb0, 0x24, 0xf0, 0x9c, 0xf7, 0xd7, 0x99, 0x60, 0x3c, 0x0f, 0xad,
-	0xc0, 0x77, 0x2f, 0xe0, 0xa9, 0xe1, 0x01, 0x58, 0x00, 0xf7, 0x3b, 0x14,
-	0xde, 0xdb, 0x56, 0xdc, 0xaf, 0xd7, 0xdd, 0x08, 0xce, 0xac, 0xd3, 0x64,
-	0xb0, 0x56, 0xac, 0x69, 0x8f, 0x2f, 0x92, 0xb7, 0x8c, 0xf4, 0x22, 0x6c,
-	0x1a, 0xd4, 0xb5, 0xdc, 0x85, 0xbc, 0x29, 0x9e, 0xc3, 0x1e, 0x8a, 0x24,
-	0x30, 0x2f, 0x8c, 0xd3, 0x30, 0xf8, 0xb7, 0x1a, 0x58, 0xb8, 0xaf, 0xeb,
-	0x56, 0xd7, 0xb5, 0x8a, 0xbd, 0x20, 0x03, 0xcf, 0xd1, 0xcf, 0xc6, 0x73,
-	0xf1, 0x7c, 0x5c, 0x87, 0xfb, 0xc9, 0xfb, 0xf6, 0x31, 0x7f, 0x8e, 0x4e,
-	0xc9, 0x7b, 0x19, 0x97, 0xe4, 0x6f, 0x7d, 0x8e, 0xf7, 0x7c, 0xe5, 0xfe,
-	0xf9, 0x54, 0xbf, 0x1e, 0xec, 0x5f, 0x37, 0xe5, 0x85, 0x8f, 0x13, 0xbf,
-	0x75, 0x8a, 0xdf, 0xa2, 0x4e, 0xa7, 0xd8, 0xd7, 0xf3, 0x7c, 0x3c, 0x9f,
-	0xed, 0xf2, 0xc1, 0x36, 0x4f, 0x27, 0x3a, 0x7d, 0xf9, 0x3c, 0xd6, 0xdb,
-	0xe9, 0x8b, 0x33, 0xee, 0xc7, 0xb2, 0xf1, 0xd2, 0x82, 0xe0, 0x31, 0xac,
-	0xd3, 0xf6, 0xda, 0xe6, 0x49, 0xe3, 0x4f, 0x86, 0x64, 0x6f, 0x5b, 0x7c,
-	0x67, 0xfa, 0xcb, 0x30, 0xfd, 0x65, 0x98, 0xfe, 0x32, 0x4c, 0x7f, 0x19,
-	0xa6, 0x3f, 0xb6, 0x4b, 0xdf, 0x64, 0x99, 0xf1, 0x6d, 0x96, 0x19, 0x92,
-	0x66, 0x23, 0xca, 0x8f, 0xa9, 0x69, 0xb6, 0xb6, 0x3e, 0x53, 0xd3, 0x28,
-	0xe4, 0x34, 0xf9, 0x0e, 0x8f, 0x57, 0xd3, 0xea, 0x55, 0xa6, 0xd5, 0xa6,
-	0x99, 0x7e, 0xba, 0x91, 0xc3, 0x9e, 0xd9, 0xd6, 0x79, 0xe6, 0xd1, 0x71,
-	0x3f, 0x74, 0xaa, 0x00, 0xd3, 0x13, 0x74, 0x4a, 0x9b, 0xe1, 0xde, 0x4f,
-	0x37, 0x99, 0x4f, 0xdf, 0xc8, 0x81, 0x76, 0xef, 0x52, 0xc7, 0x19, 0xa6,
-	0x5d, 0xc8, 0xb9, 0x25, 0xdf, 0xd5, 0xac, 0xc1, 0xba, 0x57, 0xc0, 0x4c,
-	0x12, 0xf8, 0xa8, 0xd0, 0xc7, 0x78, 0xdf, 0xd7, 0x99, 0xdf, 0xc3, 0x57,
-	0x87, 0xbe, 0x5f, 0x79, 0x1f, 0xcb, 0x89, 0xd0, 0x15, 0xe6, 0xa3, 0xa7,
-	0x73, 0x4b, 0x4c, 0xef, 0xbd, 0xf4, 0x85, 0x1c, 0xe4, 0x31, 0x60, 0xc4,
-	0xc7, 0x79, 0x12, 0x3e, 0x30, 0x63, 0x06, 0x6b, 0x1f, 0x4b, 0x19, 0x02,
-	0x4f, 0x9e, 0x01, 0x1c, 0x18, 0xf6, 0x67, 0xf6, 0xa2, 0x67, 0x7d, 0xc4,
-	0x68, 0x56, 0x3e, 0x45, 0x7c, 0xc7, 0x78, 0x8c, 0x05, 0xdc, 0x70, 0xdc,
-	0x28, 0xfe, 0x88, 0xf7, 0x42, 0x84, 0x19, 0x1e, 0xb5, 0x7c, 0xeb, 0x02,
-	0x7a, 0x91, 0x02, 0x5e, 0xd3, 0x51, 0x3f, 0x6a, 0xc5, 0xe9, 0x39, 0xbc,
-	0xff, 0xe0, 0x85, 0x22, 0xe6, 0xbd, 0x48, 0x0b, 0x41, 0xf0, 0x21, 0x3b,
-	0x7c, 0x9d, 0x24, 0xec, 0x5a, 0x59, 0xbf, 0xfc, 0xbc, 0x37, 0x6f, 0xb3,
-	0xa2, 0x42, 0x1f, 0x6e, 0x61, 0xfb, 0x06, 0xb0, 0x79, 0x8b, 0x71, 0x2d,
-	0x0c, 0x9b, 0x5f, 0xf1, 0xb5, 0x37, 0x99, 0xe7, 0x60, 0xcf, 0x3a, 0x85,
-	0x8c, 0xf1, 0xe2, 0x65, 0x1b, 0x8a, 0x97, 0x39, 0x2e, 0x5e, 0x96, 0x2e,
-	0xf3, 0x32, 0xc6, 0x09, 0xc1, 0xc3, 0xc0, 0xa3, 0x66, 0x59, 0x4f, 0x94,
-	0xdf, 0xa1, 0xff, 0xed, 0x16, 0x3c, 0x8b, 0x79, 0x3d, 0xdb, 0x0d, 0x85,
-	0x62, 0xca, 0x77, 0x48, 0xf0, 0x0e, 0x8d, 0xd7, 0xff, 0xa3, 0xe8, 0xa1,
-	0x55, 0xf0, 0x81, 0xf4, 0x2c, 0xf8, 0x95, 0xd7, 0xf8, 0xff, 0x02, 0x6c,
-	0x79, 0xbc, 0x13, 0x7a, 0x8d, 0xf9, 0x58, 0x21, 0x0c, 0x9b, 0xb5, 0x43,
-	0xd9, 0x36, 0xe8, 0xbb, 0xb5, 0x07, 0xb9, 0x96, 0x56, 0xb4, 0xcc, 0xc7,
-	0x76, 0x2b, 0xbf, 0x05, 0xfc, 0x8c, 0xd8, 0xeb, 0x3a, 0x5d, 0xc0, 0x82,
-	0x2e, 0xc0, 0x63, 0x03, 0x0c, 0x1f, 0xd1, 0x1b, 0x9c, 0xe8, 0x16, 0xc3,
-	0x01, 0xfb, 0x7c, 0x0b, 0xfb, 0xcc, 0xba, 0x2c, 0x05, 0xe6, 0xa6, 0x02,
-	0x03, 0x98, 0xdf, 0xc2, 0x6a, 0x85, 0x1f, 0x9e, 0xcf, 0x0c, 0x18, 0x85,
-	0xac, 0x9c, 0xe3, 0xca, 0xb8, 0xe4, 0x79, 0x85, 0x3c, 0x7a, 0x7b, 0x89,
-	0xb9, 0xf2, 0x1c, 0xf5, 0xfa, 0x04, 0xff, 0x52, 0x74, 0xbf, 0x1d, 0x5a,
-	0x4b, 0x30, 0x5d, 0x61, 0x4f, 0x52, 0x2e, 0x9c, 0x79, 0x94, 0x9f, 0x8f,
-	0x73, 0x8d, 0xd7, 0x71, 0xb3, 0xbc, 0x8e, 0x08, 0xaf, 0x03, 0x63, 0x6f,
-	0xf9, 0x6e, 0xa8, 0x75, 0xdc, 0x28, 0xaf, 0x63, 0x56, 0xad, 0x83, 0xd2,
-	0xc6, 0xcc, 0x6e, 0xa5, 0xc7, 0x6f, 0x79, 0xcf, 0xd6, 0x28, 0xeb, 0x27,
-	0xe9, 0x55, 0xc0, 0xf3, 0x1e, 0x85, 0x2f, 0x6e, 0x7f, 0xa8, 0x7b, 0x6e,
-	0xf6, 0xc4, 0x75, 0xfa, 0x5d, 0xba, 0x29, 0xf4, 0x93, 0x61, 0xd6, 0x4f,
-	0x70, 0x9e, 0x16, 0xc0, 0x87, 0xd3, 0x41, 0xf4, 0x9b, 0x1d, 0x64, 0x98,
-	0xb1, 0x5d, 0x35, 0xc5, 0x9f, 0xc2, 0x4f, 0x86, 0xfb, 0xe8, 0xeb, 0xbf,
-	0x48, 0x37, 0x17, 0xc1, 0xab, 0xa1, 0x8f, 0xca, 0x9e, 0xb4, 0x37, 0xd7,
-	0xa4, 0x9f, 0x36, 0xee, 0xe9, 0xa7, 0x85, 0x8f, 0x36, 0x0c, 0x7d, 0xdd,
-	0x84, 0x3f, 0x37, 0x26, 0xde, 0x67, 0xc1, 0xc7, 0x45, 0xdc, 0xcb, 0x8b,
-	0xef, 0x4c, 0xbb, 0x72, 0xdc, 0x90, 0x73, 0x92, 0x62, 0x3e, 0xe2, 0x98,
-	0x4d, 0x86, 0xac, 0x9d, 0xb9, 0x5c, 0xd4, 0x3a, 0x51, 0x9c, 0xf7, 0xc8,
-	0x09, 0x1b, 0x46, 0x44, 0xf8, 0x0c, 0x5a, 0x9d, 0x0e, 0x6a, 0x61, 0x39,
-	0x79, 0x8a, 0xd0, 0x13, 0xcd, 0xb6, 0xe0, 0xcb, 0xbf, 0xc0, 0xb8, 0xb7,
-	0x10, 0xb6, 0x43, 0x9f, 0x13, 0xf6, 0x25, 0xe4, 0x07, 0xde, 0xa7, 0x02,
-	0x18, 0x63, 0x0e, 0xfc, 0x7d, 0x15, 0xfd, 0x30, 0xc3, 0xbc, 0x7e, 0xf8,
-	0x81, 0x47, 0xad, 0x77, 0x58, 0xee, 0x5c, 0x10, 0xfe, 0x95, 0xb3, 0x94,
-	0x66, 0x3a, 0x3c, 0x2c, 0xe8, 0xd0, 0x18, 0x66, 0x6a, 0x61, 0xfa, 0x41,
-	0x8e, 0xc1, 0x98, 0xe8, 0xbf, 0x23, 0x6d, 0x16, 0x5e, 0xe5, 0x9a, 0xea,
-	0x6b, 0x90, 0x00, 0x6f, 0xd8, 0xbe, 0x6f, 0x21, 0xf1, 0x91, 0x7d, 0x2a,
-	0x6e, 0x5d, 0xab, 0xd6, 0x87, 0x0d, 0xfb, 0xcc, 0x12, 0x7d, 0x1f, 0x01,
-	0x3b, 0xe1, 0x17, 0x34, 0x26, 0x19, 0x6e, 0xfa, 0xdd, 0x35, 0x6e, 0xfb,
-	0xff, 0x29, 0x51, 0x9f, 0xff, 0x46, 0x51, 0xca, 0xd8, 0x34, 0xdb, 0xe6,
-	0x0b, 0x07, 0xdc, 0x3a, 0x87, 0x9d, 0x8d, 0x09, 0x9f, 0xcc, 0x00, 0x45,
-	0x97, 0x27, 0xe9, 0xb1, 0x0c, 0x78, 0x14, 0x5d, 0x8f, 0x3a, 0x78, 0xc3,
-	0x06, 0x68, 0x79, 0x92, 0xe2, 0x45, 0xc0, 0xc8, 0x47, 0x0b, 0x2c, 0x05,
-	0xd2, 0x59, 0xc4, 0xee, 0xf9, 0x7b, 0x1e, 0xef, 0x57, 0xf9, 0x15, 0xe5,
-	0xf7, 0x1e, 0xa2, 0xd8, 0x32, 0xa5, 0x92, 0xe1, 0x87, 0x45, 0xcf, 0xea,
-	0x64, 0x78, 0x5c, 0xf9, 0x68, 0x42, 0x7c, 0x1e, 0x7e, 0x2f, 0x8b, 0x1e,
-	0xcd, 0xd8, 0xa9, 0x24, 0x49, 0xdf, 0x03, 0xf1, 0x1c, 0x0c, 0x96, 0xad,
-	0xbb, 0x99, 0x57, 0x1c, 0x17, 0xfe, 0x07, 0xd6, 0x44, 0x16, 0x31, 0x1e,
-	0xbe, 0x83, 0x5e, 0x82, 0xbd, 0x95, 0xcc, 0x3e, 0xa0, 0xc6, 0x96, 0xc8,
-	0x64, 0x5c, 0x30, 0x7f, 0xc9, 0x49, 0x85, 0x8d, 0xca, 0xf5, 0xf0, 0x5d,
-	0x1c, 0x17, 0xfa, 0xe1, 0x30, 0xdb, 0x30, 0x62, 0x5c, 0x69, 0x4e, 0xf8,
-	0x21, 0xf8, 0x38, 0xff, 0xd3, 0x01, 0xfd, 0x6e, 0x03, 0x9c, 0x97, 0xfe,
-	0x09, 0xbe, 0x67, 0x9e, 0xe7, 0x51, 0x95, 0x17, 0x3f, 0x44, 0x91, 0x1d,
-	0xf8, 0x8b, 0x66, 0xef, 0xa8, 0xbf, 0x88, 0x61, 0xcd, 0xb2, 0xe5, 0x32,
-	0xd3, 0xc6, 0xdb, 0x5b, 0xda, 0x71, 0xef, 0x6b, 0x19, 0xcd, 0xb0, 0x32,
-	0xc5, 0xfb, 0x2f, 0xd0, 0xeb, 0x73, 0xa1, 0xf8, 0x29, 0xbc, 0x47, 0xc6,
-	0x97, 0x10, 0x3a, 0x6f, 0x88, 0x75, 0x17, 0xe8, 0x30, 0xa3, 0x22, 0xbe,
-	0x15, 0x79, 0xc2, 0x32, 0x16, 0xd6, 0xfa, 0xc9, 0x0f, 0xbf, 0x9a, 0xa3,
-	0x73, 0x22, 0x5a, 0x45, 0xfe, 0xba, 0x8c, 0x2b, 0x42, 0xfe, 0x82, 0x07,
-	0xfe, 0xc4, 0x97, 0x5c, 0xf3, 0xf7, 0xe9, 0x7c, 0xb7, 0x48, 0xb0, 0x9c,
-	0x4f, 0xa3, 0x78, 0x8a, 0xc6, 0x3d, 0x1d, 0xb3, 0x70, 0xbf, 0xd7, 0x0a,
-	0xb4, 0xeb, 0xd6, 0x19, 0xe0, 0x67, 0x12, 0x7b, 0x74, 0x01, 0x71, 0x5c,
-	0xa3, 0x2a, 0x1e, 0xd1, 0xc2, 0xfb, 0x04, 0x3b, 0x0f, 0xfe, 0xbb, 0xcf,
-	0xf2, 0x27, 0xe2, 0x0a, 0x27, 0x07, 0xa1, 0x27, 0xf5, 0x38, 0x8c, 0x33,
-	0x53, 0x38, 0xee, 0x67, 0xbb, 0x4b, 0xeb, 0xb5, 0xd2, 0xa7, 0xc4, 0xb6,
-	0x98, 0xda, 0x2f, 0xf8, 0x93, 0x46, 0x54, 0xbf, 0x01, 0x9b, 0xac, 0x5e,
-	0xc0, 0xe9, 0xe3, 0xa2, 0xc7, 0xad, 0x62, 0x10, 0xdb, 0xc9, 0x59, 0xc2,
-	0x3b, 0xb7, 0xd0, 0x77, 0xf3, 0x6e, 0xc0, 0x9e, 0xf7, 0xc8, 0x1d, 0xa3,
-	0xf8, 0x94, 0x7a, 0xff, 0xcf, 0x9d, 0xda, 0xb7, 0x5d, 0x1e, 0xfb, 0xf6,
-	0xbd, 0x41, 0x19, 0x03, 0xbb, 0x4b, 0x8d, 0xf1, 0xca, 0x53, 0xfd, 0xfb,
-	0xa7, 0xe1, 0x4f, 0xaa, 0xd4, 0x51, 0x5c, 0x13, 0x7c, 0xa5, 0xde, 0xa7,
-	0x1d, 0x62, 0x7e, 0x2a, 0xe9, 0xf8, 0xb8, 0x07, 0x1d, 0xf7, 0xce, 0x40,
-	0x2f, 0xb9, 0x7d, 0x3a, 0x3e, 0xd6, 0x90, 0x8e, 0xff, 0x75, 0x50, 0xfa,
-	0x54, 0xeb, 0xe9, 0x18, 0xb5, 0x3c, 0xc7, 0x8b, 0x8d, 0xfc, 0x57, 0xd8,
-	0x07, 0xd4, 0xa4, 0xc3, 0xe7, 0x01, 0x58, 0x69, 0xbf, 0x07, 0xe2, 0x7e,
-	0xc0, 0x47, 0xc4, 0x4e, 0xfe, 0x90, 0xe2, 0x8b, 0xb5, 0xb1, 0xd0, 0xcd,
-	0xae, 0xf9, 0x96, 0xc7, 0x35, 0xd0, 0xc5, 0x41, 0x0b, 0x76, 0x48, 0xda,
-	0xf4, 0x1a, 0x5e, 0xef, 0xf9, 0x0e, 0xe5, 0xec, 0x54, 0x9e, 0xe0, 0xa3,
-	0x0e, 0xd2, 0x53, 0x88, 0x2b, 0x2b, 0x1f, 0xf0, 0xd1, 0x8c, 0x5c, 0xb7,
-	0x79, 0x40, 0xe0, 0x03, 0xf4, 0xd5, 0x50, 0xc2, 0x9f, 0xe0, 0x3d, 0x95,
-	0xfe, 0xdf, 0xe4, 0x6a, 0x48, 0xed, 0x13, 0x8f, 0xc5, 0xfd, 0x3c, 0xeb,
-	0xfc, 0xb0, 0x3f, 0xf6, 0xd7, 0xd7, 0xcb, 0x79, 0xc5, 0x90, 0x05, 0x25,
-	0xfa, 0x0f, 0x96, 0x73, 0xfe, 0x03, 0xa6, 0xe8, 0xb9, 0x70, 0xb9, 0x78,
-	0x80, 0xf5, 0x47, 0xec, 0x21, 0x7c, 0x87, 0xda, 0xb7, 0xfb, 0xf6, 0x30,
-	0x75, 0xed, 0x67, 0xa9, 0x6f, 0x90, 0xc3, 0x7a, 0xa3, 0x71, 0x00, 0xf9,
-	0xe1, 0x16, 0x5f, 0x83, 0x5e, 0x51, 0x63, 0x56, 0x9c, 0x3a, 0xe0, 0x4f,
-	0x40, 0x0f, 0x68, 0x2b, 0x5d, 0x45, 0x53, 0xb3, 0x82, 0xa6, 0xe2, 0x6b,
-	0xb3, 0x8a, 0xa6, 0x66, 0x95, 0xff, 0x7c, 0x56, 0xd1, 0xd4, 0xac, 0xa2,
-	0xa9, 0x59, 0x45, 0x53, 0xb3, 0x8c, 0xd7, 0xa3, 0xac, 0xaf, 0x42, 0xf7,
-	0xd0, 0xfe, 0xcb, 0x2e, 0x4a, 0xe6, 0x70, 0x1e, 0xf2, 0xb8, 0x96, 0xae,
-	0x7e, 0x6d, 0x58, 0xfb, 0x47, 0x0b, 0x32, 0xcf, 0x8e, 0x9f, 0x85, 0x3d,
-	0x78, 0x98, 0xe1, 0x77, 0xcd, 0x37, 0xbf, 0x88, 0xb9, 0xfa, 0x28, 0x26,
-	0x7a, 0xc0, 0x36, 0x51, 0xd4, 0xad, 0xe3, 0x9a, 0xa8, 0xeb, 0x92, 0xb6,
-	0x5c, 0xaa, 0x61, 0x8d, 0x97, 0xc6, 0x8b, 0x69, 0xb5, 0x5f, 0xb5, 0x76,
-	0x4e, 0x0b, 0x25, 0xb2, 0x80, 0x2b, 0x72, 0x21, 0x2d, 0xde, 0x1b, 0x01,
-	0xa7, 0x94, 0xe9, 0x01, 0x83, 0xa3, 0x0a, 0x06, 0x4f, 0x8b, 0x35, 0x22,
-	0x97, 0x10, 0x3e, 0xc8, 0xc6, 0x70, 0x48, 0x67, 0x46, 0xf9, 0x3e, 0x8c,
-	0xfb, 0x07, 0x42, 0xcc, 0x83, 0xb6, 0x0b, 0x07, 0xf7, 0xda, 0x1b, 0xf1,
-	0x9a, 0xed, 0xd6, 0xd3, 0x5c, 0x77, 0xc9, 0x8e, 0x90, 0x92, 0x1b, 0x52,
-	0xef, 0xdd, 0xe5, 0xd8, 0x89, 0x14, 0xcf, 0xed, 0x2f, 0xc2, 0x7f, 0x39,
-	0x44, 0x6d, 0x25, 0x3a, 0x12, 0x06, 0x3e, 0x77, 0xb1, 0x5d, 0xc9, 0x73,
-	0x18, 0x2b, 0xd1, 0x85, 0xf0, 0x3e, 0xb6, 0x5d, 0xf6, 0xb3, 0x0e, 0x3a,
-	0xca, 0xff, 0x4e, 0xc4, 0xef, 0xc3, 0xbc, 0x3a, 0xf8, 0xda, 0x7e, 0x32,
-	0x7a, 0x52, 0x66, 0x2b, 0xeb, 0x07, 0x47, 0x2a, 0xf6, 0x88, 0x05, 0xff,
-	0x1c, 0xeb, 0xb6, 0xc6, 0x5c, 0xb8, 0x5b, 0xd5, 0x9c, 0xc1, 0x87, 0x8d,
-	0xf8, 0xd6, 0x3f, 0x97, 0x64, 0xaf, 0x80, 0x21, 0x75, 0xfc, 0xe3, 0x52,
-	0x64, 0x08, 0xc7, 0x78, 0xe7, 0x90, 0x3d, 0x11, 0xf1, 0xfd, 0x58, 0xea,
-	0xf2, 0x3e, 0xfb, 0x88, 0x7c, 0x3f, 0x80, 0x6d, 0x5a, 0x3e, 0x2f, 0xbc,
-	0x97, 0x3a, 0x4f, 0x25, 0x5f, 0x15, 0x74, 0x50, 0xa2, 0x7f, 0x67, 0x9a,
-	0x35, 0x09, 0xb1, 0x8c, 0x29, 0x51, 0x0b, 0x8d, 0x7c, 0xe5, 0xf9, 0x45,
-	0x3d, 0x2f, 0x47, 0xed, 0xf5, 0xfd, 0xc8, 0x37, 0xcb, 0x16, 0x68, 0x73,
-	0x99, 0x01, 0x3f, 0xda, 0xe8, 0xf2, 0x46, 0x4f, 0x50, 0xd4, 0x66, 0x77,
-	0xb3, 0x8e, 0xa3, 0xf3, 0x92, 0xc7, 0xf8, 0xfe, 0x01, 0xf1, 0xbe, 0xb9,
-	0xd8, 0x12, 0xc6, 0x35, 0xd3, 0xc8, 0x72, 0xe9, 0x21, 0xfe, 0x5d, 0xc4,
-	0x11, 0x93, 0xd4, 0xaa, 0x62, 0x04, 0x1d, 0x2a, 0xae, 0x14, 0x62, 0x5a,
-	0xaa, 0xd4, 0x1c, 0x8f, 0x94, 0x7d, 0x6d, 0xc0, 0xf1, 0x5a, 0x5f, 0xdb,
-	0x73, 0x5b, 0xc8, 0x9b, 0xad, 0xf0, 0x1a, 0x39, 0xa5, 0x2d, 0xa4, 0x7c,
-	0x88, 0xd6, 0x02, 0x6d, 0xb7, 0xb6, 0x6e, 0xc7, 0xd7, 0xb4, 0x36, 0xcf,
-	0xac, 0x9f, 0x79, 0xc7, 0x69, 0x53, 0xf8, 0xd4, 0x4c, 0xf3, 0xb9, 0x36,
-	0x96, 0xd9, 0xa8, 0x97, 0x02, 0xbc, 0xfc, 0x43, 0xa8, 0x37, 0x79, 0x32,
-	0xd0, 0x4c, 0xab, 0xab, 0xc8, 0x79, 0x78, 0xfc, 0x2e, 0x99, 0xe7, 0xfb,
-	0x08, 0xc3, 0x65, 0x3f, 0xcb, 0x37, 0x43, 0xc5, 0x70, 0x70, 0x0e, 0xbc,
-	0x41, 0xf4, 0xfd, 0x0c, 0x3c, 0x3c, 0xde, 0xc6, 0x7a, 0xbd, 0x8c, 0x01,
-	0x1c, 0xe4, 0x7b, 0x7f, 0x33, 0xf7, 0x08, 0xfc, 0x59, 0xe6, 0x61, 0xbe,
-	0x7f, 0x8c, 0xf5, 0x81, 0x08, 0x35, 0xd3, 0xca, 0x6a, 0x33, 0xeb, 0xf5,
-	0xcd, 0xac, 0x0f, 0x8c, 0x9a, 0x23, 0x3e, 0xf1, 0x2c, 0x51, 0xdb, 0xf2,
-	0xe9, 0xc0, 0x7e, 0xc6, 0x41, 0x3c, 0xeb, 0x8b, 0xea, 0x59, 0xb5, 0xcf,
-	0xb8, 0x55, 0xc2, 0xf1, 0x61, 0xff, 0xfa, 0x99, 0xab, 0x78, 0x2f, 0xd4,
-	0xe2, 0x34, 0xeb, 0xbe, 0x41, 0xf1, 0x6e, 0x46, 0x63, 0x66, 0x86, 0xed,
-	0x80, 0x30, 0x1f, 0x1f, 0xa1, 0x54, 0x31, 0x41, 0xbf, 0x57, 0x74, 0xfb,
-	0x6a, 0x8f, 0xf0, 0x9c, 0x65, 0x6d, 0x7d, 0x0b, 0xcf, 0xeb, 0x7d, 0xa7,
-	0x96, 0x67, 0xb4, 0x91, 0xff, 0x6b, 0x41, 0x6a, 0x7e, 0x11, 0xbe, 0x91,
-	0x12, 0x65, 0xc3, 0xf6, 0x85, 0xeb, 0xe2, 0xbd, 0x1b, 0x16, 0xbd, 0x22,
-	0xf2, 0x5b, 0xf9, 0x7a, 0xbe, 0xe7, 0x79, 0x8c, 0x7b, 0xc5, 0xa2, 0x2b,
-	0x8e, 0x84, 0xf7, 0x9f, 0x05, 0x82, 0xe4, 0x7f, 0x1d, 0x39, 0x48, 0xd0,
-	0xb5, 0xd6, 0xcf, 0x38, 0xfb, 0x98, 0x5f, 0xbf, 0x88, 0xeb, 0xf8, 0xf3,
-	0x75, 0x1c, 0xb7, 0xf1, 0x3a, 0x21, 0x6f, 0x91, 0x77, 0x02, 0x3e, 0xb7,
-	0x3f, 0x64, 0x0a, 0xfc, 0x3b, 0xc2, 0x38, 0xd5, 0x24, 0x7c, 0x81, 0xbd,
-	0x18, 0xeb, 0x0c, 0xb2, 0x6e, 0xb0, 0x7e, 0x66, 0x7c, 0x1f, 0x8e, 0x23,
-	0x3d, 0x7e, 0x86, 0x91, 0xc4, 0xa1, 0xb0, 0x78, 0xff, 0xa1, 0xeb, 0x2f,
-	0x70, 0x70, 0x9c, 0x78, 0x3f, 0xa1, 0x3f, 0xf0, 0x7e, 0x9a, 0xe8, 0xb3,
-	0xd4, 0x46, 0x71, 0x7e, 0x46, 0x2c, 0x27, 0xd7, 0x7d, 0xbe, 0xe8, 0x27,
-	0xe9, 0x47, 0x6a, 0x1e, 0xd6, 0xef, 0x29, 0xa4, 0x7e, 0xdc, 0x5b, 0xd3,
-	0x0a, 0xbe, 0x77, 0xd1, 0x8d, 0x5c, 0x07, 0xdd, 0x54, 0xb1, 0xa5, 0x1b,
-	0xc2, 0xae, 0x62, 0x9e, 0x9c, 0xe8, 0xa2, 0xeb, 0xab, 0x4d, 0x44, 0xbd,
-	0x6d, 0x22, 0xf6, 0x7b, 0x23, 0x97, 0xc7, 0xf3, 0x87, 0xa5, 0xdf, 0xa5,
-	0x82, 0x23, 0x37, 0x3c, 0x70, 0xe4, 0x3d, 0x81, 0x23, 0xef, 0x6d, 0x81,
-	0x23, 0x7b, 0x95, 0x2d, 0xd1, 0x46, 0xcd, 0x0a, 0x3f, 0x5e, 0x63, 0xfc,
-	0x78, 0x81, 0xf1, 0xe3, 0x50, 0x03, 0xfc, 0x30, 0x6a, 0xf0, 0xe3, 0xb0,
-	0xc0, 0x8f, 0x9f, 0x6d, 0x8a, 0x1f, 0x87, 0xfc, 0x9b, 0xf9, 0x82, 0x34,
-	0x6e, 0x0e, 0xd0, 0x4a, 0xce, 0xa1, 0xd5, 0x45, 0x9b, 0x2d, 0x7b, 0xd8,
-	0xe6, 0x88, 0x19, 0xce, 0x88, 0x7a, 0x97, 0x82, 0xc0, 0x2b, 0x96, 0xe3,
-	0x33, 0xa8, 0x69, 0xaa, 0xdb, 0x03, 0x12, 0xef, 0xa5, 0x14, 0xf0, 0x97,
-	0x7b, 0x12, 0xcb, 0xac, 0x9f, 0xf9, 0x73, 0xde, 0xc7, 0x2b, 0x6b, 0x81,
-	0x00, 0x7e, 0xf3, 0xcf, 0x04, 0x69, 0x63, 0x8d, 0xed, 0x54, 0xc6, 0xb1,
-	0xab, 0xb9, 0x21, 0xba, 0x92, 0x1b, 0xa0, 0x8d, 0xdc, 0x30, 0xbd, 0x93,
-	0xc3, 0x33, 0x00, 0x73, 0x3e, 0x16, 0x30, 0x37, 0xe8, 0x60, 0x90, 0xc7,
-	0xac, 0x0e, 0xd0, 0xfa, 0xaa, 0xc6, 0x57, 0xe0, 0x2a, 0xf6, 0x3f, 0xd2,
-	0x23, 0xeb, 0xd0, 0xea, 0x71, 0x20, 0x56, 0x85, 0x03, 0xf2, 0x1a, 0xec,
-	0xfd, 0x42, 0x7d, 0x0d, 0x6d, 0xab, 0x39, 0x83, 0x1c, 0xb8, 0x36, 0xb6,
-	0xc9, 0x6d, 0xe1, 0x73, 0x3d, 0xe8, 0x87, 0x4e, 0x6b, 0xdc, 0x4d, 0x5d,
-	0xbc, 0x07, 0x0e, 0xf2, 0x87, 0x86, 0x59, 0x3f, 0xed, 0x16, 0xfa, 0x68,
-	0xd4, 0x09, 0x84, 0x62, 0x54, 0x3a, 0x6b, 0x38, 0xe8, 0x93, 0xf8, 0x08,
-	0xdf, 0xcf, 0x50, 0x7e, 0x9e, 0x4e, 0x17, 0x3e, 0xd5, 0xea, 0x9e, 0x88,
-	0xd1, 0x9e, 0xe0, 0x39, 0x43, 0x4e, 0x56, 0xe2, 0x22, 0x54, 0x8e, 0x8b,
-	0xb4, 0xf2, 0xba, 0x25, 0x2d, 0xcd, 0x39, 0x3c, 0xae, 0xc8, 0xe3, 0x8a,
-	0x88, 0xa9, 0xf1, 0xf9, 0x55, 0xc4, 0x73, 0x87, 0x68, 0x63, 0x11, 0x34,
-	0x07, 0xff, 0x44, 0x25, 0x86, 0xba, 0xb1, 0x86, 0xf3, 0xf0, 0x51, 0x54,
-	0x62, 0xa8, 0x1b, 0x2a, 0x86, 0xba, 0xb1, 0x36, 0x2d, 0xf8, 0xf0, 0x42,
-	0x8e, 0x79, 0x40, 0xce, 0xaf, 0xf2, 0x07, 0xf7, 0xa9, 0x77, 0xf6, 0x9c,
-	0x10, 0x3e, 0xe4, 0x1e, 0x67, 0x73, 0x18, 0x1e, 0xac, 0x83, 0xe1, 0xb4,
-	0xd0, 0x83, 0xe2, 0x7c, 0xcf, 0x58, 0xee, 0x04, 0xc3, 0x73, 0x96, 0x69,
-	0x69, 0xb7, 0xa2, 0x25, 0x1d, 0x93, 0xed, 0x26, 0xf5, 0xfe, 0x1f, 0xa1,
-	0xeb, 0x4b, 0xfe, 0x33, 0x54, 0xc3, 0x7f, 0x28, 0x10, 0x1d, 0x97, 0xd7,
-	0xa7, 0x8b, 0xaf, 0x0c, 0x6b, 0xff, 0x5b, 0x9a, 0xef, 0xbb, 0x90, 0xdb,
-	0x49, 0x4c, 0x97, 0xe5, 0xa6, 0x67, 0xce, 0xe0, 0x76, 0x9f, 0xad, 0x71,
-	0xe1, 0xc4, 0x6d, 0xe0, 0x93, 0xbc, 0x47, 0x05, 0x9f, 0xfe, 0x77, 0x16,
-	0xc0, 0xb2, 0x93, 0x05, 0x98, 0x57, 0x84, 0x80, 0xf5, 0x03, 0x03, 0xb4,
-	0x8e, 0x39, 0x00, 0x1e, 0x53, 0x68, 0x02, 0xe6, 0x19, 0xa7, 0xf5, 0x40,
-	0xfb, 0xfb, 0x95, 0xc1, 0xeb, 0x5d, 0x1b, 0xa0, 0x67, 0x4f, 0x2d, 0xea,
-	0x79, 0x2c, 0x07, 0xca, 0xa3, 0x4e, 0x2a, 0x0c, 0x24, 0xe6, 0x27, 0x90,
-	0xff, 0x80, 0xfe, 0x00, 0xf9, 0x11, 0x98, 0x9f, 0x9c, 0x81, 0x72, 0xa0,
-	0x35, 0x53, 0xcd, 0x6b, 0x40, 0xfa, 0x40, 0x61, 0x08, 0x2a, 0x53, 0x41,
-	0x63, 0x1d, 0x40, 0xf6, 0x12, 0x21, 0x68, 0xd8, 0x01, 0x69, 0x20, 0xbb,
-	0x79, 0x8a, 0x08, 0x98, 0x9f, 0x14, 0x20, 0xc4, 0xd0, 0x00, 0xcf, 0x4f,
-	0xec, 0x40, 0x97, 0xc2, 0xdc, 0xf4, 0xff, 0xff, 0x31, 0x15, 0x16, 0x60,
-	0xda, 0x03, 0xad, 0xf9, 0xfc, 0xfd, 0xff, 0x80, 0x08, 0x0b, 0x43, 0x0b,
-	0x7c, 0xed, 0x9e, 0xb0, 0x3c, 0xa8, 0x9c, 0x5b, 0x00, 0x64, 0xb5, 0xc1,
-	0xeb, 0x6d, 0x16, 0xf0, 0x7d, 0xc4, 0x0b, 0x18, 0x7e, 0x01, 0xcb, 0x95,
-	0xff, 0xff, 0x97, 0xc2, 0xd5, 0x82, 0x00, 0x00, 0xd4, 0xc2, 0xcb, 0x42,
-	0x60, 0x7c, 0x00, 0x00, 0x00 };
-static u32 bnx2_COM_b09FwData[(0x0/4) + 1] = { 0x0 };
-static u32 bnx2_COM_b09FwRodata[(0x88/4) + 1] = {
-	0x08001ad8, 0x08001b14, 0x08001b14, 0x08001b14, 0x08001b14, 0x08001b14,
-	0x08001a24, 0x08001b14, 0x08001a98, 0x08001b14, 0x080019ac, 0x08001b14,
-	0x08001b14, 0x08001b14, 0x080019b8, 0x0, 0x08002a2c, 0x08002a7c,
-	0x08002aac, 0x08002adc, 0x08002b0c, 0x0, 0x08005fac, 0x08005fac,
-	0x08005fac, 0x08005fac, 0x08005fac, 0x08005fd8, 0x08005fd8, 0x08006018,
-	0x08006024, 0x08006024, 0x08005fac, 0x0, 0x0 };
-static u32 bnx2_COM_b09FwBss[(0x88/4) + 1] = { 0x0 };
-static u32 bnx2_COM_b09FwSbss[(0x5c/4) + 1] = { 0x0 };
+	0x1f, 0x8b, 0x08, 0x00, 0x0e, 0x34, 0xe7, 0x45, 0x00, 0x03, 0xdc, 0x5b,
+	0x6d, 0x70, 0x5c, 0xd5, 0x79, 0x7e, 0xef, 0xd9, 0xbb, 0xf2, 0x5a, 0x92,
+	0xe5, 0x6b, 0x79, 0x23, 0x16, 0x4b, 0xc0, 0xae, 0x75, 0x6d, 0x69, 0xb0,
+	0x43, 0x16, 0xa1, 0x80, 0x9a, 0xd9, 0xc0, 0xb2, 0x2b, 0x33, 0x9e, 0x0c,
+	0x69, 0x64, 0x50, 0x80, 0xb6, 0x4c, 0x46, 0xec, 0x1a, 0x9a, 0x4e, 0x87,
+	0xd6, 0xa6, 0x6e, 0x9b, 0xc9, 0x34, 0x78, 0x47, 0x1f, 0x8d, 0xa7, 0x15,
+	0xba, 0x06, 0x1b, 0xd9, 0xd3, 0xd0, 0xa0, 0x6a, 0x71, 0xf1, 0x8f, 0x8d,
+	0xaf, 0xf9, 0x48, 0xaa, 0x4c, 0x4d, 0xa5, 0x18, 0x48, 0x69, 0xa7, 0x4d,
+	0xfb, 0xa3, 0x9e, 0xa1, 0x5f, 0x84, 0x32, 0xfd, 0xc1, 0x74, 0xda, 0x4e,
+	0x3a, 0x24, 0x53, 0x08, 0x84, 0xed, 0xf3, 0x9c, 0x7b, 0xee, 0xea, 0x6a,
+	0x25, 0x7f, 0xf1, 0x91, 0x1f, 0xd5, 0xcc, 0xfa, 0xde, 0xf3, 0xfd, 0x9e,
+	0xf7, 0xbc, 0xef, 0xf3, 0x7e, 0xdc, 0xe3, 0x4f, 0x8a, 0xb4, 0x8a, 0xf9,
+	0xdb, 0x80, 0x5f, 0xfa, 0xc1, 0xdf, 0x2c, 0x5f, 0x37, 0x78, 0xdd, 0x0d,
+	0x78, 0xbd, 0x41, 0xc5, 0xec, 0x18, 0xeb, 0xf9, 0x4f, 0x12, 0xbf, 0x01,
+	0xf3, 0xbe, 0xd6, 0x9f, 0x83, 0xdf, 0x9b, 0x68, 0x1c, 0xfb, 0x0f, 0x11,
+	0xeb, 0x3c, 0x7d, 0xa2, 0x7f, 0xf5, 0xfa, 0x85, 0xdb, 0x15, 0x69, 0xb9,
+	0x40, 0x7b, 0x2c, 0x58, 0x52, 0xd3, 0xcc, 0x9f, 0x24, 0x54, 0x6e, 0xec,
+	0xe1, 0x82, 0x2b, 0x89, 0x58, 0x6e, 0xf7, 0xc1, 0xb2, 0x2b, 0x92, 0xaf,
+	0xed, 0x48, 0x17, 0xe5, 0x67, 0xf5, 0x4a, 0xd2, 0x16, 0xd6, 0x5f, 0x95,
+	0x7b, 0xef, 0xc9, 0x17, 0x6e, 0xca, 0xfc, 0x68, 0x2e, 0x26, 0x09, 0x27,
+	0xf7, 0xbc, 0x38, 0xdb, 0x25, 0xd1, 0x83, 0x31, 0x4f, 0xf4, 0xe5, 0x2d,
+	0xe9, 0x08, 0xe7, 0x7a, 0xb3, 0xfe, 0x42, 0x9f, 0x54, 0xb6, 0xe4, 0x12,
+	0xa2, 0x72, 0xdb, 0x5e, 0x2d, 0xc4, 0x9c, 0xb1, 0x58, 0xce, 0x91, 0x45,
+	0x5f, 0x46, 0xee, 0x9f, 0x96, 0x44, 0x22, 0xf7, 0xe5, 0xc4, 0xba, 0x6d,
+	0x92, 0xb0, 0x73, 0x4b, 0x0f, 0xff, 0xbe, 0x7b, 0xb0, 0xae, 0x5c, 0xb7,
+	0x7f, 0x5e, 0xda, 0x87, 0x4e, 0x0c, 0xa2, 0xbd, 0x96, 0xe9, 0x17, 0xb9,
+	0x49, 0x94, 0x5b, 0x69, 0x8f, 0xb9, 0x09, 0x29, 0xf8, 0xae, 0x14, 0x7d,
+	0x91, 0xbf, 0xac, 0x59, 0x72, 0xc2, 0xed, 0x92, 0xf9, 0x9d, 0xef, 0xd5,
+	0xf3, 0xa0, 0xe5, 0xfb, 0xee, 0xd2, 0xc3, 0x93, 0x2e, 0xe9, 0x3d, 0x90,
+	0x08, 0xe8, 0xdd, 0xbb, 0xae, 0xec, 0xda, 0x32, 0x5e, 0x63, 0xdd, 0xa8,
+	0x62, 0x5d, 0x3c, 0x97, 0x68, 0x3d, 0xe1, 0xb6, 0x9b, 0xba, 0x57, 0x6f,
+	0x29, 0x60, 0xbe, 0x89, 0x1a, 0xfb, 0xe6, 0xaf, 0x2f, 0xbb, 0x49, 0x53,
+	0xbf, 0x70, 0x63, 0xc1, 0x4d, 0xa1, 0xbe, 0xc7, 0xb4, 0x8d, 0x3d, 0x58,
+	0x76, 0x5d, 0xd3, 0xf6, 0x76, 0xac, 0xe0, 0xf6, 0x9b, 0xfa, 0xf7, 0x6e,
+	0x2e, 0xbb, 0x3b, 0x4d, 0x7d, 0x0f, 0xe6, 0xca, 0x9a, 0xfa, 0x85, 0x7b,
+	0xca, 0xee, 0xa0, 0xa9, 0xdf, 0x7d, 0x73, 0xc1, 0x1d, 0x32, 0xf5, 0x89,
+	0xa1, 0xb2, 0x9b, 0x43, 0xfd, 0x97, 0x13, 0x6a, 0x9b, 0x23, 0x53, 0xb5,
+	0x34, 0x7e, 0x79, 0xb4, 0x0d, 0xa3, 0x6e, 0x37, 0x7e, 0xb7, 0xe3, 0xf7,
+	0xc8, 0x46, 0xe9, 0x18, 0xc1, 0xf3, 0xbf, 0xba, 0x03, 0xde, 0x81, 0x47,
+	0x5e, 0x42, 0x5e, 0x8f, 0xa5, 0xe4, 0x85, 0xbe, 0xd7, 0xc1, 0x43, 0x47,
+	0x4e, 0xfb, 0x62, 0x8d, 0xf4, 0xa5, 0xc0, 0xbb, 0xa4, 0x3c, 0xe3, 0xb7,
+	0x49, 0xec, 0xb1, 0x18, 0x78, 0xf3, 0xcb, 0x52, 0x4a, 0x26, 0x64, 0xd3,
+	0xac, 0x25, 0x5b, 0x07, 0x12, 0x92, 0x77, 0xb8, 0x36, 0x4e, 0x7b, 0x26,
+	0x29, 0xb1, 0xd9, 0xfc, 0x66, 0x25, 0xdb, 0x9c, 0xa2, 0x54, 0xc0, 0xbb,
+	0x57, 0x29, 0x97, 0x68, 0x4b, 0x4b, 0x71, 0xfa, 0x5a, 0x19, 0x73, 0x48,
+	0xd7, 0x1f, 0x5c, 0x15, 0xac, 0x95, 0xb0, 0x0a, 0xc7, 0x46, 0x65, 0xca,
+	0x6b, 0xb7, 0x8a, 0xc7, 0x6e, 0x96, 0x42, 0x56, 0x92, 0x18, 0x97, 0x2a,
+	0xa1, 0xa5, 0x5a, 0x1b, 0x95, 0x49, 0x4f, 0xac, 0x82, 0x47, 0x7e, 0x76,
+	0xa1, 0xbd, 0x43, 0xf7, 0x45, 0x5d, 0x4f, 0x4c, 0xcf, 0x9d, 0x40, 0xbd,
+	0x83, 0xfa, 0x4e, 0x6b, 0x58, 0xcf, 0xa1, 0xeb, 0xd3, 0x13, 0xd2, 0x2e,
+	0x4f, 0xd5, 0x92, 0xa6, 0x6f, 0xbd, 0x5e, 0xc8, 0x3a, 0xe8, 0x37, 0x2a,
+	0x13, 0x5e, 0x52, 0xc6, 0xf0, 0x1c, 0xf7, 0xb8, 0x7e, 0x0a, 0x32, 0x75,
+	0xdd, 0xc1, 0xd2, 0x51, 0x3d, 0x5f, 0x3a, 0x96, 0xe3, 0x7c, 0x3d, 0xe8,
+	0xf7, 0x12, 0xe8, 0xb2, 0xc4, 0xd6, 0x67, 0x99, 0x97, 0xd2, 0xb4, 0x05,
+	0x79, 0xc3, 0x53, 0xf3, 0x75, 0x18, 0xf4, 0xdb, 0xe2, 0x0e, 0x58, 0x52,
+	0xc6, 0x59, 0x55, 0x1c, 0x94, 0x6b, 0x0b, 0xaa, 0xe0, 0xad, 0x93, 0xa2,
+	0x9d, 0x96, 0xd8, 0x0c, 0x65, 0x69, 0x4c, 0x26, 0x30, 0x46, 0xb9, 0xec,
+	0xf3, 0x0e, 0xf6, 0x3d, 0xa6, 0xcf, 0xa1, 0x25, 0x57, 0x51, 0x45, 0xbf,
+	0x4b, 0xd4, 0xec, 0xbd, 0xf2, 0xd2, 0xb4, 0x38, 0x38, 0xc7, 0x7a, 0xc1,
+	0x9d, 0x54, 0x85, 0xa7, 0x6d, 0x89, 0xcf, 0x58, 0x32, 0xe9, 0x66, 0xa0,
+	0x01, 0x87, 0xd4, 0x2e, 0x7f, 0x01, 0xfd, 0x38, 0x0e, 0xfd, 0x6a, 0x0a,
+	0x7c, 0xe5, 0xfb, 0x0e, 0x47, 0x69, 0x79, 0x66, 0x1f, 0x9c, 0x01, 0xf6,
+	0xf1, 0x8c, 0x87, 0x33, 0xd1, 0x67, 0x94, 0xc6, 0x19, 0x89, 0x35, 0xdc,
+	0x07, 0x99, 0x3a, 0x6a, 0x4b, 0x29, 0x8b, 0x7d, 0xa1, 0x77, 0x29, 0xbb,
+	0x4c, 0xd7, 0xc4, 0x74, 0x33, 0x5d, 0x1c, 0x47, 0xba, 0x02, 0x9a, 0xc6,
+	0x8f, 0x92, 0xbe, 0x65, 0x7a, 0xa6, 0xa6, 0x43, 0x1a, 0xb9, 0x1e, 0x69,
+	0x0b, 0xe9, 0xe2, 0x38, 0xd2, 0xb5, 0x99, 0x67, 0xcd, 0x3f, 0x6b, 0x18,
+	0x74, 0x4c, 0x78, 0x36, 0xce, 0xa8, 0x5d, 0x4a, 0x4e, 0xc5, 0x9a, 0x18,
+	0xda, 0x91, 0x82, 0x36, 0x5b, 0xe3, 0x43, 0xa4, 0xd9, 0xc5, 0x39, 0xb6,
+	0xe8, 0xf3, 0x56, 0xb9, 0x49, 0xf2, 0x0e, 0xfd, 0xb9, 0x3e, 0xde, 0x6b,
+	0x8e, 0x4c, 0xea, 0xf9, 0x48, 0xd3, 0x47, 0x31, 0x0f, 0x69, 0x7d, 0x05,
+	0xb2, 0x3a, 0x08, 0x19, 0xcd, 0xca, 0x5f, 0xf8, 0x3b, 0xe5, 0xcf, 0xfc,
+	0x7e, 0xf9, 0x0e, 0xf4, 0xf6, 0xdb, 0x7e, 0x5a, 0x9e, 0xf7, 0x7b, 0xe4,
+	0x39, 0x3f, 0x25, 0xcf, 0x6a, 0xf9, 0x1d, 0x16, 0xe9, 0xa0, 0x4c, 0xa7,
+	0xa5, 0x13, 0xfa, 0xb3, 0x09, 0xba, 0xf9, 0x38, 0xf8, 0x77, 0xb4, 0x4f,
+	0xf2, 0x9b, 0x73, 0x92, 0xb8, 0x1a, 0xbf, 0x2b, 0xf0, 0xeb, 0xca, 0xd9,
+	0x5a, 0x56, 0xec, 0x1c, 0x79, 0x68, 0x4b, 0x51, 0xef, 0xd9, 0x96, 0x09,
+	0xff, 0x91, 0xab, 0x03, 0xd9, 0x15, 0x19, 0x01, 0x8f, 0xd5, 0xc0, 0x4f,
+	0xea, 0x79, 0x07, 0xfb, 0x18, 0xd8, 0xa1, 0x79, 0xaf, 0x06, 0x28, 0xb3,
+	0x69, 0xc8, 0xbd, 0x6d, 0x15, 0xbd, 0x93, 0xc0, 0x8d, 0x36, 0xab, 0x70,
+	0xa4, 0x22, 0xe5, 0x23, 0x75, 0x29, 0x67, 0xe3, 0xf2, 0x90, 0x53, 0x97,
+	0xe1, 0x6c, 0x8b, 0xec, 0x77, 0xc0, 0xfb, 0x9d, 0xbf, 0x6d, 0x85, 0x98,
+	0xfd, 0xb8, 0xff, 0x3b, 0x78, 0x67, 0x9d, 0xc8, 0x51, 0xfd, 0x1e, 0xd4,
+	0x57, 0xfc, 0xb8, 0xe4, 0x93, 0x95, 0x94, 0x2d, 0x5b, 0x54, 0xb0, 0xee,
+	0x78, 0xd8, 0x06, 0x7e, 0x2c, 0x01, 0x27, 0x33, 0x5a, 0x5f, 0x4a, 0xd3,
+	0xeb, 0xdf, 0xce, 0xeb, 0x6a, 0xf4, 0x77, 0x06, 0xe5, 0xac, 0xe6, 0x67,
+	0x7a, 0xcc, 0xca, 0x25, 0x65, 0x6b, 0x8d, 0xe5, 0x21, 0xeb, 0x4e, 0x9f,
+	0xf2, 0x8c, 0x77, 0x9f, 0x74, 0x5e, 0x89, 0x7e, 0x36, 0x9e, 0x79, 0x43,
+	0x6f, 0x94, 0x46, 0xce, 0x43, 0x1a, 0xf9, 0xfc, 0x66, 0x84, 0xc6, 0x27,
+	0x1b, 0xef, 0x47, 0x23, 0xef, 0x15, 0xff, 0x8f, 0x5a, 0x03, 0xda, 0x86,
+	0xe4, 0x8d, 0x99, 0xaf, 0x98, 0x75, 0xf0, 0x7e, 0x8a, 0xf3, 0x7f, 0xab,
+	0x1e, 0xc8, 0x4b, 0xe5, 0x22, 0xeb, 0x2c, 0x44, 0xd6, 0xf9, 0x6e, 0x64,
+	0x9d, 0xef, 0x46, 0xd6, 0xa9, 0x80, 0xa7, 0xb2, 0x51, 0x41, 0x86, 0x4b,
+	0x34, 0x63, 0x72, 0x08, 0x73, 0xbe, 0x2e, 0xb1, 0x1c, 0xf5, 0x3c, 0xc4,
+	0x9b, 0x73, 0xe8, 0x9f, 0x93, 0xb3, 0x33, 0x15, 0x29, 0x1d, 0x89, 0xcb,
+	0x1d, 0xba, 0xdf, 0x26, 0x43, 0x5f, 0xb4, 0x2d, 0x21, 0x7b, 0x92, 0x7c,
+	0x0f, 0xdb, 0x6c, 0xf0, 0x99, 0xe5, 0x6f, 0x5d, 0x19, 0x94, 0xf9, 0xbe,
+	0x60, 0xf6, 0x32, 0x1a, 0x8c, 0x3b, 0xf5, 0xa6, 0xc6, 0xc3, 0x45, 0x9f,
+	0xb8, 0x25, 0xd9, 0x98, 0x2b, 0xfb, 0x86, 0xb3, 0x5d, 0x32, 0xe1, 0x58,
+	0xd9, 0xf1, 0xfe, 0x75, 0xd4, 0x8b, 0xbc, 0x72, 0xdb, 0x80, 0x0d, 0x92,
+	0x56, 0xc4, 0x7c, 0xbd, 0x2f, 0x4b, 0x05, 0xf4, 0x3b, 0x2c, 0x8f, 0x28,
+	0xb7, 0xb3, 0xa9, 0x9e, 0xba, 0x1d, 0xc3, 0x3b, 0x65, 0x78, 0x97, 0x39,
+	0x63, 0x1b, 0x65, 0xe2, 0xf0, 0x35, 0xa6, 0x1c, 0xb6, 0x6f, 0xb6, 0x57,
+	0x96, 0xcf, 0x76, 0xaf, 0x2c, 0x87, 0x38, 0x11, 0xc5, 0x70, 0xee, 0x15,
+	0xf8, 0xe4, 0x52, 0xee, 0xe2, 0xa0, 0x35, 0x0b, 0x9d, 0x5b, 0x67, 0x68,
+	0xb8, 0xc2, 0xd0, 0x00, 0x5a, 0xfb, 0x20, 0x59, 0x5a, 0x97, 0xb4, 0x68,
+	0x35, 0x95, 0xc9, 0xfb, 0xf0, 0x7d, 0x83, 0x6e, 0x0f, 0x74, 0x2e, 0x7c,
+	0x86, 0xf8, 0xfe, 0x66, 0xc4, 0x5e, 0xf4, 0x40, 0x67, 0x93, 0xe0, 0x55,
+	0x88, 0xf5, 0xc4, 0xe0, 0x14, 0xec, 0x03, 0x64, 0x55, 0x63, 0x7b, 0x3b,
+	0xf0, 0xd0, 0x36, 0xd8, 0x9c, 0x30, 0xd8, 0xdc, 0x0e, 0x5c, 0x66, 0xd9,
+	0x31, 0xe5, 0xa4, 0x29, 0xa7, 0x50, 0x86, 0x1d, 0x9f, 0x25, 0x2e, 0x5f,
+	0x77, 0x70, 0xef, 0x51, 0x8d, 0xf7, 0xb4, 0x15, 0x40, 0x61, 0xe2, 0x35,
+	0x71, 0xbb, 0x47, 0xe6, 0x6b, 0x58, 0xaf, 0x81, 0x8d, 0xdc, 0x7b, 0x94,
+	0x1e, 0xd2, 0xb2, 0x5e, 0x14, 0x6c, 0x57, 0x3e, 0x49, 0x7a, 0x1f, 0xc4,
+	0xde, 0x89, 0x3f, 0xa4, 0xfb, 0x2a, 0xd0, 0xca, 0x7d, 0xfc, 0x3c, 0x69,
+	0xe5, 0x7a, 0xcd, 0xf4, 0x7e, 0x58, 0x1c, 0x24, 0xed, 0x27, 0xb1, 0xe7,
+	0x3c, 0x30, 0x4f, 0xac, 0xd1, 0xbe, 0x51, 0xec, 0x79, 0x04, 0x78, 0x78,
+	0x3b, 0xf0, 0x70, 0x37, 0xf0, 0x70, 0x18, 0x78, 0x98, 0x03, 0x16, 0x0e,
+	0x01, 0x0b, 0x07, 0x81, 0x85, 0x59, 0xf0, 0x26, 0x29, 0x73, 0xc0, 0xc6,
+	0x39, 0x60, 0xe4, 0x1c, 0xe6, 0x18, 0x9f, 0x15, 0xeb, 0x4b, 0xd8, 0xc3,
+	0x63, 0x33, 0x99, 0x93, 0x90, 0xa5, 0x54, 0x45, 0x41, 0xfe, 0xb3, 0x43,
+	0x90, 0xed, 0x7e, 0xa9, 0xfa, 0xb6, 0x94, 0x69, 0x53, 0xb7, 0xf7, 0x42,
+	0xd7, 0x20, 0xef, 0x29, 0x31, 0x7f, 0x1b, 0xcc, 0xf3, 0x1f, 0x45, 0xdc,
+	0xbf, 0xa3, 0x2c, 0xa6, 0x45, 0xce, 0x48, 0xc9, 0xeb, 0x75, 0x0a, 0xaa,
+	0x1f, 0xfd, 0x58, 0xce, 0xaa, 0xfb, 0x8f, 0x5c, 0xaf, 0xf6, 0x1e, 0x21,
+	0x5f, 0xa6, 0x81, 0x57, 0x75, 0x99, 0xcc, 0x52, 0xb7, 0xea, 0x72, 0x22,
+	0x9b, 0x19, 0xaa, 0x48, 0x9b, 0x4c, 0x25, 0xa7, 0xb5, 0xad, 0xb5, 0x73,
+	0x87, 0xb5, 0xbd, 0x2a, 0xbb, 0x78, 0xd6, 0x06, 0x54, 0xe9, 0x08, 0xf7,
+	0xdf, 0x8b, 0x5f, 0x1c, 0xb4, 0x70, 0x7e, 0x5b, 0x86, 0x07, 0x1d, 0xf5,
+	0x40, 0x5f, 0x05, 0x08, 0x96, 0x71, 0xce, 0x62, 0xe5, 0xe2, 0x74, 0x6f,
+	0xaa, 0xa8, 0x6c, 0x19, 0xb3, 0x2d, 0x19, 0x87, 0x7c, 0x0f, 0x67, 0xdf,
+	0xa9, 0x4f, 0x25, 0xd9, 0xbe, 0x4e, 0xbe, 0xae, 0x7d, 0x0e, 0xac, 0x5d,
+	0x3d, 0x8a, 0x75, 0xe3, 0x38, 0x03, 0xae, 0xcb, 0x79, 0x50, 0xae, 0xd9,
+	0x28, 0x67, 0x4e, 0x56, 0xc4, 0x87, 0x9e, 0x6c, 0x94, 0xc2, 0xce, 0x16,
+	0xc9, 0x8f, 0xa4, 0x65, 0x7c, 0xc6, 0x07, 0x4e, 0xe1, 0x1c, 0xdd, 0x56,
+	0x29, 0x8d, 0xa6, 0xe5, 0xd1, 0x19, 0xd6, 0x9d, 0xc6, 0xfe, 0x33, 0x87,
+	0xf2, 0xc2, 0xfd, 0xc7, 0xf5, 0xbe, 0xd2, 0xea, 0xb4, 0xec, 0xf7, 0xde,
+	0x30, 0x7a, 0x14, 0x94, 0xef, 0xc7, 0x99, 0x9e, 0xf0, 0x17, 0xb0, 0x7f,
+	0x57, 0xe6, 0x81, 0xff, 0xc5, 0x23, 0xc0, 0x41, 0xb7, 0x03, 0x98, 0x95,
+	0x59, 0xa0, 0x4d, 0x8d, 0xc1, 0xef, 0xab, 0x6a, 0x5e, 0xf7, 0xc8, 0x91,
+	0x19, 0x25, 0xdf, 0xbe, 0x31, 0x8d, 0x32, 0xb0, 0x31, 0x9b, 0x39, 0x3d,
+	0xa6, 0x7a, 0xe4, 0x86, 0xce, 0x14, 0xc6, 0xe5, 0x54, 0xc9, 0xdb, 0x18,
+	0x03, 0x2f, 0x8f, 0xa7, 0x15, 0xfb, 0x2a, 0x29, 0x66, 0x63, 0x38, 0xff,
+	0x0a, 0xfa, 0xbf, 0x8f, 0xf5, 0x7a, 0x64, 0x16, 0xbe, 0xd6, 0xec, 0x4c,
+	0x1e, 0xe3, 0x88, 0x5d, 0x99, 0xe3, 0x4b, 0x0a, 0x18, 0x33, 0x0b, 0xf9,
+	0x1e, 0x85, 0x2f, 0x33, 0x03, 0xd1, 0x69, 0x4d, 0xe3, 0x4c, 0x7b, 0x9d,
+	0x71, 0xe0, 0x41, 0xbe, 0x87, 0xef, 0x9c, 0xd3, 0x95, 0x13, 0x1e, 0xe5,
+	0x30, 0x2d, 0x4f, 0xf9, 0x1c, 0xd7, 0xbb, 0xf0, 0x1c, 0x7c, 0x9f, 0xdf,
+	0xf5, 0xae, 0x44, 0xff, 0x77, 0xe1, 0x07, 0x3b, 0x52, 0xc5, 0xb9, 0x95,
+	0xc1, 0xcb, 0x7c, 0x2a, 0x28, 0x8f, 0xcf, 0x66, 0x16, 0xde, 0x50, 0x7c,
+	0x77, 0x2b, 0xf3, 0xea, 0x5a, 0x91, 0x4e, 0xf2, 0x33, 0x0b, 0x5e, 0xba,
+	0x8e, 0x52, 0xdb, 0x8d, 0xef, 0x47, 0x3d, 0x72, 0x41, 0x9f, 0x2d, 0xf3,
+	0x03, 0x51, 0x3d, 0xa2, 0x3d, 0x0c, 0xf5, 0x28, 0x93, 0x5a, 0x52, 0x0a,
+	0xed, 0xb6, 0x1c, 0xd6, 0x65, 0x0b, 0xb4, 0x66, 0x52, 0xdc, 0xdf, 0x44,
+	0xad, 0x5f, 0x9e, 0xf2, 0xd8, 0x1f, 0x7c, 0x9e, 0x6e, 0x37, 0xfd, 0x4f,
+	0x83, 0x87, 0xf4, 0xdf, 0xfa, 0x41, 0x73, 0xa0, 0x5b, 0xf3, 0xd3, 0x49,
+	0xdd, 0x36, 0xe5, 0x05, 0x7e, 0x9a, 0x82, 0x2f, 0x37, 0x07, 0x5f, 0xae,
+	0xa8, 0xf5, 0xcc, 0xc9, 0xc3, 0xd7, 0x87, 0x9e, 0x04, 0x3a, 0x56, 0xad,
+	0x91, 0x96, 0xbb, 0x40, 0x5f, 0xa6, 0x02, 0x62, 0x0e, 0xab, 0x1c, 0xce,
+	0x7d, 0x50, 0x2a, 0xf4, 0xf7, 0xce, 0xc6, 0x9e, 0x92, 0xb1, 0x2a, 0xed,
+	0x11, 0x7e, 0x9e, 0xeb, 0x30, 0xbe, 0xc8, 0x6b, 0x5b, 0xd1, 0x0d, 0x39,
+	0x80, 0x1d, 0xc9, 0x6e, 0x32, 0x7e, 0xce, 0x13, 0x38, 0xcf, 0x33, 0x38,
+	0xf7, 0x9a, 0xec, 0x3d, 0xf6, 0x0a, 0x65, 0xba, 0xbf, 0x2a, 0x99, 0xfe,
+	0x29, 0xd9, 0xe1, 0xcc, 0x43, 0x1f, 0xf3, 0xa3, 0xf5, 0x5b, 0x54, 0x8e,
+	0x63, 0x0e, 0x62, 0x0c, 0x9e, 0xd5, 0x57, 0xe4, 0x21, 0x9f, 0x75, 0x0f,
+	0x81, 0x9f, 0xd0, 0x95, 0xc1, 0x27, 0x8c, 0x1e, 0x60, 0x3e, 0x3b, 0x9c,
+	0xef, 0x15, 0x33, 0x1f, 0xfb, 0xb1, 0x0f, 0xc7, 0x2c, 0xcf, 0xbb, 0x8b,
+	0xb6, 0x08, 0x78, 0xb4, 0x4b, 0xd5, 0x6f, 0x89, 0xa3, 0xfd, 0xc4, 0x20,
+	0xdf, 0x31, 0x0f, 0x6c, 0x91, 0xe3, 0x9e, 0x41, 0x5f, 0xf8, 0x7a, 0xde,
+	0x7a, 0x29, 0x74, 0x85, 0xf4, 0x52, 0x06, 0xe8, 0x27, 0x68, 0x1b, 0xbc,
+	0x39, 0xe0, 0xfd, 0x1f, 0xc6, 0x02, 0x99, 0x3c, 0x80, 0x32, 0xf5, 0xef,
+	0x80, 0x14, 0xbd, 0x0c, 0xf6, 0x09, 0x1d, 0xf3, 0x3b, 0xac, 0x60, 0x8f,
+	0xe0, 0xff, 0xc8, 0x39, 0xf0, 0x41, 0x2a, 0x01, 0x6f, 0xc8, 0x17, 0xf2,
+	0xa4, 0x03, 0xb2, 0x0f, 0xb9, 0x87, 0xdc, 0x96, 0x34, 0x0f, 0xfe, 0xbd,
+	0x33, 0xf0, 0x8b, 0x33, 0x95, 0x3c, 0xe3, 0xb9, 0x4e, 0xe2, 0x26, 0x30,
+	0xcc, 0x87, 0x70, 0x60, 0xee, 0x25, 0xb5, 0x9e, 0xf4, 0xa6, 0x97, 0x62,
+	0x7d, 0x2c, 0xf7, 0x2f, 0x41, 0x86, 0xab, 0x38, 0x9f, 0xc2, 0xce, 0x5e,
+	0x83, 0x5b, 0xcf, 0xc6, 0x28, 0xaf, 0x55, 0x60, 0x4c, 0xc9, 0xdb, 0xe1,
+	0xdc, 0x4d, 0xbe, 0x39, 0x8e, 0x3c, 0xe7, 0x45, 0xb1, 0x03, 0xb6, 0xcf,
+	0xa5, 0x1c, 0x26, 0x21, 0x07, 0x36, 0x6c, 0x68, 0x0a, 0x67, 0xfe, 0x6f,
+	0x9d, 0xc1, 0x5e, 0xf8, 0x6e, 0xcb, 0x9c, 0x83, 0x35, 0xbd, 0xc5, 0x8d,
+	0x41, 0x1d, 0xdf, 0xb7, 0xf0, 0x8c, 0x0e, 0xaf, 0xa4, 0x9d, 0xe7, 0xdb,
+	0x7c, 0xa6, 0x27, 0xb0, 0x17, 0xd6, 0xe3, 0x59, 0x3d, 0x2e, 0x7b, 0x89,
+	0x9b, 0x83, 0xdb, 0x52, 0x2f, 0xa2, 0x7f, 0x11, 0x36, 0xa1, 0x62, 0xb3,
+	0xed, 0x6d, 0x6b, 0x79, 0x8c, 0xa2, 0x5f, 0x0a, 0x1f, 0x78, 0xc9, 0xfa,
+	0x92, 0xff, 0x92, 0x55, 0xa8, 0xbe, 0x6d, 0x15, 0x21, 0x27, 0x55, 0x8f,
+	0xf1, 0x0b, 0xf5, 0xc7, 0xc1, 0xda, 0x99, 0xd4, 0x5b, 0xaa, 0x37, 0x3d,
+	0x0f, 0x2c, 0xb8, 0x1f, 0x3a, 0x5d, 0xb4, 0x17, 0xa4, 0xec, 0xd7, 0xa4,
+	0x74, 0x6c, 0x07, 0xf4, 0x2d, 0x1d, 0xa1, 0x8b, 0x78, 0x56, 0xa1, 0x1f,
+	0x6e, 0xed, 0xf2, 0xa4, 0xd2, 0x92, 0x23, 0xae, 0x6d, 0x83, 0xec, 0xa0,
+	0xae, 0xb6, 0x2c, 0x7f, 0xb7, 0xad, 0xa2, 0x15, 0xb1, 0xee, 0xe0, 0x4a,
+	0x7a, 0xab, 0x72, 0x71, 0x7a, 0x77, 0x35, 0xe8, 0x25, 0x66, 0x00, 0xff,
+	0x3d, 0xe0, 0xbf, 0x07, 0xfc, 0xf7, 0x80, 0xff, 0x1e, 0xf0, 0xdf, 0x83,
+	0x6d, 0xf0, 0x60, 0x03, 0x3c, 0xd8, 0x00, 0x0f, 0x36, 0xc0, 0x83, 0x0d,
+	0xf0, 0x0a, 0x38, 0x27, 0xe2, 0x3c, 0x6d, 0xc8, 0x3d, 0x0d, 0xbb, 0x19,
+	0xf8, 0x39, 0x57, 0x1a, 0xdf, 0x01, 0xfa, 0xe7, 0x6c, 0x91, 0xf1, 0xfe,
+	0x2b, 0xb0, 0xb7, 0x56, 0x3c, 0xdb, 0xf0, 0xc4, 0x1a, 0xfd, 0x9f, 0x35,
+	0x7a, 0xf2, 0x55, 0xd0, 0xa5, 0x50, 0xfe, 0x05, 0xc8, 0x61, 0x0b, 0xe8,
+	0xf9, 0x94, 0xf1, 0x31, 0xbe, 0x61, 0x07, 0x72, 0xd8, 0x86, 0xba, 0xcf,
+	0xa0, 0xae, 0x0d, 0x7d, 0xf6, 0xa3, 0x0f, 0x7d, 0x94, 0x0e, 0x53, 0x17,
+	0xed, 0x47, 0x5f, 0xe5, 0x0b, 0x58, 0x2b, 0x83, 0x7e, 0x1d, 0x98, 0xbb,
+	0x07, 0x7d, 0x6e, 0x46, 0x9f, 0xab, 0x50, 0xa6, 0x6f, 0xdb, 0x8d, 0xf2,
+	0xa7, 0x9b, 0xc6, 0x5c, 0x83, 0xba, 0xcf, 0x36, 0xd5, 0x9d, 0x45, 0x1d,
+	0x62, 0x62, 0xe7, 0x45, 0x33, 0xae, 0x82, 0x72, 0x57, 0x53, 0x9f, 0x57,
+	0x50, 0x37, 0x84, 0xba, 0xbf, 0xc2, 0x13, 0xb1, 0xb0, 0x43, 0x9a, 0xc2,
+	0x36, 0xfa, 0xa9, 0x69, 0xd4, 0xc7, 0x8d, 0xaf, 0xf9, 0x24, 0x7d, 0x2f,
+	0xd8, 0xdc, 0x3f, 0xb6, 0x03, 0xdf, 0x0c, 0xde, 0xab, 0x96, 0xc3, 0xb0,
+	0xfc, 0xcd, 0xa6, 0x32, 0xfb, 0x7e, 0xbf, 0xa9, 0xae, 0x6d, 0xd3, 0xca,
+	0xf2, 0x4f, 0xe3, 0xab, 0xc7, 0xdc, 0xdb, 0xd4, 0xe7, 0xeb, 0x9d, 0x2b,
+	0xcb, 0xbb, 0x5b, 0x56, 0x8f, 0xd9, 0xbe, 0x71, 0x65, 0xdd, 0xad, 0x9b,
+	0x57, 0x96, 0xe9, 0x03, 0x26, 0x11, 0xc3, 0x84, 0xfd, 0x77, 0x7e, 0x22,
+	0x68, 0x27, 0x7f, 0x9b, 0x65, 0x49, 0x2b, 0x23, 0xca, 0x0a, 0xe7, 0xb0,
+	0x64, 0x41, 0x9f, 0x1c, 0x95, 0x7b, 0xc9, 0x2a, 0x42, 0xa6, 0x0a, 0x7e,
+	0x38, 0x1f, 0x75, 0xb6, 0x39, 0x4f, 0x10, 0xe6, 0x07, 0xe8, 0x6f, 0xb5,
+	0x43, 0x6e, 0xee, 0xa2, 0x4d, 0x3a, 0x54, 0x91, 0x65, 0xfd, 0xdc, 0xaa,
+	0xce, 0xa7, 0x9f, 0xf7, 0x19, 0x8c, 0x3a, 0x07, 0x3a, 0xeb, 0x32, 0x92,
+	0x5d, 0x47, 0x1b, 0x63, 0xb0, 0x8b, 0xb8, 0x53, 0xaf, 0xc7, 0xb6, 0xd7,
+	0x65, 0x5f, 0xf6, 0xdd, 0xba, 0x68, 0xcc, 0xbb, 0x57, 0xe3, 0x4e, 0x5a,
+	0x75, 0xe3, 0x8c, 0x1c, 0xc4, 0x12, 0x88, 0xed, 0x93, 0xb4, 0x49, 0xc7,
+	0xe9, 0x9f, 0x1c, 0x0c, 0x30, 0x95, 0xb8, 0x83, 0xb2, 0x3f, 0x85, 0x39,
+	0xb9, 0x3e, 0x9e, 0x55, 0xe2, 0xb8, 0xad, 0x6d, 0x4a, 0xc9, 0xe1, 0xbc,
+	0x6b, 0x61, 0xe3, 0xbf, 0xd8, 0xf4, 0x0b, 0x6d, 0xf7, 0x24, 0xec, 0x1b,
+	0xdb, 0xe8, 0x2b, 0x9c, 0xa4, 0x5f, 0x12, 0xc1, 0xaa, 0x9b, 0x62, 0xe2,
+	0x2e, 0x63, 0x66, 0xb0, 0xaf, 0x2d, 0xf4, 0xfb, 0x2f, 0x61, 0xaf, 0x6b,
+	0x63, 0x51, 0xaf, 0xba, 0xb8, 0x6e, 0xef, 0x69, 0xe8, 0x76, 0x28, 0x7b,
+	0x6b, 0xe5, 0x03, 0x5e, 0xd5, 0x67, 0xf1, 0xac, 0x9f, 0x39, 0x5c, 0x81,
+	0x2e, 0x2d, 0xea, 0xd8, 0x37, 0x3c, 0x17, 0xfa, 0x38, 0x99, 0xe3, 0x73,
+	0x90, 0xed, 0xbd, 0x3a, 0x26, 0x60, 0x3c, 0x50, 0x97, 0x5d, 0xd9, 0x4f,
+	0x25, 0xc9, 0x87, 0xbc, 0xfa, 0x71, 0x9c, 0x3e, 0xc3, 0xa2, 0x47, 0x9e,
+	0x65, 0xd1, 0x9e, 0x05, 0x26, 0xfc, 0xab, 0x14, 0x93, 0xac, 0x7b, 0xab,
+	0x3e, 0x0f, 0xbf, 0x4a, 0xfb, 0x47, 0xda, 0xde, 0xd3, 0xbf, 0x83, 0x5d,
+	0xf7, 0xc9, 0xd3, 0x25, 0xf0, 0x39, 0xf4, 0x01, 0x7e, 0x40, 0x1f, 0x55,
+	0x56, 0xfa, 0xd2, 0x22, 0x0f, 0xd5, 0xfe, 0x01, 0x36, 0x47, 0x05, 0xbe,
+	0x0a, 0xe3, 0x65, 0x97, 0xf5, 0x37, 0xc6, 0xe9, 0xcb, 0x05, 0xb6, 0x3e,
+	0x86, 0xf5, 0x10, 0x5f, 0xd7, 0xfe, 0xd3, 0x2a, 0x79, 0x3d, 0xf4, 0xb3,
+	0xb0, 0x7f, 0xf8, 0x50, 0x3e, 0xdb, 0x58, 0x97, 0x30, 0xfe, 0x77, 0xbb,
+	0xf1, 0xb7, 0x1d, 0xe3, 0x6f, 0x6b, 0x3a, 0x12, 0x4e, 0x2e, 0xf4, 0x0b,
+	0x78, 0x66, 0xe9, 0x83, 0x6a, 0x3b, 0xfd, 0x82, 0x0e, 0x59, 0xdb, 0x2f,
+	0x08, 0x69, 0x3a, 0x85, 0x7d, 0xd2, 0xcf, 0xd3, 0x79, 0xa0, 0xce, 0x20,
+	0xf7, 0x44, 0x1a, 0x42, 0xfb, 0xa8, 0xed, 0xf0, 0x21, 0x98, 0x3c, 0xe6,
+	0x24, 0x41, 0xeb, 0x6e, 0x29, 0x4c, 0x9f, 0x32, 0xf6, 0x96, 0x71, 0x04,
+	0x7d, 0xf8, 0x40, 0x66, 0x0b, 0xd9, 0x0e, 0xcb, 0xcc, 0xd3, 0x05, 0x0b,
+	0x19, 0xc9, 0x51, 0x71, 0x2d, 0xfa, 0x31, 0xa1, 0x4f, 0xb3, 0x60, 0x7c,
+	0x9a, 0x33, 0xb2, 0xcf, 0x0b, 0xe2, 0x86, 0x91, 0xda, 0x12, 0xea, 0x34,
+	0xed, 0x29, 0xfa, 0x96, 0x0a, 0x3e, 0x77, 0xfe, 0xde, 0x0c, 0x02, 0x90,
+	0x60, 0x2f, 0x5b, 0xb1, 0x97, 0x6a, 0x63, 0x2f, 0x6d, 0x4b, 0xcd, 0x3e,
+	0x0e, 0xc7, 0x4e, 0xae, 0x1a, 0x2b, 0xd8, 0xc7, 0xdc, 0x79, 0xda, 0xb8,
+	0x47, 0xfa, 0x0d, 0x8e, 0xd9, 0x63, 0x78, 0x4e, 0x8f, 0x63, 0x8f, 0x49,
+	0xab, 0xa4, 0x7d, 0x2d, 0xfa, 0x2d, 0x88, 0xb3, 0x6b, 0x2f, 0xe1, 0x49,
+	0xfd, 0xd0, 0xf3, 0x60, 0x4f, 0xed, 0x7a, 0x4f, 0x53, 0xde, 0x2b, 0x7a,
+	0x1f, 0xf3, 0xb5, 0xbf, 0x91, 0xf2, 0xb1, 0x1f, 0xc0, 0xee, 0x45, 0x73,
+	0x73, 0xcc, 0x6b, 0x92, 0x1f, 0x95, 0x08, 0x7e, 0x72, 0xaf, 0xcc, 0xbb,
+	0xbd, 0x1c, 0x0f, 0xe2, 0x83, 0x69, 0x9c, 0xb1, 0x15, 0xb4, 0xeb, 0xf5,
+	0x43, 0xbe, 0xb6, 0x44, 0xe8, 0xa9, 0xc3, 0xe7, 0x4c, 0x81, 0x86, 0xe8,
+	0x98, 0x03, 0x32, 0xec, 0xf1, 0x3c, 0x7a, 0x53, 0x7b, 0xc5, 0x75, 0x4a,
+	0x12, 0xfa, 0x19, 0x5c, 0x9f, 0x3a, 0x5f, 0x84, 0xe3, 0xcb, 0x5c, 0x6a,
+	0xc8, 0xbb, 0x90, 0x6f, 0xed, 0x4b, 0xcd, 0x32, 0x30, 0x89, 0x58, 0xab,
+	0xec, 0x91, 0x4f, 0xa1, 0x6c, 0x86, 0x6b, 0xbf, 0x6a, 0x71, 0x3f, 0x13,
+	0x3a, 0x7f, 0xf8, 0x4f, 0x0d, 0x19, 0x1d, 0x07, 0x76, 0x04, 0x32, 0xf7,
+	0xf7, 0x86, 0x37, 0xa1, 0x6c, 0xb6, 0x9b, 0x73, 0x66, 0x2c, 0x48, 0xdd,
+	0x09, 0xe5, 0x60, 0x9b, 0x73, 0xa7, 0xe6, 0x05, 0xdb, 0xb4, 0xcf, 0xad,
+	0xcf, 0x72, 0xac, 0x71, 0x96, 0x1b, 0x9a, 0xe4, 0xf2, 0xdd, 0x8d, 0x81,
+	0x1e, 0x52, 0xdf, 0xa0, 0xb7, 0xe0, 0xd7, 0xb3, 0x2b, 0xf4, 0xbb, 0xff,
+	0x3c, 0x39, 0xd9, 0x76, 0x89, 0xcd, 0x7e, 0x0f, 0xbc, 0xbc, 0x06, 0xb1,
+	0x8a, 0x88, 0x3d, 0x43, 0x1c, 0xa2, 0xbf, 0xb1, 0xec, 0xef, 0xce, 0xcb,
+	0x5a, 0xbe, 0xee, 0xc5, 0x7c, 0x8d, 0x4f, 0x5e, 0xa2, 0xaf, 0x31, 0xdc,
+	0x22, 0xad, 0xc4, 0xa2, 0x33, 0xf0, 0x6d, 0x2d, 0x69, 0x71, 0xbf, 0x01,
+	0x1b, 0x76, 0xda, 0x5e, 0xe7, 0x86, 0x98, 0xd0, 0x2e, 0x9b, 0x66, 0xb7,
+	0x68, 0x5c, 0x70, 0x66, 0x96, 0x71, 0x61, 0x1c, 0xbc, 0x1f, 0x09, 0xf2,
+	0xbc, 0xc9, 0x4d, 0x72, 0xa9, 0xf1, 0xf5, 0xb2, 0xdf, 0x3f, 0xd6, 0xf0,
+	0xfb, 0xaf, 0x6c, 0xe2, 0xe3, 0x5a, 0xb8, 0x78, 0x1a, 0x7c, 0xcb, 0x21,
+	0xfe, 0x65, 0x5c, 0x3b, 0x8c, 0x78, 0x98, 0xb1, 0x58, 0x1e, 0x31, 0x71,
+	0xe6, 0xb4, 0xc8, 0x6e, 0xc4, 0xc8, 0x99, 0x1f, 0x31, 0x7f, 0xf5, 0xbc,
+	0x9f, 0x99, 0x13, 0xb9, 0x1d, 0x7c, 0x1d, 0x04, 0x6e, 0x66, 0x81, 0xa3,
+	0x3b, 0xc1, 0xdf, 0x7e, 0x8d, 0x9d, 0xf7, 0x1f, 0x11, 0xeb, 0x0e, 0x9d,
+	0xab, 0xa6, 0x3e, 0x27, 0x61, 0x47, 0xeb, 0xf5, 0xfd, 0xd9, 0x5e, 0xc4,
+	0xf5, 0x69, 0xb9, 0xd5, 0x66, 0x1c, 0x6b, 0xd9, 0x5b, 0x07, 0xe6, 0x63,
+	0x51, 0x9f, 0xb4, 0x70, 0x51, 0x3b, 0xb0, 0x9a, 0xf7, 0x45, 0x6d, 0x0b,
+	0x0e, 0xc7, 0x2e, 0xc4, 0xfb, 0x3b, 0x1a, 0xbc, 0x6f, 0x69, 0x95, 0xd6,
+	0xdb, 0x75, 0x1e, 0x61, 0xeb, 0xc0, 0x7e, 0xe2, 0x55, 0x16, 0x76, 0x1d,
+	0xf6, 0xb7, 0x2e, 0xb7, 0x65, 0xdf, 0xae, 0xbf, 0xe8, 0x6e, 0x94, 0xd2,
+	0xce, 0xfb, 0x0c, 0x66, 0x2f, 0x7d, 0xad, 0xe0, 0x56, 0xa0, 0x1f, 0x41,
+	0xce, 0x70, 0xef, 0x74, 0x02, 0x96, 0x80, 0x7f, 0x9d, 0x32, 0x3f, 0xf4,
+	0x16, 0xce, 0x70, 0xc7, 0x49, 0x26, 0x9c, 0x14, 0x70, 0x78, 0x3e, 0xd9,
+	0xae, 0xf3, 0xc5, 0x9f, 0x70, 0x59, 0xef, 0xe0, 0x4c, 0x47, 0x65, 0x1e,
+	0xfe, 0x43, 0x75, 0x08, 0x34, 0xee, 0xec, 0x42, 0x7f, 0xea, 0x1d, 0x79,
+	0x3e, 0x0a, 0xdb, 0x4b, 0x9e, 0x26, 0xd1, 0x7f, 0x0f, 0xfa, 0x74, 0xe2,
+	0x79, 0x5f, 0x6c, 0xde, 0x61, 0xec, 0xfc, 0x79, 0x94, 0x39, 0x47, 0xd4,
+	0x76, 0x7e, 0x2e, 0x2e, 0x7a, 0x4e, 0x8e, 0xe9, 0xd2, 0xfa, 0xbf, 0xbc,
+	0x16, 0xd7, 0x61, 0xdb, 0xcf, 0xea, 0xd7, 0x0f, 0x0c, 0x45, 0xd6, 0xeb,
+	0x88, 0xac, 0x37, 0x14, 0x59, 0x8f, 0x74, 0x76, 0x46, 0xe8, 0xec, 0xc4,
+	0xf8, 0x22, 0xd6, 0x26, 0x3f, 0xa2, 0x6b, 0x3e, 0x18, 0x59, 0x33, 0xdc,
+	0x5f, 0x57, 0x64, 0xdc, 0xbb, 0x58, 0x8f, 0x75, 0xc9, 0x48, 0x1d, 0x69,
+	0xd8, 0x8c, 0x3a, 0x96, 0x3b, 0x23, 0x74, 0x91, 0xd6, 0x0d, 0xa8, 0xd7,
+	0xfe, 0x13, 0xf8, 0xdc, 0x0a, 0xbb, 0xa5, 0x60, 0x3b, 0x5a, 0xe0, 0x5f,
+	0x35, 0xef, 0xf5, 0x51, 0xac, 0x1b, 0xce, 0x97, 0xc4, 0x1c, 0xec, 0xcf,
+	0xbe, 0x31, 0x33, 0x9e, 0xf5, 0x6c, 0xff, 0xf3, 0xfa, 0x9f, 0x6a, 0xbe,
+	0x6d, 0x06, 0xed, 0x3a, 0xef, 0x22, 0x73, 0x9d, 0x36, 0xce, 0x93, 0xf1,
+	0xb1, 0x25, 0x57, 0xbb, 0xca, 0xea, 0x1d, 0xe0, 0xd9, 0x6f, 0x34, 0x58,
+	0xda, 0x6a, 0x15, 0x8e, 0x30, 0x5f, 0xd0, 0x66, 0x62, 0x3e, 0xc4, 0x1e,
+	0xda, 0xc6, 0xd8, 0xa6, 0x9d, 0x36, 0x86, 0x7e, 0x0b, 0xed, 0xe7, 0x69,
+	0xf3, 0x8e, 0x27, 0x64, 0xf8, 0x81, 0x6a, 0xa7, 0xbc, 0xa8, 0x79, 0xea,
+	0xc8, 0xd9, 0x06, 0x4f, 0xe3, 0xe6, 0xbb, 0xcc, 0x01, 0xf3, 0xcd, 0xa3,
+	0x0f, 0x7e, 0x11, 0xde, 0x6b, 0x79, 0xd0, 0x90, 0x96, 0xde, 0x01, 0xc6,
+	0x6e, 0x15, 0x3c, 0x99, 0xa7, 0xb0, 0xf0, 0x0c, 0xf2, 0x17, 0xbd, 0x03,
+	0xb0, 0x4b, 0xc0, 0xa1, 0xde, 0x81, 0x73, 0x3a, 0x9e, 0xab, 0xfa, 0x8e,
+	0x75, 0x9b, 0x17, 0xe4, 0x88, 0xce, 0xba, 0x17, 0xca, 0x11, 0xdd, 0xb3,
+	0x8e, 0x79, 0x8d, 0x30, 0x47, 0x74, 0x56, 0x74, 0x8e, 0xe8, 0xf8, 0x45,
+	0x72, 0x44, 0xf9, 0x4b, 0xcf, 0x11, 0x71, 0x7e, 0x5b, 0xee, 0x1c, 0x74,
+	0xd4, 0xaf, 0x9a, 0x1c, 0xd1, 0x1b, 0x12, 0xe4, 0x88, 0x5e, 0x94, 0xb5,
+	0x73, 0x44, 0x87, 0x9a, 0x72, 0x44, 0x9b, 0x75, 0x8e, 0x88, 0xf3, 0x04,
+	0x39, 0x22, 0x96, 0x4b, 0x03, 0x43, 0x91, 0x5c, 0x07, 0xf0, 0xd7, 0xbb,
+	0x01, 0x7c, 0x73, 0xac, 0x51, 0x2f, 0xc4, 0x34, 0x62, 0xff, 0x15, 0x0d,
+	0xfb, 0xb5, 0x8c, 0x6f, 0x96, 0x96, 0xb9, 0x8b, 0xe1, 0xdb, 0x68, 0xe0,
+	0x97, 0xac, 0xc0, 0xb6, 0xc9, 0x86, 0xef, 0xe2, 0xad, 0x63, 0x0c, 0x3d,
+	0x51, 0x5b, 0x9e, 0x77, 0x02, 0xbc, 0x1e, 0x6b, 0xe4, 0x49, 0xce, 0xe7,
+	0x1f, 0x25, 0xe5, 0xc0, 0x9a, 0xdf, 0xbd, 0x52, 0xf9, 0xd5, 0xdf, 0xbd,
+	0x2c, 0x49, 0x82, 0xce, 0xd2, 0x40, 0x49, 0xc7, 0x5d, 0xf3, 0xde, 0xaf,
+	0xc8, 0xd2, 0xdd, 0x0e, 0xf0, 0x27, 0xcc, 0x9f, 0xf0, 0x7c, 0x97, 0x6d,
+	0x4a, 0x41, 0x7d, 0x7c, 0x39, 0x94, 0x07, 0x74, 0x0e, 0xe5, 0xc5, 0x75,
+	0xd1, 0x1c, 0xca, 0x59, 0xb9, 0x70, 0x0e, 0xe5, 0x81, 0x35, 0x72, 0x28,
+	0x2f, 0xcb, 0x72, 0x0e, 0xe5, 0x65, 0x09, 0x73, 0x28, 0x31, 0x59, 0xda,
+	0x1c, 0x48, 0xe3, 0x03, 0xfe, 0x12, 0x7e, 0x67, 0xf0, 0x0b, 0x72, 0x2a,
+	0x67, 0x1b, 0xf4, 0xaf, 0x95, 0x53, 0x79, 0x7d, 0xdd, 0x07, 0xc9, 0xa9,
+	0x04, 0x36, 0x20, 0xcc, 0xa9, 0xe0, 0xe7, 0xc0, 0xe6, 0xa8, 0x68, 0x4e,
+	0xe5, 0x27, 0xd4, 0x07, 0xd4, 0xb1, 0xcc, 0x7a, 0xe8, 0x05, 0xec, 0x52,
+	0x5e, 0xe7, 0x38, 0x3e, 0x67, 0x78, 0x38, 0x87, 0x3d, 0xa7, 0x71, 0x16,
+	0xe4, 0x63, 0xaf, 0xf6, 0x2d, 0xf3, 0x76, 0xca, 0x2a, 0xf4, 0xc1, 0x9a,
+	0x4d, 0xf3, 0xbb, 0xb8, 0x6d, 0xed, 0xf5, 0x29, 0xe3, 0x09, 0xab, 0x8c,
+	0xbd, 0x0c, 0x4f, 0xcf, 0xc9, 0x5e, 0x3f, 0xf4, 0xa9, 0x06, 0x1a, 0x73,
+	0x50, 0x37, 0xe7, 0x81, 0xb3, 0xc0, 0x89, 0x4b, 0xb0, 0x51, 0xa7, 0x40,
+	0x73, 0x74, 0x1f, 0x88, 0x89, 0x07, 0x51, 0xa7, 0xcf, 0x9c, 0xbe, 0x65,
+	0x48, 0x4b, 0x9a, 0x7a, 0x7e, 0x09, 0xf3, 0xb1, 0xee, 0x94, 0x8e, 0xc7,
+	0xca, 0x83, 0xdc, 0x2b, 0x6d, 0xdd, 0x22, 0xe8, 0x43, 0x5d, 0x95, 0x31,
+	0x20, 0xed, 0x5e, 0x18, 0xa3, 0xb5, 0xeb, 0x18, 0xad, 0x4b, 0xf3, 0x83,
+	0xbc, 0xbe, 0x35, 0x41, 0xac, 0xec, 0x72, 0xb9, 0x87, 0x33, 0x06, 0xeb,
+	0x58, 0x0e, 0x62, 0xc1, 0xbc, 0xe2, 0xfb, 0xef, 0xe1, 0x5c, 0x99, 0xa7,
+	0x09, 0xcf, 0xef, 0x2b, 0x66, 0xdf, 0x43, 0x52, 0xe9, 0x92, 0xc4, 0x66,
+	0xd0, 0x53, 0x9a, 0xa1, 0xdf, 0xfd, 0x69, 0x1d, 0x83, 0x24, 0xdd, 0xf3,
+	0xeb, 0xed, 0x1d, 0x97, 0xa1, 0xb7, 0x23, 0x17, 0xd4, 0xdb, 0xaf, 0x25,
+	0xa2, 0x7a, 0x7b, 0xc7, 0x65, 0xe8, 0xed, 0xbe, 0xcb, 0xd2, 0x5b, 0xee,
+	0x8d, 0x98, 0x14, 0xe6, 0xc4, 0x56, 0xfb, 0x59, 0xe1, 0xba, 0xe3, 0x58,
+	0x33, 0x7f, 0x9e, 0x35, 0xc7, 0xce, 0x9b, 0x5b, 0x6d, 0xf6, 0xb1, 0x2e,
+	0xe5, 0xbc, 0x19, 0x5b, 0xd1, 0xde, 0xb6, 0x1b, 0xbb, 0x74, 0x9f, 0x89,
+	0xe7, 0xc3, 0xb8, 0x3e, 0xaa, 0x3f, 0x94, 0x0b, 0xca, 0xc2, 0x77, 0xc0,
+	0x2f, 0xca, 0x43, 0xa8, 0x73, 0xdd, 0x4d, 0x32, 0xb8, 0x88, 0x78, 0xbf,
+	0xdb, 0xc8, 0x20, 0xcf, 0xba, 0x4f, 0x7f, 0x67, 0xaa, 0x7a, 0x4f, 0x05,
+	0x71, 0xbe, 0x8b, 0x67, 0x35, 0xd4, 0x35, 0xf0, 0x24, 0x19, 0xb6, 0x91,
+	0x8f, 0x2e, 0x7c, 0x9e, 0x1d, 0xf0, 0xd7, 0xc0, 0x23, 0x5d, 0xbf, 0x32,
+	0x27, 0x7c, 0x61, 0x3c, 0x93, 0x4a, 0x1c, 0x7d, 0x4f, 0x0c, 0x42, 0xc7,
+	0x07, 0x89, 0x51, 0x35, 0xc4, 0x3d, 0x94, 0x43, 0xca, 0xe6, 0xb6, 0xfe,
+	0x5d, 0x8a, 0x3e, 0xd5, 0x13, 0x88, 0x83, 0x29, 0xaf, 0x69, 0xd9, 0xe5,
+	0x6f, 0x3b, 0x7d, 0x56, 0x71, 0x8d, 0x7a, 0xbd, 0xc4, 0x58, 0xd1, 0x11,
+	0xb5, 0x75, 0xe0, 0xbf, 0x13, 0xb4, 0x4b, 0x57, 0xb8, 0x31, 0x23, 0x6b,
+	0x79, 0xbc, 0x53, 0x6e, 0x7f, 0x08, 0x7b, 0xcf, 0xef, 0xfd, 0xaf, 0xa1,
+	0x3e, 0x05, 0x9d, 0xa7, 0x7d, 0x67, 0x3c, 0x72, 0x93, 0xe9, 0xd7, 0xad,
+	0xbf, 0x57, 0x16, 0xb2, 0x37, 0x98, 0x6f, 0x57, 0xb4, 0x3f, 0x19, 0xda,
+	0xec, 0x15, 0xe7, 0xcc, 0xfb, 0x12, 0x45, 0x1d, 0xcf, 0x70, 0xbc, 0x96,
+	0x49, 0xc4, 0x20, 0x76, 0x24, 0x97, 0x9e, 0x30, 0xb1, 0x1b, 0x75, 0xac,
+	0x1d, 0x67, 0xe8, 0x9b, 0x58, 0x85, 0xf1, 0xeb, 0xca, 0x7b, 0x12, 0x6b,
+	0xcb, 0xc0, 0x96, 0x0f, 0x20, 0x03, 0xcd, 0xe7, 0x97, 0x80, 0xee, 0x87,
+	0xe7, 0x17, 0xfa, 0x31, 0x73, 0x66, 0xdf, 0xdd, 0xc1, 0x19, 0xfe, 0xbf,
+	0xd8, 0xa7, 0x15, 0xd9, 0x67, 0x88, 0x47, 0x0f, 0x98, 0x7d, 0xde, 0xd4,
+	0x84, 0x47, 0x23, 0x4d, 0x3a, 0xfb, 0x71, 0xe2, 0xd1, 0x9f, 0xac, 0xff,
+	0xf8, 0xf1, 0x88, 0xfb, 0xea, 0x5e, 0x13, 0x87, 0x82, 0x7d, 0x3c, 0x22,
+	0x2a, 0xf7, 0x51, 0xc6, 0x7b, 0x1f, 0xe4, 0x7c, 0xa2, 0x38, 0xc2, 0x33,
+	0xe9, 0xd0, 0x3e, 0x6c, 0xa0, 0x7b, 0xb0, 0xe5, 0xd5, 0xb8, 0xbc, 0x7e,
+	0x57, 0x42, 0xfe, 0xf7, 0x46, 0x7e, 0x0f, 0xb3, 0x4d, 0x4e, 0x8b, 0xe5,
+	0xd7, 0xd6, 0x07, 0x76, 0xe8, 0xb5, 0x4d, 0x81, 0xdd, 0xe1, 0x98, 0x50,
+	0x9f, 0x1d, 0xb4, 0xb3, 0xad, 0x5b, 0x96, 0x3a, 0x2f, 0x27, 0x06, 0xdc,
+	0xe6, 0xbc, 0xa1, 0xd6, 0x8a, 0x01, 0x2f, 0x9c, 0x0f, 0x5c, 0x8e, 0x01,
+	0x89, 0xb3, 0x9d, 0x5a, 0x36, 0x4a, 0x49, 0xc6, 0x3e, 0x7d, 0x06, 0x3b,
+	0xf9, 0x8e, 0xd8, 0xd6, 0x43, 0xbc, 0xeb, 0x21, 0xd6, 0xf5, 0x10, 0xff,
+	0x7a, 0x88, 0x71, 0x3d, 0xc4, 0xb6, 0x1e, 0x62, 0x5b, 0x0f, 0xb1, 0xad,
+	0xd7, 0x6f, 0x62, 0xe4, 0x11, 0x93, 0xf7, 0xe7, 0x77, 0x72, 0xe6, 0x17,
+	0x2a, 0xb0, 0x25, 0x93, 0xbc, 0xe7, 0xa0, 0x0a, 0xd9, 0xf5, 0x66, 0x7f,
+	0x61, 0x4e, 0xbc, 0xc7, 0xe4, 0x6c, 0x5e, 0xd7, 0x79, 0x43, 0x51, 0xb3,
+	0xad, 0xc1, 0xb7, 0x74, 0xde, 0xc7, 0xf8, 0x2d, 0xf8, 0x25, 0xfa, 0x3e,
+	0x13, 0x75, 0xb4, 0xae, 0x72, 0xcc, 0xc9, 0x88, 0x52, 0xb9, 0xeb, 0x31,
+	0x66, 0x47, 0x10, 0x13, 0x24, 0x25, 0xa6, 0x72, 0x6d, 0xe4, 0xa9, 0xa5,
+	0x72, 0x1b, 0xcc, 0x5c, 0x47, 0x5b, 0x03, 0xdf, 0xaa, 0x8f, 0x65, 0x5b,
+	0xe5, 0x6e, 0xe6, 0x13, 0xe7, 0x1e, 0xd6, 0xf7, 0x74, 0xae, 0x5c, 0x6b,
+	0x4a, 0xe3, 0x7b, 0x21, 0x7b, 0x37, 0xe6, 0xd3, 0xf7, 0x88, 0x1a, 0xfc,
+	0x56, 0xe7, 0xe5, 0xf7, 0x94, 0xe1, 0x77, 0xc0, 0xe3, 0x18, 0xfb, 0xe9,
+	0xbc, 0x30, 0x79, 0x1d, 0xce, 0xa7, 0xf3, 0x7a, 0x58, 0x47, 0xdf, 0xa5,
+	0xc0, 0x53, 0xc5, 0xa5, 0x63, 0xf4, 0x9e, 0xb8, 0x1b, 0x5d, 0x37, 0xfc,
+	0x26, 0x7e, 0x29, 0x6b, 0x76, 0xeb, 0xef, 0x68, 0x81, 0xcd, 0x98, 0xd2,
+	0x32, 0x68, 0xe7, 0xb8, 0xaf, 0xf7, 0x21, 0x7f, 0x53, 0x5a, 0xfe, 0x8a,
+	0x88, 0x63, 0x26, 0x07, 0xb7, 0xa5, 0x6d, 0x75, 0xa0, 0x95, 0xf9, 0xd7,
+	0x61, 0x3f, 0xc4, 0x3d, 0xae, 0xd7, 0x6c, 0xc7, 0x99, 0x57, 0x0b, 0xf1,
+	0x4c, 0xb6, 0x04, 0xf9, 0xb6, 0x0f, 0xa3, 0x4b, 0xad, 0x4d, 0xba, 0x14,
+	0xee, 0x93, 0xfb, 0xe7, 0x73, 0xed, 0x3b, 0x15, 0x8b, 0x7e, 0xe4, 0xfb,
+	0x48, 0x43, 0x36, 0x78, 0xb7, 0xe4, 0x8b, 0x90, 0x41, 0xfd, 0x9d, 0x02,
+	0x7a, 0x54, 0xaf, 0x0f, 0x33, 0xc7, 0xbc, 0xf3, 0x0b, 0xe6, 0xde, 0x82,
+	0x3c, 0xcc, 0xfc, 0x83, 0xbd, 0x2a, 0xff, 0x30, 0x0c, 0x59, 0x81, 0x0f,
+	0xe0, 0x75, 0x68, 0x9f, 0x4e, 0xb9, 0xf4, 0x07, 0x9a, 0xbf, 0xbf, 0x3c,
+	0xda, 0x16, 0xf0, 0xe1, 0xed, 0xd6, 0xe0, 0x1b, 0xc4, 0xdf, 0x26, 0x57,
+	0x96, 0x39, 0xfe, 0x7f, 0x8c, 0xac, 0x1c, 0x86, 0x6d, 0x1e, 0x86, 0x2c,
+	0x22, 0x26, 0xd7, 0xf3, 0x1d, 0x96, 0xd2, 0xd3, 0x0b, 0x9d, 0x2b, 0xfb,
+	0xa3, 0xee, 0x58, 0xd8, 0xff, 0xb1, 0xa6, 0xfe, 0x8f, 0xa1, 0xff, 0x0b,
+	0x4d, 0xfd, 0x1f, 0x8b, 0xf4, 0x3f, 0xda, 0xd4, 0x1f, 0x31, 0xe2, 0xd3,
+	0xff, 0xdc, 0xd4, 0xff, 0x68, 0xa4, 0xff, 0x6c, 0x53, 0xff, 0x59, 0xf4,
+	0x7f, 0xad, 0xa9, 0x3f, 0xea, 0x8e, 0xb5, 0x98, 0xef, 0x62, 0xc4, 0xd8,
+	0x7d, 0x26, 0x16, 0xc7, 0xb3, 0xd6, 0xfc, 0xad, 0x85, 0x72, 0xd7, 0x83,
+	0x33, 0x08, 0xef, 0xb4, 0x51, 0x5f, 0xf3, 0xd0, 0xd7, 0x65, 0x5f, 0x26,
+	0x90, 0xc7, 0xa8, 0x2c, 0x12, 0x1f, 0x2a, 0x12, 0x73, 0x7d, 0xfa, 0x47,
+	0x56, 0xb9, 0x1a, 0xda, 0x24, 0xde, 0x5b, 0xe2, 0x7d, 0xd7, 0xc0, 0xf6,
+	0xc6, 0xdd, 0x45, 0x13, 0x83, 0x5d, 0xd1, 0x06, 0xda, 0x81, 0x97, 0x21,
+	0x66, 0xca, 0xe1, 0x40, 0x6f, 0x28, 0xbf, 0x9c, 0xdf, 0xe8, 0x0f, 0x65,
+	0xd5, 0xac, 0x33, 0xbc, 0x0a, 0xd7, 0xd2, 0xab, 0x72, 0x5b, 0xb1, 0x4b,
+	0xc0, 0xb5, 0x91, 0x06, 0xae, 0x7d, 0x51, 0xe6, 0x1a, 0xf1, 0xf6, 0x19,
+	0xd9, 0xef, 0xed, 0xe1, 0x3d, 0x9d, 0xc3, 0x79, 0xf9, 0x68, 0xe2, 0xed,
+	0x3d, 0x0d, 0x3b, 0xc9, 0x3b, 0x1d, 0xe9, 0x83, 0xbc, 0x83, 0x1b, 0xe6,
+	0x66, 0x27, 0xbd, 0x5f, 0xc7, 0xfe, 0x69, 0x33, 0x2f, 0x37, 0xde, 0xe6,
+	0x7c, 0x49, 0xd9, 0x1f, 0xdc, 0x77, 0x68, 0xcc, 0x5b, 0x69, 0xcc, 0x9b,
+	0x32, 0xfa, 0x46, 0x1b, 0xbc, 0x6c, 0x2f, 0x8b, 0xb0, 0x97, 0x63, 0x88,
+	0xb9, 0x17, 0xbd, 0xb5, 0xf2, 0xa3, 0x97, 0x6b, 0x2f, 0x9b, 0xf3, 0xcc,
+	0xcd, 0xf6, 0x92, 0xeb, 0x34, 0xe7, 0x96, 0xd3, 0x4d, 0xf8, 0x4f, 0x79,
+	0x3a, 0x67, 0x7c, 0x6a, 0x3c, 0xab, 0xe7, 0xa0, 0x8f, 0x4a, 0xc6, 0xb4,
+	0xfc, 0xb2, 0x1c, 0xc6, 0x96, 0xf7, 0x34, 0x62, 0xcb, 0xe5, 0x78, 0x10,
+	0xbe, 0x6b, 0xff, 0x67, 0x0c, 0x3e, 0xd2, 0x47, 0x76, 0xac, 0xb2, 0xb7,
+	0x5b, 0xed, 0xd5, 0x6d, 0xcc, 0x97, 0x5e, 0x2b, 0xb7, 0xea, 0x38, 0xfe,
+	0x8c, 0xc9, 0x4d, 0xcd, 0x69, 0xff, 0x9f, 0xdf, 0x0b, 0xca, 0xd9, 0x4d,
+	0xc6, 0xdf, 0xbb, 0x18, 0xae, 0xae, 0x8c, 0x4d, 0x95, 0x3a, 0x88, 0xb1,
+	0x8c, 0x4d, 0xfb, 0xdb, 0x89, 0xa1, 0x05, 0xff, 0x82, 0xe3, 0x31, 0x8e,
+	0xe3, 0xd9, 0x47, 0xc7, 0xa1, 0xe8, 0xb7, 0x68, 0xc6, 0x07, 0x71, 0x68,
+	0xc1, 0xff, 0x71, 0x5b, 0x80, 0x83, 0x17, 0x8a, 0x59, 0x3e, 0xdf, 0xce,
+	0xbc, 0xde, 0xa2, 0x77, 0x31, 0x5a, 0x57, 0xc7, 0xbd, 0xb1, 0x55, 0x71,
+	0xaf, 0x6d, 0xe2, 0xda, 0x5f, 0xd2, 0x71, 0x6f, 0xc0, 0x63, 0xee, 0x25,
+	0x1a, 0x47, 0xb9, 0xc0, 0x42, 0x7e, 0x53, 0x21, 0x3e, 0xd0, 0x47, 0x81,
+	0x9f, 0x35, 0xfd, 0x8b, 0xe0, 0x73, 0x72, 0x0d, 0xb9, 0xf9, 0xb8, 0xed,
+	0x44, 0xb8, 0xf7, 0x73, 0x12, 0xe4, 0xeb, 0x76, 0x83, 0x16, 0xc6, 0x56,
+	0x71, 0x23, 0x0f, 0x3f, 0x35, 0xf7, 0x2a, 0xc3, 0x7e, 0x61, 0x1c, 0xdf,
+	0xf8, 0xee, 0x5a, 0xc9, 0xaf, 0xc8, 0x9f, 0x74, 0x33, 0x0d, 0x8d, 0x73,
+	0xcf, 0x5f, 0xc6, 0x77, 0x8b, 0x0f, 0x73, 0x3f, 0xa2, 0xd9, 0xae, 0xf1,
+	0xbb, 0x29, 0xbf, 0x95, 0x8a, 0x75, 0x67, 0x9f, 0x0b, 0x1d, 0xe0, 0xbd,
+	0xe1, 0x28, 0xbe, 0x26, 0xa4, 0x34, 0x2b, 0x89, 0x64, 0x8e, 0xdf, 0x00,
+	0x68, 0xff, 0x7f, 0x68, 0xf6, 0x99, 0x92, 0x7d, 0x33, 0x41, 0xce, 0x53,
+	0x5d, 0xf0, 0x5e, 0xdc, 0xe3, 0xe0, 0x43, 0xe6, 0x50, 0x98, 0xf3, 0x54,
+	0xc1, 0xbd, 0xb8, 0x43, 0x1f, 0xdd, 0xbd, 0x38, 0xce, 0x6f, 0xcb, 0x9e,
+	0x35, 0xee, 0xc5, 0xc5, 0x2e, 0xf1, 0x5e, 0xdc, 0x26, 0x9d, 0xf3, 0xe4,
+	0x3c, 0x41, 0xce, 0x93, 0xe5, 0xad, 0x03, 0xcc, 0x95, 0xf0, 0xee, 0xdb,
+	0xa0, 0xbe, 0x2f, 0xbc, 0x75, 0xe0, 0xe7, 0x11, 0xa3, 0xfc, 0x75, 0xfb,
+	0xc7, 0x1f, 0xa3, 0x70, 0x2f, 0xbf, 0x11, 0x7c, 0xdf, 0x95, 0xcb, 0xc9,
+	0x03, 0x7c, 0xb8, 0xbc, 0xe6, 0x3e, 0x9d, 0xd7, 0x7c, 0xa7, 0x3d, 0x9a,
+	0xd7, 0x54, 0x17, 0xb9, 0x1b, 0xb6, 0x6f, 0x8d, 0xbc, 0x66, 0x3c, 0x72,
+	0x37, 0x2c, 0x6e, 0xee, 0x86, 0x6d, 0x72, 0x11, 0x4b, 0x9a, 0x3c, 0xa6,
+	0xba, 0xe0, 0xdd, 0xb0, 0xce, 0x0d, 0x1f, 0x3e, 0x8f, 0xb9, 0xea, 0x6e,
+	0x18, 0x6c, 0xdd, 0x16, 0x49, 0x5f, 0x56, 0xdc, 0xf3, 0x61, 0x62, 0x1e,
+	0xde, 0xab, 0x6f, 0xc1, 0x9e, 0xe3, 0xb2, 0x27, 0x49, 0xf9, 0xe4, 0xdd,
+	0xc6, 0x3e, 0xe8, 0x02, 0x9e, 0x3e, 0xcb, 0xfd, 0x3c, 0x23, 0x6b, 0xa4,
+	0x6f, 0xe5, 0x3d, 0x84, 0xe5, 0x3b, 0xbd, 0x89, 0xc6, 0x9d, 0xde, 0x29,
+	0xc8, 0x8d, 0x9a, 0x49, 0xc8, 0x7c, 0x44, 0xa6, 0x26, 0x3d, 0xf8, 0x4b,
+	0xb3, 0x8e, 0x69, 0xe7, 0xff, 0xef, 0x48, 0x02, 0xf3, 0x78, 0x0f, 0xb8,
+	0x43, 0x62, 0xb3, 0xc1, 0x37, 0xcb, 0xe0, 0xff, 0xb8, 0xa4, 0xd0, 0x87,
+	0x77, 0x3c, 0xe3, 0xb2, 0x5f, 0xe7, 0x2c, 0x42, 0x59, 0xfe, 0x35, 0xf0,
+	0x78, 0x73, 0x7e, 0xb9, 0x9c, 0x5c, 0xc3, 0xee, 0x27, 0xa5, 0x3c, 0x43,
+	0x79, 0xbe, 0xc1, 0xfc, 0xff, 0x82, 0xd3, 0x52, 0xf6, 0x4f, 0x99, 0xf8,
+	0x42, 0x7f, 0xdb, 0x01, 0x2f, 0xb7, 0x18, 0x1b, 0x8c, 0x67, 0x75, 0x0b,
+	0x6d, 0x1e, 0xd6, 0x38, 0x2e, 0xc3, 0xd3, 0x3b, 0x52, 0x7b, 0x81, 0x77,
+	0x63, 0x7a, 0xcd, 0xcb, 0xe1, 0xb9, 0x75, 0x9e, 0xef, 0x8d, 0x97, 0xca,
+	0xf7, 0xd0, 0x3f, 0xae, 0x62, 0x7f, 0x5b, 0x20, 0x1f, 0x5f, 0x95, 0xe2,
+	0xb1, 0x6b, 0x65, 0xf8, 0x68, 0x06, 0xf4, 0xbc, 0x5f, 0x2f, 0x67, 0xe1,
+	0x4b, 0x3f, 0xcd, 0x7b, 0x63, 0xc0, 0x50, 0xf0, 0xed, 0xf9, 0x55, 0xdf,
+	0xb1, 0xa3, 0x77, 0xcd, 0xfa, 0x1b, 0x77, 0x87, 0x9e, 0xf5, 0x25, 0xd1,
+	0x49, 0x9a, 0x67, 0x96, 0xef, 0x8f, 0x2f, 0xfa, 0xbb, 0xb4, 0x6d, 0x7b,
+	0xc6, 0x5f, 0x91, 0xfb, 0xd1, 0x67, 0x38, 0x5e, 0xfb, 0x1e, 0xec, 0xdb,
+	0x39, 0x8b, 0xf6, 0x6d, 0xca, 0x93, 0xab, 0x63, 0xc2, 0xf3, 0x10, 0x0b,
+	0x3c, 0xd0, 0x77, 0x38, 0x82, 0xef, 0xfb, 0x3d, 0xfa, 0x5c, 0x03, 0xac,
+	0x58, 0x88, 0xdc, 0xc1, 0x58, 0x3e, 0xdb, 0xe0, 0x6e, 0x46, 0x70, 0x16,
+	0xc1, 0xfd, 0x11, 0xed, 0x6f, 0x1e, 0xdc, 0xe3, 0x06, 0xf7, 0x47, 0x7a,
+	0x67, 0x59, 0xd7, 0xd5, 0x64, 0xfb, 0x12, 0x90, 0x01, 0xde, 0x3b, 0xe2,
+	0xbd, 0x71, 0xd2, 0xac, 0x73, 0x1d, 0xff, 0x47, 0xdd, 0xd5, 0xc7, 0xb6,
+	0x75, 0x5d, 0xf7, 0xc3, 0x47, 0xea, 0xc3, 0xb4, 0x2c, 0x53, 0x32, 0x25,
+	0xd3, 0x96, 0x2c, 0xbf, 0x27, 0x3d, 0x59, 0x72, 0xac, 0x14, 0xac, 0xab,
+	0xad, 0x02, 0x46, 0xa4, 0x0c, 0x49, 0x7f, 0xb4, 0x08, 0x06, 0xfa, 0xa3,
+	0x99, 0x8b, 0x66, 0xab, 0x4b, 0xd9, 0x4e, 0x0a, 0xf4, 0x0f, 0xb7, 0xc5,
+	0x80, 0x6c, 0x58, 0x60, 0x86, 0xb4, 0x12, 0x63, 0x56, 0x4c, 0xd6, 0x66,
+	0x85, 0x0c, 0xd8, 0x30, 0x4e, 0x54, 0x9c, 0x14, 0x50, 0xc6, 0x04, 0x69,
+	0x83, 0xa2, 0x58, 0x61, 0x45, 0x76, 0x36, 0x6c, 0x7f, 0x65, 0x43, 0xd0,
+	0x05, 0x9b, 0xb3, 0x38, 0x76, 0xb0, 0x06, 0x45, 0xd6, 0x7d, 0x62, 0x18,
+	0xd0, 0x0d, 0xdc, 0xf9, 0xdd, 0x0f, 0xf2, 0xf1, 0xf1, 0x51, 0x1f, 0x89,
+	0x33, 0x60, 0x02, 0x04, 0xbe, 0xf7, 0x78, 0xdf, 0x7b, 0xf7, 0x9e, 0x7b,
+	0xce, 0xb9, 0xbf, 0x73, 0xee, 0x39, 0x87, 0x9e, 0x7b, 0xdb, 0x9b, 0xf3,
+	0xb9, 0xca, 0x77, 0x8e, 0x8a, 0x77, 0x0e, 0x28, 0x9d, 0xa5, 0xe3, 0xc5,
+	0x63, 0xc6, 0x6c, 0x61, 0x22, 0xe2, 0x67, 0xfe, 0x9e, 0xad, 0xc2, 0xbe,
+	0x6e, 0x87, 0xe1, 0xd6, 0xa2, 0x67, 0xbc, 0x85, 0x9e, 0xcd, 0x32, 0xc1,
+	0xf6, 0x78, 0x5d, 0x77, 0x4b, 0xda, 0xc9, 0xeb, 0x88, 0x85, 0xd7, 0x31,
+	0x0e, 0x92, 0x76, 0x75, 0x19, 0xba, 0xe2, 0x8c, 0x6f, 0x68, 0xd0, 0xee,
+	0x74, 0x9d, 0x76, 0x3b, 0xff, 0x1f, 0xd1, 0xee, 0x1d, 0x81, 0x7f, 0x5f,
+	0xad, 0x22, 0x6e, 0x4d, 0x63, 0x00, 0x9d, 0x3b, 0x04, 0x3a, 0x42, 0x9f,
+	0x5a, 0xe5, 0x15, 0x82, 0x4e, 0x45, 0x5c, 0x71, 0xad, 0xf6, 0x5a, 0xb4,
+	0xee, 0xa7, 0x64, 0xbb, 0x04, 0xf6, 0x09, 0xfc, 0x79, 0xed, 0xd7, 0xc8,
+	0x63, 0x1f, 0x6b, 0x8d, 0x04, 0x56, 0x72, 0xdb, 0x27, 0x0c, 0x08, 0x1d,
+	0xf6, 0xc9, 0xb1, 0x4d, 0xda, 0x27, 0xe7, 0xa5, 0x7d, 0x92, 0xdd, 0xb8,
+	0x7d, 0xb2, 0xbb, 0x25, 0xae, 0xab, 0x31, 0x9e, 0xcd, 0xdb, 0x27, 0xc6,
+	0x9a, 0xf6, 0xc9, 0x90, 0xc3, 0x17, 0x83, 0xfe, 0xfe, 0x06, 0x65, 0x8f,
+	0x43, 0xc7, 0x69, 0x3a, 0x83, 0xc6, 0xc7, 0x5d, 0x7e, 0xe1, 0x4f, 0x93,
+	0xd6, 0xbf, 0xf8, 0x3f, 0xa6, 0xf5, 0x50, 0x8b, 0xcf, 0xbb, 0x31, 0x1e,
+	0x0a, 0xef, 0xd8, 0x14, 0x8e, 0x77, 0xd3, 0x7a, 0xa8, 0xad, 0xef, 0xb4,
+	0x7d, 0xcc, 0x62, 0xb3, 0xef, 0x74, 0xd4, 0x68, 0xa7, 0xdb, 0xff, 0xd8,
+	0xe1, 0x53, 0x75, 0xea, 0x77, 0xc8, 0x14, 0xf9, 0x8e, 0x4d, 0xe8, 0x77,
+	0x41, 0x96, 0xac, 0x6c, 0x96, 0x60, 0x33, 0xe1, 0x7d, 0x11, 0x21, 0x6b,
+	0x2e, 0xbc, 0xc5, 0xef, 0x63, 0x7a, 0xbe, 0xf8, 0x87, 0x62, 0x9d, 0x92,
+	0xfe, 0x07, 0xb4, 0x0f, 0xfb, 0xce, 0x88, 0xb6, 0x32, 0xbe, 0x49, 0xf9,
+	0x23, 0x14, 0xf6, 0x6f, 0xe7, 0x87, 0x68, 0x5d, 0xf3, 0x36, 0x67, 0x2b,
+	0x68, 0x19, 0xdf, 0xcb, 0xf3, 0x12, 0x69, 0xb2, 0xb5, 0xa0, 0x3f, 0xcf,
+	0x33, 0x2e, 0x18, 0xad, 0x63, 0x82, 0xe6, 0xb9, 0xb9, 0x28, 0x6c, 0x3a,
+	0xad, 0x3b, 0x57, 0x64, 0xec, 0xa9, 0xb8, 0x0e, 0x9c, 0xa6, 0x75, 0xa7,
+	0x1b, 0x07, 0xef, 0xf5, 0xe0, 0x0b, 0xcf, 0xdc, 0x4f, 0x3d, 0x77, 0x26,
+	0x62, 0xce, 0x53, 0x9e, 0x73, 0x57, 0xcf, 0xe1, 0xca, 0x36, 0xda, 0xca,
+	0xfb, 0x53, 0x62, 0x5c, 0xdf, 0xfc, 0x62, 0x02, 0xb9, 0x6a, 0xf5, 0xfc,
+	0x21, 0x77, 0xce, 0x14, 0xd6, 0x01, 0x2d, 0x87, 0x3a, 0x3f, 0x1b, 0xb4,
+	0x18, 0xf1, 0xc8, 0x99, 0x72, 0xae, 0x25, 0xb8, 0xcf, 0x4d, 0x8b, 0xc6,
+	0x3a, 0x32, 0xa7, 0xd6, 0x91, 0x45, 0x87, 0x1e, 0x6f, 0xc5, 0xed, 0xfd,
+	0x1e, 0xb8, 0xdd, 0x2b, 0x6f, 0x0a, 0x7d, 0x7a, 0x92, 0x71, 0xc8, 0x67,
+	0x80, 0x43, 0x42, 0xc8, 0x5b, 0x92, 0x58, 0x04, 0xdf, 0x17, 0x19, 0x8f,
+	0x44, 0x98, 0x57, 0x7e, 0x44, 0xe7, 0x18, 0x6b, 0x5f, 0xa7, 0xfd, 0xca,
+	0x3e, 0x83, 0xdc, 0xea, 0x38, 0x53, 0xc4, 0xf1, 0xfb, 0x28, 0xfb, 0x98,
+	0x35, 0x19, 0xa7, 0x1f, 0xd1, 0x59, 0x11, 0x33, 0x83, 0xfd, 0x3d, 0xc4,
+	0x1c, 0x3c, 0x20, 0xde, 0x2f, 0x7d, 0x19, 0xf7, 0x23, 0xa6, 0x6e, 0xe3,
+	0xf1, 0xfb, 0x2a, 0xb7, 0x8e, 0xdb, 0xe1, 0x9d, 0x4b, 0x4a, 0xa6, 0xc4,
+	0x35, 0xbe, 0xff, 0x49, 0xa3, 0xf5, 0xfe, 0xb8, 0x91, 0xaa, 0xa6, 0x8c,
+	0x44, 0x05, 0xed, 0x9e, 0x34, 0x92, 0x55, 0xd8, 0x90, 0x9a, 0x47, 0xac,
+	0x28, 0xe4, 0x6d, 0x95, 0xd6, 0xdf, 0x8b, 0x58, 0x24, 0x57, 0x9e, 0xc4,
+	0x06, 0xfa, 0x7d, 0xb8, 0xa9, 0xdf, 0x9a, 0xbe, 0x38, 0x86, 0xbf, 0xe7,
+	0x15, 0xa6, 0xa9, 0xc6, 0xb5, 0x41, 0xf8, 0xd7, 0x27, 0xb3, 0xb4, 0x16,
+	0xae, 0xb5, 0x5a, 0x70, 0xed, 0xe2, 0xba, 0xfd, 0xfe, 0xa4, 0x32, 0x2e,
+	0xf3, 0xa3, 0xfd, 0xb6, 0xc0, 0xaf, 0xdc, 0xef, 0x26, 0x6c, 0xeb, 0xe2,
+	0x29, 0xb4, 0xd1, 0x7e, 0x70, 0xed, 0x07, 0xeb, 0x55, 0xf1, 0xc0, 0x3a,
+	0x3e, 0x21, 0x88, 0x7c, 0xaf, 0x90, 0x8c, 0x6b, 0x85, 0x8d, 0xb5, 0xc2,
+	0xfd, 0x83, 0xbd, 0x05, 0x9f, 0x8f, 0xb0, 0xb7, 0xcc, 0x24, 0x49, 0x5f,
+	0xf7, 0x99, 0xaa, 0xd3, 0xbf, 0xeb, 0x95, 0x4b, 0x39, 0xea, 0x91, 0x4b,
+	0xe9, 0x94, 0xb5, 0x80, 0x43, 0xd6, 0x22, 0x0e, 0xdc, 0x36, 0xcc, 0x76,
+	0x4b, 0x0f, 0xeb, 0x90, 0x1e, 0xb1, 0x6d, 0xe2, 0xbf, 0xea, 0xb4, 0x5b,
+	0xdc, 0x79, 0xf1, 0x90, 0x3b, 0x60, 0x33, 0x69, 0xc3, 0xa4, 0x4a, 0xf5,
+	0x9c, 0x7a, 0x1e, 0x77, 0x23, 0x6f, 0xb1, 0xd2, 0x92, 0x63, 0xe9, 0xd5,
+	0xdf, 0x91, 0x96, 0xfe, 0x62, 0xfd, 0x8a, 0xb7, 0xc5, 0x74, 0x5e, 0x76,
+	0xd5, 0xfd, 0xea, 0x9f, 0x5b, 0x9f, 0xe1, 0x5d, 0xa3, 0xc2, 0xe7, 0x9d,
+	0xad, 0xeb, 0xb2, 0x19, 0xd9, 0xdf, 0x42, 0xb3, 0x9d, 0xe1, 0xbf, 0x42,
+	0x8a, 0x76, 0xde, 0xba, 0x7d, 0x73, 0xfe, 0xb3, 0xad, 0x6e, 0x1c, 0xdc,
+	0x27, 0xfd, 0x62, 0x73, 0x2a, 0x0e, 0x7b, 0x40, 0xd9, 0x7b, 0xeb, 0xf1,
+	0x3b, 0xae, 0xcd, 0x29, 0x5f, 0xa2, 0x65, 0x96, 0x09, 0x7c, 0x7e, 0xfc,
+	0x54, 0x87, 0x1d, 0x52, 0x7b, 0x59, 0xd8, 0xaf, 0x02, 0xdf, 0xeb, 0xe7,
+	0x43, 0x67, 0x6f, 0x64, 0xce, 0xcc, 0x96, 0x39, 0x93, 0x7c, 0x05, 0x5b,
+	0x0b, 0xf1, 0xc5, 0x53, 0xae, 0x18, 0xef, 0x4f, 0x42, 0x8b, 0x5e, 0x8f,
+	0xb8, 0x67, 0xc4, 0x2d, 0xb7, 0xeb, 0xe7, 0x1d, 0x07, 0x2e, 0x47, 0x7f,
+	0x6b, 0xb5, 0x57, 0xa2, 0xbb, 0xe5, 0x5a, 0x5c, 0xf5, 0xc6, 0x48, 0xa1,
+	0x0d, 0xf7, 0xcf, 0xbd, 0xf6, 0xee, 0xda, 0xe0, 0xda, 0x2b, 0xea, 0x8b,
+	0xf8, 0x0e, 0x09, 0x1d, 0xd0, 0x43, 0x95, 0x12, 0xe2, 0xaf, 0x3f, 0x0b,
+	0x99, 0x67, 0x3d, 0xeb, 0xc8, 0x49, 0xf3, 0x9e, 0xc7, 0xfa, 0x9e, 0x4a,
+	0x20, 0x86, 0xbd, 0x3f, 0xc4, 0x96, 0xf4, 0xb3, 0xee, 0x41, 0xfb, 0x71,
+	0xf3, 0x16, 0xfc, 0xbd, 0xca, 0xff, 0x94, 0x52, 0xeb, 0xcb, 0xa1, 0x0d,
+	0xec, 0xad, 0x6c, 0x4e, 0x4f, 0x5b, 0xe6, 0x0a, 0x61, 0xdf, 0x07, 0xf1,
+	0xc2, 0xc7, 0x7a, 0xa9, 0xf7, 0x2b, 0x5d, 0x5d, 0xf6, 0x1f, 0xf4, 0xc9,
+	0xbd, 0x28, 0x7c, 0xd7, 0x43, 0x2f, 0x94, 0x10, 0xcb, 0x8d, 0xef, 0x7e,
+	0x8b, 0xbf, 0xf3, 0xd2, 0x51, 0x3a, 0x16, 0x1d, 0x58, 0x4e, 0xce, 0x4f,
+	0x99, 0x60, 0x2b, 0xd5, 0xe8, 0x6f, 0xa2, 0x9f, 0x93, 0xfb, 0x19, 0xd5,
+	0xfb, 0xbd, 0x57, 0xe3, 0xe5, 0x2f, 0xfc, 0x69, 0xdf, 0xc7, 0x8d, 0x8d,
+	0xfc, 0xd6, 0x86, 0xfc, 0x85, 0xd8, 0xe7, 0xdf, 0xc8, 0x9e, 0x89, 0xde,
+	0x1b, 0x9e, 0x16, 0x39, 0xa7, 0x4e, 0x3e, 0xb8, 0x3f, 0xfb, 0xc3, 0xe0,
+	0x87, 0x91, 0x16, 0x5d, 0xf5, 0xc9, 0xfd, 0xfd, 0x6e, 0xba, 0x06, 0x3d,
+	0x7d, 0x55, 0xde, 0xfb, 0xc0, 0xd8, 0xf3, 0x87, 0x9f, 0xba, 0x4a, 0x67,
+	0xae, 0x81, 0x87, 0x0d, 0xe6, 0xb6, 0x31, 0xca, 0x87, 0x91, 0x57, 0x24,
+	0x72, 0x73, 0xf4, 0xbe, 0xa1, 0xc8, 0x15, 0x3a, 0x23, 0x72, 0x20, 0xc7,
+	0x23, 0xf7, 0x78, 0x3d, 0x3c, 0x53, 0x7d, 0x9b, 0xce, 0x56, 0x82, 0xfc,
+	0xdf, 0xc0, 0xee, 0xad, 0x79, 0x90, 0xcd, 0x3c, 0x7e, 0x4f, 0xf0, 0xf8,
+	0xf0, 0x9a, 0x3c, 0x7e, 0xa4, 0xce, 0xe3, 0x5f, 0xe9, 0x97, 0xfc, 0xdc,
+	0xcb, 0xcf, 0xea, 0xa5, 0x43, 0xe2, 0xb9, 0x6f, 0xf3, 0xf1, 0x56, 0x3a,
+	0x14, 0x92, 0xc7, 0x67, 0x2b, 0xac, 0xe3, 0x0b, 0x6f, 0xd3, 0xb9, 0x6b,
+	0x59, 0x5f, 0x4a, 0xe4, 0x2f, 0x38, 0x6b, 0x69, 0xe8, 0xfb, 0xd1, 0xae,
+	0x1d, 0xff, 0x6b, 0xbd, 0x24, 0x73, 0xae, 0xca, 0x52, 0x3f, 0xd1, 0x5b,
+	0xd1, 0x21, 0x17, 0xff, 0x37, 0xdb, 0x8e, 0xe7, 0xd5, 0x1a, 0x78, 0x7c,
+	0x0d, 0xbf, 0x46, 0x2b, 0x5f, 0xf6, 0x79, 0xe0, 0xe1, 0xa7, 0xfb, 0xe5,
+	0x3e, 0xd5, 0x5a, 0x7e, 0x8d, 0xa6, 0xb8, 0x0e, 0xe7, 0xbe, 0x3d, 0xeb,
+	0xfd, 0x3d, 0x2a, 0x17, 0xf0, 0x87, 0xfd, 0x72, 0xbd, 0x40, 0x7e, 0xe0,
+	0x0a, 0xd3, 0xe1, 0x22, 0x63, 0x95, 0x21, 0xea, 0xbc, 0xaa, 0xc7, 0x3a,
+	0x24, 0xf4, 0xad, 0xd3, 0x4f, 0x73, 0x51, 0xe5, 0x76, 0xe7, 0x1c, 0x63,
+	0xba, 0x28, 0x6c, 0x9c, 0xf6, 0xf2, 0xd6, 0x3e, 0xe6, 0x6a, 0xd8, 0xb5,
+	0x26, 0xb8, 0xf9, 0x0d, 0x75, 0x4a, 0x30, 0xbf, 0x64, 0x48, 0x1c, 0x3c,
+	0xc3, 0xf8, 0x76, 0xb3, 0xfb, 0x45, 0x9f, 0x14, 0x23, 0xba, 0x6b, 0x60,
+	0xb8, 0x8f, 0x31, 0x0f, 0xd2, 0xe6, 0xc8, 0xbc, 0x58, 0x15, 0xba, 0xe0,
+	0xe2, 0x54, 0x8d, 0x92, 0xd1, 0x6d, 0x94, 0x99, 0xe2, 0x77, 0xcf, 0xd8,
+	0x6c, 0x7b, 0xf9, 0x29, 0xcb, 0xf2, 0x9b, 0x99, 0xda, 0xa2, 0xf0, 0xa2,
+	0xf6, 0xa7, 0x77, 0xa9, 0x38, 0x87, 0x5e, 0xb1, 0x2f, 0x29, 0x6b, 0xf5,
+	0xf0, 0x71, 0x45, 0x3f, 0x1b, 0xd7, 0xc1, 0xbb, 0x9d, 0xaa, 0xdd, 0x65,
+	0x47, 0x3b, 0xb4, 0xb9, 0xac, 0xda, 0xe2, 0x99, 0x1a, 0x53, 0x74, 0x2b,
+	0x7d, 0x0b, 0x39, 0x5c, 0x51, 0xb9, 0x7a, 0xc2, 0x7e, 0xa0, 0xd9, 0xfa,
+	0x58, 0x2e, 0x73, 0xdb, 0xff, 0xae, 0xc5, 0x85, 0x2d, 0x77, 0x99, 0x31,
+	0x6f, 0x55, 0xc8, 0x8a, 0xbb, 0x4f, 0x18, 0x8b, 0x5f, 0xec, 0x0f, 0xf1,
+	0xb1, 0x7a, 0xcf, 0xe9, 0x7a, 0x9f, 0x10, 0xa3, 0x61, 0x45, 0xe4, 0xb3,
+	0x74, 0xbb, 0xcb, 0x8e, 0x76, 0x5a, 0x57, 0xe8, 0xfd, 0x87, 0x8f, 0x7c,
+	0xb3, 0x85, 0xdb, 0x3e, 0x19, 0xc3, 0x1b, 0x12, 0xfb, 0xa7, 0x32, 0x46,
+	0x43, 0x1f, 0xc3, 0xbf, 0x8c, 0x98, 0x0a, 0xc4, 0x49, 0x38, 0xf5, 0x8d,
+	0x1c, 0x6f, 0x00, 0x6b, 0x51, 0x15, 0xfb, 0xa6, 0xd8, 0xaf, 0x68, 0x87,
+	0x9d, 0x77, 0x21, 0x36, 0x7f, 0x13, 0x18, 0x74, 0x23, 0xf2, 0x67, 0x7a,
+	0xc8, 0x9f, 0xf3, 0xfd, 0xc8, 0x83, 0x43, 0x3e, 0x5c, 0x76, 0xd2, 0xa0,
+	0x1a, 0xdb, 0x0a, 0x06, 0x95, 0x43, 0x3e, 0x3a, 0x67, 0x5b, 0xd1, 0x8a,
+	0xc0, 0x9a, 0x8f, 0xc0, 0x7f, 0x35, 0xb9, 0x42, 0x07, 0x44, 0xce, 0x38,
+	0x6a, 0x1f, 0x94, 0x79, 0x0d, 0x3e, 0xcd, 0x3c, 0x78, 0x96, 0xed, 0x8f,
+	0xec, 0x49, 0xec, 0xb7, 0xe8, 0x79, 0x41, 0x0e, 0x3c, 0x3e, 0x4d, 0x9e,
+	0xbb, 0xdf, 0xdd, 0x41, 0xc1, 0x38, 0x3f, 0xd3, 0x84, 0x7e, 0xe2, 0xe7,
+	0xa4, 0x29, 0xc1, 0x76, 0x12, 0x6c, 0xd6, 0xd3, 0x27, 0xad, 0x50, 0x99,
+	0x0c, 0x6e, 0x0b, 0xdb, 0x15, 0xcf, 0xc1, 0xfd, 0xf1, 0x50, 0x07, 0xb9,
+	0x73, 0x72, 0x7b, 0x45, 0x9e, 0xe2, 0x5b, 0xd1, 0x07, 0xc9, 0x18, 0x84,
+	0xbe, 0xc2, 0xbc, 0x3d, 0xa0, 0xf6, 0x89, 0xb6, 0xf3, 0xf1, 0x84, 0x3a,
+	0x0e, 0x8a, 0xf9, 0x94, 0xc7, 0x9a, 0xbf, 0xf1, 0xf7, 0xf3, 0x2e, 0xb2,
+	0xfd, 0x6a, 0xfe, 0x9a, 0x62, 0x41, 0x22, 0x63, 0x46, 0x90, 0xce, 0x57,
+	0xd6, 0xf2, 0xbf, 0x78, 0xe5, 0xba, 0x6e, 0xdf, 0x60, 0xae, 0xeb, 0x4f,
+	0x76, 0xc8, 0xdc, 0x32, 0x67, 0x5f, 0xfe, 0x93, 0xfb, 0xe2, 0x85, 0xc9,
+	0x5a, 0x70, 0x22, 0x8f, 0xb7, 0x46, 0x3f, 0x8b, 0x7e, 0x9e, 0xee, 0x84,
+	0x23, 0x2a, 0x66, 0x09, 0x31, 0x4a, 0x0f, 0x2a, 0xbe, 0xd6, 0xba, 0x9f,
+	0x3c, 0x74, 0xff, 0xa3, 0x22, 0x56, 0x53, 0xae, 0x1d, 0x43, 0x8a, 0x1e,
+	0xa0, 0x59, 0xc4, 0x41, 0xb3, 0x01, 0x07, 0xcd, 0x0c, 0x75, 0xbc, 0x4d,
+	0x9c, 0x9f, 0xaf, 0x3c, 0xb5, 0x5d, 0xe6, 0x8b, 0x63, 0x2f, 0xf1, 0x92,
+	0x3a, 0x5e, 0x6f, 0xbc, 0x56, 0x98, 0x82, 0xc2, 0xdf, 0xe4, 0x18, 0xeb,
+	0xcb, 0x44, 0xf6, 0x81, 0x70, 0x2b, 0x0d, 0x5e, 0x73, 0x5c, 0x47, 0x1f,
+	0xc7, 0x1d, 0x7d, 0x1c, 0x75, 0xf4, 0x71, 0x6f, 0x9b, 0x3e, 0xb2, 0x8e,
+	0xe7, 0xf7, 0x9c, 0xad, 0x7e, 0xdc, 0xbe, 0xa2, 0x9f, 0xc8, 0x23, 0x06,
+	0x3d, 0xb7, 0x52, 0x2e, 0x1c, 0x51, 0x6b, 0xc7, 0x2f, 0x55, 0x2e, 0xba,
+	0x57, 0x9f, 0xff, 0x8e, 0xda, 0xcf, 0x9b, 0x93, 0x57, 0x9d, 0xf9, 0xc7,
+	0xdf, 0xa5, 0xa4, 0xcc, 0x23, 0x57, 0xb2, 0x7d, 0xb9, 0x8d, 0x1f, 0x1a,
+	0xf1, 0x1c, 0xc0, 0x20, 0xc2, 0x2e, 0xdc, 0x2d, 0x6b, 0xc1, 0x05, 0x68,
+	0xa9, 0x9e, 0xcb, 0xeb, 0x57, 0xb9, 0x3b, 0xc7, 0xc3, 0xf7, 0x37, 0x8f,
+	0x17, 0xd7, 0xff, 0x4c, 0xf8, 0xf2, 0xe4, 0xfe, 0xd1, 0x8a, 0xca, 0x47,
+	0xb6, 0x4c, 0xc4, 0x06, 0x2c, 0x2e, 0xc3, 0xff, 0xda, 0x2e, 0x77, 0x57,
+	0xea, 0xa2, 0x4c, 0xbd, 0x3e, 0x4a, 0x59, 0xe4, 0x35, 0x48, 0xff, 0x98,
+	0xcc, 0xbf, 0x5d, 0x5c, 0xbe, 0x25, 0x72, 0x5e, 0x13, 0x2a, 0x8f, 0x37,
+	0x43, 0x3d, 0x02, 0xe7, 0x7e, 0xfc, 0xfc, 0xdb, 0x17, 0xc2, 0x9b, 0xcf,
+	0xbf, 0x75, 0xde, 0xb3, 0xb9, 0xfc, 0xdb, 0x10, 0x8f, 0xdd, 0x58, 0x90,
+	0xf9, 0xb7, 0xcd, 0x7b, 0x32, 0x32, 0xff, 0x36, 0xe3, 0xc0, 0x0f, 0x12,
+	0xaf, 0xbf, 0xe5, 0x88, 0xdf, 0x96, 0xb9, 0xb5, 0x8b, 0x75, 0xcc, 0x2a,
+	0x73, 0x6b, 0x65, 0xbc, 0xb7, 0xb3, 0x0e, 0x8c, 0xdc, 0xfb, 0x91, 0xef,
+	0xd9, 0xe6, 0xda, 0xfb, 0x91, 0x39, 0xb5, 0xa6, 0xd1, 0xce, 0x86, 0xc3,
+	0x1a, 0x81, 0x7a, 0x08, 0x71, 0xe6, 0xdd, 0xad, 0x6d, 0xea, 0x21, 0xc4,
+	0xdb, 0xd4, 0x43, 0x70, 0xea, 0x7e, 0x27, 0xc6, 0x02, 0x26, 0xc6, 0xda,
+	0x08, 0x2c, 0x8c, 0x7a, 0x06, 0x51, 0x3a, 0x5f, 0xc7, 0x9e, 0x0f, 0x52,
+	0x5a, 0x61, 0xcf, 0xf3, 0x15, 0xad, 0x8f, 0x46, 0x5d, 0xfa, 0xc8, 0x0b,
+	0x8b, 0x5a, 0x2a, 0xce, 0x47, 0xcb, 0x6b, 0xd6, 0x21, 0xaf, 0x59, 0x0f,
+	0x79, 0xc5, 0x3d, 0xd9, 0x36, 0xfd, 0xfe, 0xa5, 0xba, 0x07, 0xff, 0x4f,
+	0x46, 0x50, 0xb3, 0x85, 0x68, 0xf7, 0x80, 0xc2, 0x7f, 0x0e, 0x79, 0x3d,
+	0xcb, 0xf2, 0xaa, 0xaf, 0xa3, 0xbf, 0xed, 0x6c, 0x00, 0x8d, 0x19, 0x87,
+	0x7c, 0x87, 0xaf, 0xbd, 0x21, 0xe2, 0xa4, 0x9a, 0xed, 0x45, 0x8d, 0x27,
+	0xf6, 0x09, 0x59, 0xba, 0xe3, 0x47, 0xdc, 0x8a, 0xbe, 0x16, 0x52, 0x7e,
+	0x32, 0x4d, 0x8b, 0xce, 0x26, 0xcc, 0xd1, 0xc0, 0x1b, 0x22, 0xc6, 0xd7,
+	0xd1, 0xb7, 0x7f, 0xe5, 0xbe, 0xe9, 0xeb, 0x7a, 0xcd, 0x7c, 0xa7, 0xc9,
+	0x9f, 0x71, 0xa3, 0xa9, 0xee, 0x1f, 0x7c, 0x47, 0xdb, 0xd2, 0x86, 0x9d,
+	0x12, 0x31, 0xa6, 0x7d, 0x36, 0xfc, 0x64, 0x09, 0x96, 0xfd, 0xbe, 0x34,
+	0xe2, 0x99, 0xfb, 0xae, 0x98, 0x74, 0xa2, 0x70, 0x7e, 0x8f, 0xe4, 0x95,
+	0x0b, 0xa2, 0xa6, 0x25, 0x6a, 0x20, 0x26, 0x79, 0x7d, 0x4e, 0x30, 0xe8,
+	0x9c, 0xab, 0x76, 0xd1, 0x22, 0xa3, 0x7b, 0xbf, 0x5d, 0x16, 0xbe, 0x3e,
+	0xd6, 0x49, 0x45, 0xd4, 0x36, 0x35, 0x16, 0x3a, 0xf9, 0xb9, 0x83, 0xb4,
+	0x54, 0x1a, 0x17, 0x35, 0xa1, 0x64, 0x7d, 0x11, 0xb4, 0xf5, 0x51, 0xbf,
+	0xfd, 0x0d, 0xa6, 0xdd, 0xd7, 0x44, 0x8c, 0xe5, 0x62, 0xf1, 0x82, 0xfc,
+	0x2c, 0x3f, 0xa5, 0xde, 0xc1, 0xef, 0xab, 0xfe, 0x98, 0xe2, 0xfd, 0xa6,
+	0xc3, 0x96, 0x73, 0xfe, 0x79, 0xe3, 0x95, 0x63, 0x9b, 0xc2, 0x2b, 0xd9,
+	0x74, 0x03, 0xaf, 0x38, 0x9f, 0xad, 0xb1, 0xcb, 0xe4, 0xa0, 0xac, 0xf7,
+	0x00, 0x1a, 0x6c, 0x05, 0x16, 0x4b, 0x83, 0x96, 0x46, 0xcc, 0x8a, 0x24,
+	0xfc, 0x33, 0x94, 0xaf, 0x5e, 0xa7, 0x4c, 0x11, 0x98, 0x99, 0x3f, 0xcb,
+	0xe7, 0x76, 0x4a, 0x1f, 0x8d, 0xbe, 0x07, 0x7a, 0x65, 0x07, 0xb7, 0xff,
+	0xeb, 0x41, 0x19, 0x97, 0xed, 0xbc, 0xde, 0xcb, 0xd7, 0xbf, 0x10, 0x69,
+	0xbe, 0xbe, 0x85, 0xaf, 0xf7, 0xa7, 0x31, 0x87, 0xc6, 0x15, 0xf8, 0x25,
+	0x27, 0x29, 0xc7, 0xf3, 0x93, 0xaf, 0xf2, 0xda, 0x7a, 0x95, 0xf5, 0x55,
+	0x45, 0xb7, 0x1b, 0x40, 0xce, 0x8e, 0x98, 0x13, 0x83, 0xdb, 0x5c, 0x2c,
+	0x4c, 0x71, 0xbb, 0x21, 0xf2, 0x5f, 0x35, 0x29, 0x5f, 0xd1, 0xbc, 0xaa,
+	0xe3, 0xed, 0xdf, 0x18, 0x90, 0x31, 0x55, 0xef, 0xec, 0x94, 0xf4, 0x9b,
+	0x14, 0x3e, 0x4f, 0xc4, 0x73, 0x3c, 0x23, 0xf8, 0xd0, 0x9a, 0x31, 0xeb,
+	0xef, 0xdf, 0x06, 0xbe, 0x42, 0xdd, 0x54, 0x1e, 0x03, 0xeb, 0xc5, 0x98,
+	0x1d, 0xca, 0xd5, 0x63, 0xd5, 0x9e, 0xdb, 0x2d, 0xef, 0xff, 0xe9, 0x80,
+	0xac, 0x55, 0x7a, 0x5b, 0x9d, 0xeb, 0x35, 0x07, 0xf1, 0xcb, 0x3e, 0x41,
+	0x1b, 0xff, 0x02, 0xf4, 0xa5, 0xc1, 0xc7, 0x3c, 0x9e, 0x34, 0xfa, 0xf8,
+	0xb3, 0x01, 0x5d, 0x9f, 0x50, 0x8e, 0xeb, 0x28, 0xf7, 0x37, 0xc5, 0xe3,
+	0xd2, 0xd7, 0xe3, 0x7c, 0xee, 0x35, 0xbf, 0x78, 0x56, 0x30, 0x2d, 0xeb,
+	0x8b, 0x05, 0xd3, 0x99, 0x49, 0x39, 0xcf, 0x0d, 0x9f, 0x6e, 0xa4, 0xee,
+	0xd3, 0x9d, 0x2b, 0xf4, 0x0f, 0xc2, 0xbf, 0x61, 0x5c, 0xe1, 0xf9, 0x0e,
+	0x3f, 0xc3, 0x6d, 0x91, 0xab, 0x90, 0xe3, 0xcf, 0x1e, 0x15, 0xd7, 0xd3,
+	0xca, 0x2b, 0x32, 0x4e, 0x42, 0xaf, 0x5b, 0xb8, 0x77, 0x80, 0x9f, 0x21,
+	0xd7, 0xae, 0xf6, 0xef, 0xa1, 0x96, 0x38, 0x98, 0x56, 0x1e, 0x5b, 0xcb,
+	0x0f, 0x2b, 0xf6, 0x13, 0x3d, 0xf8, 0x6c, 0xad, 0x7a, 0x06, 0xef, 0x08,
+	0x3f, 0x5a, 0xb2, 0x45, 0x5e, 0x21, 0xc7, 0x01, 0xfa, 0xce, 0x7c, 0x96,
+	0xb6, 0xf0, 0x5c, 0x7d, 0xc3, 0xf8, 0x35, 0xec, 0xb7, 0x93, 0x8c, 0x79,
+	0x62, 0x1a, 0x17, 0xec, 0xc9, 0xb3, 0x06, 0xd3, 0xb9, 0x90, 0xad, 0x05,
+	0xec, 0x1e, 0xea, 0x64, 0x59, 0xfd, 0x22, 0x8d, 0xb1, 0xfd, 0x07, 0x99,
+	0xb5, 0x23, 0x29, 0x82, 0xbc, 0x59, 0xa1, 0xc3, 0xcc, 0x13, 0xc9, 0x2a,
+	0xf8, 0xd9, 0xa0, 0x27, 0x4a, 0x44, 0x8f, 0x97, 0xc6, 0x42, 0xdf, 0x27,
+	0xdb, 0x6c, 0x7c, 0x6f, 0x85, 0x12, 0xdc, 0x8f, 0x54, 0xf5, 0x77, 0xe8,
+	0x43, 0x51, 0xe7, 0x04, 0x74, 0xd4, 0xf3, 0xfe, 0xdb, 0x74, 0x3a, 0x8d,
+	0x7e, 0x6f, 0x5c, 0x3e, 0x4f, 0x6c, 0x4a, 0x3e, 0x83, 0x1e, 0xf2, 0xf9,
+	0xea, 0xa0, 0xe4, 0x9b, 0x1a, 0xf3, 0x68, 0x90, 0x66, 0x8b, 0x88, 0x01,
+	0x7b, 0x18, 0x75, 0xa7, 0x8a, 0x19, 0xd6, 0x4b, 0x99, 0x86, 0x5e, 0xba,
+	0x94, 0xf0, 0xc7, 0x21, 0xe3, 0xa8, 0xcb, 0xa6, 0xe2, 0x7e, 0x30, 0x8e,
+	0xdd, 0x34, 0xb6, 0xb0, 0x95, 0xef, 0xa5, 0x95, 0xc4, 0x74, 0x5c, 0xe5,
+	0xfa, 0x5b, 0x66, 0x92, 0xf5, 0xe3, 0x1c, 0xcb, 0x72, 0xae, 0xf8, 0x00,
+	0x2d, 0x86, 0x87, 0x69, 0x74, 0x41, 0xd7, 0x37, 0xc1, 0x58, 0xff, 0x6d,
+	0x48, 0xea, 0x24, 0x3d, 0xee, 0x5f, 0x11, 0xbe, 0x0b, 0xf3, 0xfa, 0xa7,
+	0x35, 0xee, 0xad, 0xeb, 0xe8, 0xa5, 0xbf, 0x52, 0x32, 0x5b, 0xbb, 0x91,
+	0x88, 0x52, 0x36, 0x31, 0xfd, 0x97, 0x82, 0xff, 0x47, 0xaf, 0xc3, 0x0f,
+	0x07, 0x1d, 0x6d, 0x52, 0xba, 0xe0, 0xa6, 0xc5, 0x30, 0x8f, 0x1b, 0xdf,
+	0xd7, 0xfe, 0x79, 0x36, 0xfa, 0x94, 0x58, 0xfb, 0xc7, 0xae, 0x73, 0x3b,
+	0xb1, 0x36, 0x69, 0xbd, 0xe1, 0xc5, 0x87, 0xba, 0x8e, 0xa5, 0xe6, 0x45,
+	0x19, 0xeb, 0xc9, 0xf8, 0x2d, 0x94, 0xf6, 0xbb, 0x79, 0xf2, 0x23, 0x3a,
+	0x36, 0x6f, 0xd2, 0xf1, 0x82, 0xf5, 0x7c, 0x96, 0x66, 0x58, 0xae, 0x9d,
+	0xeb, 0x05, 0xb7, 0x27, 0xf0, 0x59, 0x8c, 0x65, 0x9f, 0xed, 0xe6, 0xa2,
+	0x29, 0xe3, 0xee, 0x44, 0xed, 0xb9, 0x2e, 0xa1, 0x47, 0x43, 0xf6, 0x3f,
+	0x0d, 0xea, 0xf5, 0x20, 0x53, 0x44, 0x1e, 0x21, 0x7f, 0x96, 0xb9, 0x7d,
+	0x61, 0x90, 0x32, 0x25, 0x3c, 0x07, 0xeb, 0x1d, 0xfa, 0xce, 0xe7, 0x4b,
+	0x72, 0x5e, 0x47, 0xf9, 0xd9, 0xc8, 0xbb, 0x3f, 0x5e, 0x9d, 0x12, 0xb1,
+	0x77, 0xd0, 0xcd, 0x72, 0x3e, 0x63, 0x74, 0xd1, 0x53, 0xaf, 0x28, 0x4c,
+	0xe9, 0x90, 0xef, 0x8c, 0x90, 0xef, 0x98, 0x98, 0x8f, 0x4c, 0xc9, 0x60,
+	0xbc, 0xa6, 0x7d, 0x0f, 0xfd, 0x7c, 0x1e, 0x50, 0x3a, 0x04, 0xdf, 0x0d,
+	0xec, 0x14, 0x71, 0x89, 0x36, 0xae, 0xe3, 0x33, 0x46, 0xcf, 0x30, 0xee,
+	0x7c, 0xb6, 0xd0, 0x45, 0xb7, 0x8a, 0x5d, 0xf4, 0x66, 0x71, 0x98, 0x6e,
+	0xce, 0x6f, 0xa7, 0x8b, 0x8c, 0x99, 0x2f, 0xda, 0x01, 0x33, 0xc7, 0xf6,
+	0xc5, 0x0b, 0x51, 0x11, 0x33, 0xc4, 0x72, 0x87, 0xf6, 0xc0, 0x7f, 0x89,
+	0x5d, 0xcc, 0x73, 0x8c, 0xbd, 0xbb, 0xe9, 0x03, 0x7e, 0x67, 0xae, 0xa0,
+	0x63, 0x1d, 0xe0, 0x93, 0x1f, 0xaf, 0xe3, 0xd7, 0xf5, 0x79, 0x24, 0xb4,
+	0x0e, 0x8f, 0xc4, 0x84, 0xae, 0xcf, 0xcf, 0xf3, 0xf7, 0xf3, 0xf0, 0x9f,
+	0x33, 0xbd, 0x59, 0x3f, 0x7f, 0x3d, 0x80, 0xf6, 0xb8, 0x66, 0xcb, 0x58,
+	0x49, 0x31, 0xb6, 0x08, 0x9f, 0x83, 0xb6, 0x11, 0x45, 0x87, 0x6e, 0x1e,
+	0x9f, 0x4f, 0xb4, 0xcf, 0x2c, 0x75, 0xd3, 0x99, 0x12, 0x63, 0x90, 0x92,
+	0x9f, 0x6d, 0x18, 0xb4, 0x0d, 0xec, 0xd5, 0xf5, 0x5f, 0x2f, 0x72, 0xdf,
+	0x73, 0x25, 0x89, 0x41, 0x72, 0x4b, 0xbd, 0x94, 0x2f, 0xf5, 0xa8, 0xf3,
+	0x07, 0x44, 0x8c, 0xbb, 0xac, 0x63, 0x84, 0xef, 0xd6, 0xd2, 0x6f, 0x6f,
+	0x31, 0x4f, 0x61, 0x4d, 0x95, 0x76, 0x29, 0x74, 0xcd, 0x8d, 0x96, 0xba,
+	0xc4, 0xe0, 0xb9, 0x19, 0xfa, 0x2e, 0xaf, 0xb7, 0xa3, 0x57, 0xe1, 0x3f,
+	0xfe, 0x2a, 0xf8, 0xa6, 0x0c, 0x1e, 0x1b, 0xbd, 0x8a, 0xba, 0x48, 0x7e,
+	0x91, 0xe7, 0x94, 0x0c, 0x4f, 0x8a, 0xdc, 0x10, 0x29, 0xa3, 0x27, 0x45,
+	0x2d, 0xba, 0x1f, 0x0a, 0xdd, 0x64, 0x65, 0x4d, 0x03, 0x78, 0x04, 0x3e,
+	0x18, 0x19, 0x83, 0x75, 0xc2, 0xee, 0x7b, 0x6b, 0x20, 0x36, 0x41, 0xf1,
+	0x41, 0xf0, 0xbd, 0x94, 0x59, 0x55, 0x5f, 0x40, 0xe8, 0xfb, 0xd0, 0x3e,
+	0x9d, 0x2f, 0xa9, 0xcf, 0xf5, 0x5a, 0xa1, 0xcf, 0x7b, 0x5c, 0xdf, 0x87,
+	0x5c, 0xdf, 0xd7, 0xe3, 0xe5, 0x78, 0xcd, 0xe3, 0x75, 0x9e, 0x64, 0x8d,
+	0xa2, 0xcc, 0x82, 0xe4, 0xbf, 0xd0, 0xbe, 0xf1, 0xd0, 0x97, 0x15, 0x06,
+	0xcf, 0x2c, 0x8f, 0x45, 0xfa, 0x8c, 0x1e, 0x7f, 0x66, 0xea, 0xef, 0x6b,
+	0xf1, 0x34, 0x70, 0xd1, 0xdc, 0x4e, 0xa9, 0xe3, 0xd0, 0xaf, 0x6c, 0x14,
+	0xd0, 0xed, 0xe4, 0x72, 0x0f, 0xad, 0x88, 0x9a, 0x5c, 0xc0, 0x18, 0xb8,
+	0x1f, 0xcf, 0xc9, 0x86, 0x3a, 0x08, 0x35, 0xd7, 0x21, 0xe3, 0x07, 0x22,
+	0xd7, 0x79, 0x3e, 0x53, 0xcb, 0xff, 0x55, 0x3b, 0x2d, 0x6a, 0xdc, 0xa0,
+	0x2d, 0x63, 0x48, 0x81, 0xf9, 0x19, 0xbf, 0x34, 0xd9, 0x55, 0x33, 0xe8,
+	0x67, 0x16, 0x7b, 0x2b, 0x86, 0xfd, 0x22, 0xcb, 0x98, 0xdc, 0x2b, 0x4f,
+	0xb9, 0xf6, 0xca, 0x4f, 0x8a, 0xbd, 0x72, 0xec, 0x93, 0x83, 0xae, 0xa0,
+	0xa5, 0x57, 0x4c, 0x0b, 0xe6, 0x31, 0xca, 0xf3, 0x68, 0xd2, 0xc5, 0x6b,
+	0x42, 0xdf, 0x44, 0x93, 0x7e, 0x19, 0x5f, 0x9d, 0xa2, 0xac, 0x88, 0xbf,
+	0x96, 0x9f, 0x71, 0x23, 0x61, 0x5b, 0x93, 0xab, 0x8c, 0x29, 0x2a, 0xc5,
+	0x2d, 0x74, 0xb3, 0xdc, 0xc1, 0x98, 0xef, 0x6f, 0x69, 0xb5, 0x4c, 0x8c,
+	0x0d, 0xb7, 0x53, 0x3e, 0xca, 0xbc, 0x36, 0x19, 0xe4, 0x79, 0x65, 0x7c,
+	0x3b, 0xc9, 0xf2, 0xc7, 0x63, 0xa8, 0x94, 0x6a, 0xef, 0xe7, 0xa2, 0x71,
+	0x33, 0x31, 0xdd, 0xc3, 0xf6, 0x4b, 0x88, 0xff, 0x6d, 0xfe, 0xff, 0x6c,
+	0x04, 0xb4, 0x59, 0x5c, 0xc2, 0xf7, 0x8c, 0x7d, 0x0a, 0xb5, 0xf7, 0x67,
+	0xb9, 0xcd, 0xec, 0x34, 0xec, 0x20, 0xd8, 0x7b, 0x36, 0xff, 0xcb, 0x36,
+	0x15, 0xe6, 0xbb, 0xdc, 0xb5, 0x6c, 0xc4, 0x10, 0x3a, 0x1e, 0x75, 0x5d,
+	0xc6, 0xd4, 0x67, 0xdc, 0x98, 0xe5, 0xbe, 0xdc, 0x24, 0x3c, 0xc3, 0xa4,
+	0x4c, 0x74, 0x1f, 0xcb, 0xc1, 0x76, 0xfe, 0x44, 0x3e, 0xd6, 0x56, 0xca,
+	0x4f, 0x8d, 0xab, 0x7c, 0xac, 0x48, 0x9b, 0x7c, 0x2c, 0xdc, 0xc7, 0x38,
+	0x60, 0xbe, 0x76, 0x6f, 0x36, 0xea, 0x7c, 0x2f, 0x19, 0x99, 0xe8, 0x36,
+	0x81, 0x99, 0x2a, 0x4b, 0xfb, 0xb9, 0x0f, 0x71, 0x33, 0x33, 0xcd, 0x7d,
+	0x2d, 0x39, 0xfb, 0x5f, 0xbb, 0x97, 0x8c, 0xa2, 0x9d, 0xdf, 0xd5, 0x2e,
+	0x4e, 0xa2, 0xed, 0x12, 0xda, 0xd7, 0xfe, 0x27, 0x11, 0xd5, 0xe3, 0x74,
+	0xde, 0x8b, 0xf1, 0x40, 0xbe, 0xf8, 0xb3, 0x72, 0x9b, 0x6e, 0x16, 0x61,
+	0x8f, 0x1b, 0xcc, 0xf7, 0xe8, 0x91, 0x49, 0xd9, 0x0a, 0x63, 0xc0, 0x6b,
+	0x7b, 0x7d, 0xab, 0xc5, 0x37, 0x6a, 0x99, 0xa6, 0xd8, 0x96, 0x66, 0x3f,
+	0xbc, 0xb4, 0xc1, 0x86, 0xc9, 0xbe, 0x82, 0x35, 0x14, 0xeb, 0x67, 0xb6,
+	0xe6, 0xb7, 0x81, 0xf7, 0x60, 0x1b, 0x5d, 0x60, 0xfd, 0x25, 0xe3, 0x93,
+	0x58, 0x97, 0xb2, 0x0e, 0x93, 0xf2, 0x93, 0x6a, 0xfa, 0x39, 0x04, 0xc9,
+	0xc3, 0xa3, 0x8d, 0xb8, 0x48, 0xc7, 0xfe, 0x7a, 0xc0, 0xb1, 0xbf, 0x1e,
+	0x72, 0xc4, 0x45, 0x86, 0x05, 0x3e, 0x6b, 0x60, 0xaa, 0xb0, 0xc2, 0x54,
+	0xc0, 0x5e, 0x52, 0xb7, 0x2d, 0xd6, 0x75, 0xdb, 0x8e, 0x75, 0x74, 0x9b,
+	0x97, 0xad, 0xba, 0xa2, 0xf4, 0x88, 0x15, 0xc5, 0x1a, 0x73, 0x83, 0xf5,
+	0xc5, 0xeb, 0xd5, 0x69, 0xd6, 0x23, 0x51, 0xd6, 0x23, 0x53, 0xac, 0x47,
+	0x26, 0x59, 0x8f, 0xd8, 0x4c, 0x03, 0x93, 0xc7, 0xfe, 0x11, 0xeb, 0x69,
+	0xac, 0x1f, 0x33, 0xf4, 0x4c, 0x15, 0x3a, 0x79, 0x8a, 0x31, 0xd0, 0x47,
+	0xb4, 0x3a, 0xdf, 0xcb, 0xfc, 0x2b, 0x71, 0x4f, 0xb3, 0x5d, 0x83, 0xda,
+	0x2b, 0xf0, 0x17, 0xff, 0x39, 0xf4, 0xce, 0x2b, 0x59, 0x1a, 0xf1, 0xdd,
+	0x2c, 0x82, 0xce, 0xab, 0xa8, 0x55, 0xf1, 0x12, 0x64, 0x1b, 0x35, 0x82,
+	0x7f, 0x30, 0x31, 0xc3, 0x7d, 0x1f, 0xf1, 0xe5, 0x79, 0x5e, 0xbe, 0x1d,
+	0xcd, 0x86, 0xfa, 0x59, 0x06, 0x8e, 0x2b, 0x19, 0x38, 0xde, 0x90, 0x81,
+	0x6c, 0x8e, 0x47, 0xd2, 0xb7, 0xb0, 0x9d, 0xc6, 0x0f, 0x26, 0x76, 0xf5,
+	0xb1, 0xfc, 0x22, 0x66, 0xa2, 0x51, 0xbf, 0xc7, 0x4f, 0xa7, 0xc3, 0x41,
+	0x55, 0xf7, 0xc7, 0x14, 0x39, 0xef, 0xf9, 0xe2, 0xbb, 0x8c, 0x4b, 0x58,
+	0x4e, 0x43, 0x38, 0xbf, 0x0c, 0xbf, 0x28, 0xdb, 0x0d, 0xdd, 0xc2, 0xaf,
+	0xb4, 0x28, 0xda, 0xe2, 0xdc, 0x9a, 0x64, 0x1d, 0x17, 0x5d, 0x31, 0xac,
+	0x99, 0xb8, 0xf1, 0x9b, 0xc3, 0xa8, 0xe1, 0xfe, 0x83, 0xea, 0xe7, 0x86,
+	0xe5, 0xde, 0x5c, 0x72, 0x97, 0xd4, 0x27, 0xcc, 0xa3, 0xe1, 0xb8, 0xb0,
+	0xdd, 0x3a, 0xae, 0xc8, 0xf5, 0x73, 0x91, 0xe7, 0xbb, 0x12, 0x9d, 0xe4,
+	0xf9, 0xee, 0x51, 0x6b, 0x67, 0x96, 0xbf, 0x17, 0xeb, 0x32, 0xaf, 0xa1,
+	0xc3, 0xa8, 0x7f, 0x1f, 0x12, 0x75, 0x22, 0x4e, 0xa2, 0x0e, 0x4f, 0x02,
+	0xcf, 0x63, 0xee, 0x85, 0xfe, 0xf8, 0x07, 0x5e, 0xa3, 0xf1, 0x5e, 0xf0,
+	0x23, 0x1f, 0x97, 0x67, 0xe8, 0x52, 0x41, 0xf7, 0xe1, 0x3d, 0x32, 0xbe,
+	0x8b, 0x7e, 0xf8, 0x68, 0x87, 0xfd, 0x9e, 0xc8, 0x05, 0x31, 0xfe, 0xc4,
+	0xdd, 0xa7, 0xa3, 0xaa, 0x4f, 0xa8, 0x75, 0xd9, 0x85, 0xda, 0x3e, 0x84,
+	0x9a, 0x48, 0x8b, 0xa2, 0x16, 0x65, 0xa7, 0xb0, 0x59, 0x17, 0x85, 0xed,
+	0xb1, 0x7f, 0x57, 0xa3, 0x3e, 0xe6, 0x7e, 0xd7, 0xb5, 0x3b, 0xbc, 0x6e,
+	0x1d, 0x12, 0x18, 0x6d, 0x14, 0xf5, 0xda, 0x45, 0x5e, 0xea, 0x8c, 0xf8,
+	0xce, 0x58, 0xc0, 0x77, 0x0f, 0xa9, 0xef, 0x3e, 0x2f, 0xb0, 0xb1, 0x11,
+	0xeb, 0x66, 0xbd, 0x28, 0xf8, 0x9d, 0xe7, 0xd9, 0x9e, 0x64, 0x7e, 0x8f,
+	0x54, 0xf8, 0xb9, 0xa7, 0x05, 0x3d, 0x35, 0x3d, 0x40, 0x0b, 0xc8, 0x40,
+	0x8f, 0xe2, 0x7f, 0xcb, 0x4c, 0xf9, 0xf5, 0xb8, 0xdb, 0xd1, 0x99, 0xb1,
+	0x4e, 0x01, 0x63, 0xc5, 0x98, 0x4c, 0x5f, 0xbc, 0x1c, 0xf1, 0xe5, 0xe6,
+	0x61, 0xeb, 0x20, 0xdf, 0x65, 0x0f, 0xe2, 0xa9, 0xb8, 0x0f, 0x3b, 0x29,
+	0x9e, 0x46, 0xbf, 0xd0, 0x4e, 0xd3, 0xc0, 0x76, 0xd1, 0xc2, 0x79, 0xdf,
+	0x76, 0x75, 0x5f, 0xb7, 0x98, 0x0b, 0x32, 0xf0, 0x1e, 0xfd, 0x6e, 0xbc,
+	0x17, 0xef, 0xc7, 0x7d, 0x78, 0x9e, 0x7c, 0xee, 0x00, 0xeb, 0xed, 0xc4,
+	0xb4, 0x7c, 0x96, 0x71, 0x5d, 0x7e, 0x37, 0x60, 0x7b, 0xf7, 0x57, 0xce,
+	0x9f, 0x4f, 0xd5, 0xf1, 0xc1, 0xfc, 0x6d, 0xa7, 0xb2, 0xf0, 0x7d, 0xe2,
+	0xbb, 0x11, 0x9f, 0xb0, 0x6b, 0x6d, 0xfe, 0xe4, 0x79, 0x9d, 0xe3, 0xf3,
+	0x33, 0xc5, 0xdb, 0xc2, 0x66, 0xcf, 0xa5, 0x47, 0x7c, 0xe5, 0x32, 0xc6,
+	0x3b, 0xe2, 0x4b, 0xb1, 0x0c, 0x24, 0x8b, 0x89, 0x5a, 0x5e, 0xe2, 0x02,
+	0x3a, 0xdd, 0x6f, 0x85, 0x4e, 0x1b, 0xef, 0x0f, 0xcb, 0x9a, 0xb7, 0x38,
+	0x66, 0x39, 0x2c, 0xb0, 0x1c, 0x16, 0x58, 0x0e, 0x0b, 0x2c, 0x87, 0x6c,
+	0xab, 0xbe, 0x56, 0x60, 0x39, 0xe4, 0xb5, 0xe4, 0x55, 0x5e, 0x4b, 0xa4,
+	0xec, 0xc6, 0x95, 0x7f, 0x53, 0xcb, 0xae, 0x3b, 0x6f, 0x53, 0xcb, 0x2a,
+	0xd6, 0x6f, 0xf2, 0x1d, 0x99, 0x68, 0x96, 0xd9, 0x5b, 0x2c, 0xb3, 0x1d,
+	0xb1, 0x41, 0xba, 0x5b, 0xc2, 0x9c, 0x59, 0xe6, 0x1c, 0xeb, 0xea, 0x94,
+	0x1f, 0x58, 0x2b, 0xc0, 0xf2, 0x04, 0xac, 0x69, 0x31, 0xdd, 0x07, 0xe9,
+	0x1e, 0xeb, 0xeb, 0xbb, 0x25, 0xc8, 0xf0, 0x1e, 0x75, 0x6e, 0xb1, 0x0c,
+	0x63, 0xfd, 0xb3, 0x7d, 0xb7, 0x8a, 0x06, 0x63, 0xb2, 0x40, 0x28, 0x43,
+	0xd0, 0xa7, 0x02, 0xa7, 0xf1, 0xbc, 0xaf, 0xb0, 0xde, 0x87, 0x0f, 0x0f,
+	0xeb, 0xc5, 0x19, 0x1f, 0xaf, 0x17, 0x91, 0x9b, 0xac, 0x4f, 0xcf, 0x97,
+	0x6c, 0x96, 0xfb, 0x7e, 0xfa, 0x56, 0x09, 0xeb, 0x34, 0x68, 0xc4, 0xe7,
+	0x65, 0x12, 0xbe, 0x31, 0x23, 0x86, 0xb1, 0x8f, 0x67, 0x0d, 0xc1, 0x27,
+	0x7f, 0x0a, 0x3a, 0x30, 0xed, 0x5f, 0xdc, 0x85, 0xda, 0xf3, 0x71, 0xa3,
+	0x53, 0xf9, 0x1a, 0x71, 0x8c, 0xf6, 0x68, 0x0b, 0xba, 0xe1, 0xbc, 0xdd,
+	0xbe, 0x24, 0x7e, 0xb3, 0x21, 0x0a, 0xff, 0x9b, 0x4b, 0x7f, 0x5d, 0xe2,
+	0xfb, 0x05, 0xbd, 0x66, 0x12, 0x7e, 0xe4, 0x90, 0xd3, 0xd3, 0xfe, 0xd8,
+	0x0c, 0x3d, 0x5b, 0x45, 0xbf, 0xaf, 0x52, 0x3e, 0x0c, 0x7d, 0x64, 0x45,
+	0xef, 0x90, 0xa4, 0x5d, 0x37, 0xe3, 0xce, 0x27, 0xbc, 0x75, 0x9c, 0x99,
+	0x10, 0x38, 0xb9, 0x8b, 0xf5, 0x0b, 0x68, 0xf3, 0x13, 0xe6, 0x35, 0x7e,
+	0x5f, 0x41, 0xeb, 0xb7, 0x1f, 0xb3, 0xce, 0xc1, 0x9c, 0xe1, 0x7c, 0x6d,
+	0x9d, 0xb6, 0xaa, 0x74, 0x9a, 0xed, 0xd0, 0x69, 0xb9, 0xba, 0x4e, 0x63,
+	0xde, 0x10, 0xba, 0x0c, 0xba, 0xea, 0x51, 0xc6, 0x91, 0xf2, 0x18, 0xf8,
+	0x70, 0x87, 0xd0, 0x5d, 0xac, 0xfb, 0xd9, 0xae, 0x58, 0xac, 0x66, 0x7d,
+	0x87, 0x85, 0x0e, 0xd1, 0xfc, 0xbd, 0x7f, 0xb7, 0x94, 0x8b, 0x6e, 0xa1,
+	0x0f, 0x72, 0x27, 0xa1, 0xb7, 0xbc, 0xda, 0x8f, 0x73, 0x3b, 0xb4, 0xb7,
+	0x23, 0x2f, 0xb1, 0x3e, 0x5b, 0x8c, 0xc2, 0xa6, 0xed, 0x51, 0xb6, 0x0f,
+	0xea, 0x72, 0x61, 0xaf, 0x0b, 0x63, 0xd5, 0xfa, 0x6c, 0x40, 0xf9, 0x35,
+	0xe0, 0x87, 0xc4, 0x9c, 0xb7, 0xc5, 0x08, 0x26, 0x30, 0x02, 0xdf, 0x13,
+	0x60, 0x7a, 0x89, 0x1a, 0xe2, 0x44, 0xef, 0xd2, 0xaa, 0x90, 0x8d, 0x77,
+	0x05, 0x76, 0xc9, 0xf3, 0x77, 0xb3, 0xd3, 0x07, 0x45, 0x3f, 0xf3, 0x4b,
+	0x0d, 0xfd, 0x38, 0x57, 0x78, 0x0f, 0xeb, 0x86, 0xe8, 0x6b, 0x65, 0x42,
+	0xea, 0xc0, 0xc5, 0x32, 0x6a, 0x80, 0x89, 0x3e, 0x73, 0x5f, 0xf5, 0x38,
+	0xd1, 0x0f, 0xad, 0x0f, 0x36, 0x22, 0x7b, 0x8c, 0x6b, 0xfb, 0x31, 0x47,
+	0x59, 0x07, 0x0f, 0x3d, 0xcb, 0xef, 0xc7, 0xb5, 0xf5, 0xc7, 0x73, 0xaf,
+	0x3e, 0x1e, 0xf8, 0xf6, 0x70, 0xcf, 0xbb, 0x74, 0x57, 0x8d, 0xe7, 0x6e,
+	0x7d, 0x3c, 0xcf, 0xa8, 0xf1, 0x50, 0xce, 0x88, 0x0d, 0x28, 0xdc, 0xbf,
+	0xe1, 0x67, 0x77, 0x27, 0x18, 0xc7, 0xe4, 0x96, 0x40, 0xe7, 0xfd, 0x8a,
+	0x9f, 0x9c, 0x7e, 0x54, 0x67, 0x5f, 0xad, 0xc9, 0x3b, 0xac, 0x7f, 0xef,
+	0x09, 0x1c, 0x33, 0xc2, 0x38, 0x06, 0xd7, 0x29, 0x0f, 0x3d, 0x9d, 0x0b,
+	0xa3, 0x4e, 0xed, 0x0c, 0x8f, 0x9b, 0xed, 0xb1, 0x69, 0xfe, 0x14, 0xfe,
+	0x35, 0x3c, 0x47, 0xdf, 0xff, 0x3c, 0xdd, 0x9b, 0x87, 0x2e, 0x07, 0x8e,
+	0x95, 0xb5, 0x6c, 0xef, 0x2d, 0x4b, 0xff, 0x6e, 0xca, 0xd3, 0xbf, 0x0b,
+	0xdf, 0xee, 0x34, 0x70, 0x7e, 0x08, 0x7e, 0xe0, 0xa4, 0xfa, 0xad, 0x8f,
+	0x5c, 0x15, 0xcf, 0xf2, 0xd2, 0x4b, 0x33, 0x8e, 0xd8, 0x38, 0xc4, 0xaa,
+	0x64, 0x59, 0xcf, 0xd8, 0xa1, 0x0e, 0x43, 0xe6, 0xdc, 0xdc, 0xa8, 0x6a,
+	0xec, 0x74, 0x94, 0xe7, 0xcc, 0x8e, 0x1a, 0x46, 0x4a, 0xf8, 0x1a, 0xba,
+	0xed, 0x1e, 0xea, 0xe2, 0x75, 0xf4, 0x2c, 0xa1, 0x96, 0x9a, 0x65, 0x62,
+	0x0f, 0xe0, 0x12, 0xf3, 0x64, 0x3e, 0x6a, 0x45, 0x1e, 0x17, 0x76, 0x29,
+	0xd6, 0x17, 0x03, 0x74, 0x62, 0x5a, 0xa3, 0x0f, 0x7c, 0xbc, 0x84, 0x3a,
+	0x9a, 0x51, 0x1e, 0x3f, 0xfc, 0xc7, 0x63, 0xe6, 0x9b, 0xbc, 0x2e, 0x5d,
+	0x12, 0x7e, 0x99, 0x0b, 0x94, 0x63, 0x39, 0x3d, 0x22, 0xe4, 0xd4, 0x18,
+	0x61, 0x29, 0x62, 0xb9, 0x42, 0x6c, 0xc2, 0xb8, 0xa8, 0xdb, 0x23, 0x6d,
+	0x1d, 0x1e, 0xe5, 0xb2, 0xaa, 0x87, 0x90, 0x86, 0xee, 0xd8, 0xb8, 0x4f,
+	0x22, 0xfd, 0x89, 0x7d, 0x31, 0x4e, 0x4c, 0xe6, 0xf6, 0x7d, 0xc3, 0xae,
+	0x33, 0x45, 0xbd, 0x48, 0xd0, 0x4e, 0xf8, 0x13, 0x8d, 0x29, 0xa6, 0x9b,
+	0xfe, 0xdd, 0x19, 0xa7, 0xdf, 0xe0, 0x9c, 0xc8, 0xeb, 0x7f, 0xa5, 0x2a,
+	0xd7, 0xe0, 0x1c, 0xdb, 0xf4, 0xf9, 0x83, 0x4e, 0x4c, 0x62, 0x15, 0x93,
+	0xc2, 0x97, 0xb3, 0x9b, 0x12, 0x0b, 0x53, 0xf4, 0x68, 0x01, 0x3a, 0x8c,
+	0xee, 0x24, 0x6c, 0xfc, 0xa2, 0x0c, 0x64, 0x7c, 0x8a, 0x52, 0x55, 0xd0,
+	0xc8, 0xc7, 0x58, 0x89, 0x79, 0xaf, 0x88, 0x3d, 0x7f, 0x3e, 0x2e, 0xe3,
+	0x77, 0x54, 0x7e, 0x5d, 0xf9, 0xcb, 0x87, 0x29, 0xb9, 0x40, 0xd9, 0x4c,
+	0xf4, 0x4b, 0xa2, 0xd6, 0x75, 0x26, 0x3a, 0xa1, 0x7c, 0x3b, 0x11, 0xbe,
+	0x0e, 0x7f, 0x99, 0x49, 0x5f, 0x2e, 0x58, 0xd9, 0x0c, 0x49, 0x9f, 0x05,
+	0x71, 0x1f, 0x0c, 0x5e, 0x7b, 0x77, 0xb0, 0x0e, 0x39, 0x21, 0xfc, 0x16,
+	0x8c, 0x54, 0xe6, 0xd1, 0x1e, 0x3e, 0x87, 0x7e, 0x82, 0x9d, 0x96, 0x29,
+	0x3e, 0xa5, 0xda, 0xd6, 0x28, 0xc4, 0xbc, 0x10, 0xfa, 0x55, 0x3b, 0x1b,
+	0x35, 0x1a, 0xf7, 0xc3, 0xe7, 0x71, 0x42, 0xe0, 0xc8, 0x11, 0xb6, 0x79,
+	0x44, 0xbb, 0xda, 0xac, 0xf0, 0x5f, 0xf0, 0x79, 0xf9, 0x81, 0x21, 0xfd,
+	0x9b, 0x08, 0xb8, 0x2e, 0xfd, 0x1a, 0xfc, 0xcc, 0x32, 0xf7, 0xa3, 0x29,
+	0x9e, 0x7e, 0x98, 0xe2, 0x9b, 0xf0, 0x33, 0x9d, 0xbc, 0xaf, 0x7e, 0x26,
+	0xa6, 0x35, 0xaf, 0x3d, 0x37, 0x58, 0x36, 0x5e, 0x5f, 0xd7, 0xfe, 0xfb,
+	0x50, 0xaf, 0xe1, 0x4c, 0xab, 0x90, 0xf8, 0xdd, 0x0c, 0x60, 0xf0, 0x7c,
+	0xf5, 0x71, 0xfc, 0x5e, 0x8c, 0x2f, 0x2d, 0xb0, 0x71, 0x84, 0xb1, 0x0d,
+	0x30, 0xce, 0x98, 0xd8, 0x17, 0x8b, 0x3f, 0x16, 0xf1, 0xe5, 0x97, 0x07,
+	0xc9, 0x0f, 0x7f, 0x9c, 0xad, 0x63, 0x29, 0xba, 0x45, 0xdc, 0xbb, 0xdc,
+	0x8f, 0xc4, 0xfa, 0x0c, 0x9d, 0x78, 0x87, 0xed, 0x86, 0x09, 0x15, 0x87,
+	0xd3, 0x21, 0x6a, 0x53, 0xc9, 0xbd, 0x54, 0xad, 0x53, 0x34, 0xef, 0xe9,
+	0xbd, 0x0e, 0xe7, 0x6f, 0x73, 0x41, 0x76, 0x9d, 0x98, 0x02, 0xfe, 0x29,
+	0x31, 0x47, 0x97, 0x88, 0xe4, 0x1c, 0x37, 0xf6, 0x31, 0xba, 0x78, 0x9e,
+	0x60, 0x0f, 0xc2, 0xef, 0xf7, 0x35, 0xfe, 0xc4, 0x7e, 0xc4, 0xd5, 0x21,
+	0xe0, 0xa8, 0x3e, 0x9b, 0x79, 0x66, 0x1a, 0xe7, 0x83, 0x6c, 0x9f, 0x69,
+	0xdc, 0x2b, 0x7d, 0x51, 0x6c, 0xb3, 0xa9, 0xf9, 0x82, 0x1f, 0x6a, 0x54,
+	0xd5, 0x29, 0xb0, 0xc8, 0xec, 0x07, 0x9d, 0x3e, 0x2d, 0x79, 0x5c, 0x6f,
+	0xef, 0x62, 0x23, 0xb1, 0x4e, 0xf8, 0xdd, 0x30, 0xd4, 0xeb, 0xdc, 0x0b,
+	0xda, 0xf3, 0x1c, 0x39, 0xf7, 0x36, 0x1e, 0xdf, 0xa5, 0x7f, 0xb3, 0xe8,
+	0xfe, 0xcc, 0xdb, 0x16, 0x8f, 0x79, 0xfb, 0xf9, 0x90, 0xdc, 0x3b, 0x7b,
+	0x58, 0xb5, 0xf1, 0x8a, 0x6f, 0x5d, 0xfe, 0x0e, 0xfc, 0x50, 0x8d, 0xfc,
+	0x8b, 0x77, 0x84, 0x5e, 0x69, 0xf5, 0x85, 0x47, 0x58, 0x9f, 0x4a, 0x39,
+	0x3e, 0xe1, 0x21, 0xc7, 0xfd, 0x31, 0xe0, 0x96, 0x8f, 0x2f, 0xc7, 0xc7,
+	0xdb, 0xca, 0xf1, 0x9e, 0x61, 0xe9, 0x8b, 0x6d, 0x95, 0x63, 0xe4, 0x00,
+	0x9d, 0xa8, 0xb6, 0xf3, 0x7b, 0x61, 0x1e, 0x90, 0xcb, 0xee, 0xf4, 0x95,
+	0x80, 0x66, 0xda, 0x5f, 0x82, 0x7d, 0x43, 0xf0, 0x25, 0xf6, 0x5e, 0x4e,
+	0x1a, 0xa9, 0x79, 0xf7, 0x5e, 0xea, 0x46, 0xee, 0xbd, 0xed, 0x71, 0x2f,
+	0xb0, 0x3b, 0x64, 0xc3, 0x8a, 0x48, 0x5f, 0x80, 0xa6, 0xdf, 0xb0, 0xef,
+	0x70, 0xc9, 0xca, 0x96, 0x09, 0xbe, 0xee, 0x30, 0x9d, 0xc3, 0xfe, 0xb4,
+	0xf2, 0x25, 0x1f, 0x2b, 0x48, 0x3a, 0x84, 0x0e, 0x0a, 0xfe, 0x00, 0xbe,
+	0x8d, 0xa4, 0xfd, 0x69, 0x9e, 0x63, 0xe9, 0x47, 0xce, 0x2c, 0x45, 0xd4,
+	0xbc, 0x71, 0x5b, 0x3c, 0xcf, 0x33, 0x5f, 0x10, 0xf3, 0x65, 0x3d, 0xbf,
+	0x52, 0x8f, 0x4f, 0xc6, 0xda, 0x50, 0xa3, 0xff, 0xe0, 0x75, 0xcf, 0x7f,
+	0x30, 0x24, 0x6a, 0x37, 0xdc, 0xa8, 0x1e, 0x64, 0xbc, 0x89, 0x39, 0x85,
+	0x0f, 0x52, 0xfb, 0x88, 0x1f, 0xda, 0x4b, 0xbd, 0x07, 0x18, 0x05, 0x18,
+	0x64, 0x33, 0xbe, 0x34, 0x0e, 0x22, 0xce, 0xdc, 0xe4, 0x7b, 0x50, 0x73,
+	0x6a, 0xdc, 0x4c, 0x51, 0x0f, 0xfc, 0x10, 0xa8, 0x25, 0x6d, 0xe6, 0x9a,
+	0x64, 0xec, 0x94, 0x90, 0xb1, 0xd4, 0xf2, 0x29, 0x25, 0x63, 0xa7, 0x94,
+	0x1f, 0xfe, 0x94, 0x92, 0xb1, 0x53, 0x4a, 0xc6, 0x4e, 0x29, 0x19, 0x3b,
+	0xc5, 0x7c, 0x3e, 0xc6, 0xf8, 0x16, 0x58, 0x44, 0xfb, 0x41, 0x7b, 0x29,
+	0x53, 0xc2, 0x75, 0xac, 0xcf, 0x6e, 0x39, 0x7b, 0x69, 0x44, 0xca, 0x19,
+	0x63, 0x13, 0x19, 0xaf, 0xc7, 0xef, 0xc2, 0x1c, 0xfc, 0x1e, 0xd3, 0xef,
+	0x23, 0x3a, 0x33, 0x8f, 0xbe, 0xfa, 0x28, 0x29, 0x6a, 0xc9, 0x76, 0x50,
+	0xc2, 0x89, 0x85, 0x43, 0xc8, 0x0f, 0x93, 0xb6, 0x5f, 0xb6, 0x6d, 0xae,
+	0x98, 0xe6, 0x93, 0x98, 0x9a, 0x2f, 0xb7, 0x5d, 0xd4, 0x45, 0xe9, 0x22,
+	0xe8, 0x8a, 0x98, 0x4a, 0x93, 0xe7, 0x46, 0xd0, 0x49, 0x86, 0x44, 0xb9,
+	0x68, 0x70, 0x4c, 0xd1, 0xe0, 0xdb, 0x62, 0x8c, 0x88, 0x49, 0x84, 0x2f,
+	0xb3, 0x3d, 0x1d, 0x72, 0x85, 0x31, 0x7e, 0x0e, 0xcb, 0xc2, 0xc1, 0x08,
+	0xeb, 0xa4, 0x8d, 0xd3, 0xa1, 0x31, 0xf6, 0x76, 0xba, 0x67, 0xa3, 0x79,
+	0x39, 0x77, 0x1c, 0x6b, 0x49, 0x44, 0xad, 0x23, 0x12, 0x17, 0x6f, 0xb1,
+	0x6b, 0x74, 0x34, 0xba, 0x97, 0x8f, 0xad, 0x74, 0x96, 0x0e, 0x90, 0xd1,
+	0x57, 0xa3, 0xbf, 0x60, 0x39, 0xe8, 0x66, 0x39, 0x38, 0xaa, 0xec, 0x92,
+	0xa3, 0x75, 0xbb, 0x64, 0xcf, 0x1e, 0xc4, 0x65, 0x64, 0xc4, 0xbe, 0xd7,
+	0x56, 0x55, 0x43, 0x00, 0xbe, 0x6f, 0x9c, 0x77, 0x51, 0x7c, 0x18, 0xe7,
+	0xf8, 0x2d, 0x22, 0x6b, 0x32, 0xee, 0x1b, 0xdf, 0x23, 0xb0, 0xbb, 0xcf,
+	0xc2, 0x3d, 0x47, 0xa5, 0xde, 0xf3, 0x91, 0x7f, 0xfc, 0x36, 0xe3, 0x89,
+	0x1a, 0x3d, 0xc1, 0xef, 0xcc, 0x17, 0xf7, 0xf1, 0xb3, 0x75, 0x4d, 0x09,
+	0x3b, 0x6e, 0xf8, 0xb6, 0x92, 0xbf, 0xaf, 0xdd, 0xbb, 0x2d, 0xc1, 0x8f,
+	0x8c, 0xa7, 0x8d, 0xd9, 0xe8, 0x7b, 0xb5, 0xd3, 0x27, 0xe1, 0x63, 0x87,
+	0x9c, 0x58, 0x21, 0xd3, 0xe7, 0x25, 0x1f, 0x12, 0x2b, 0x35, 0xe2, 0x63,
+	0x21, 0x2f, 0x35, 0xfa, 0x77, 0x1e, 0x5b, 0x88, 0xb0, 0x77, 0x22, 0x9f,
+	0x9f, 0xa6, 0x19, 0x91, 0x83, 0x8d, 0x38, 0xe9, 0x33, 0xf3, 0xfa, 0x5d,
+	0xb6, 0xe2, 0x8d, 0xcf, 0x20, 0xce, 0xad, 0xb8, 0x48, 0x6b, 0xaf, 0x39,
+	0xf0, 0xd7, 0x8d, 0x2d, 0xac, 0xf6, 0x85, 0x45, 0x4e, 0xf8, 0x76, 0xc6,
+	0x48, 0x3a, 0x1e, 0x7a, 0x9c, 0x9f, 0x0f, 0x3f, 0x5e, 0x80, 0x92, 0x57,
+	0xd0, 0xae, 0x93, 0x46, 0x17, 0x6a, 0x5f, 0xe0, 0xef, 0xc5, 0xfe, 0x65,
+	0x86, 0xba, 0xd5, 0xde, 0x44, 0x8f, 0xda, 0xcf, 0x8a, 0xb0, 0xec, 0x35,
+	0x72, 0x9d, 0x47, 0xeb, 0x3e, 0x3d, 0xc8, 0x84, 0xdb, 0xa7, 0xf7, 0xf4,
+	0x3a, 0xeb, 0xd5, 0x7a, 0x72, 0x80, 0x58, 0xd6, 0x2e, 0x52, 0xbe, 0x4a,
+	0x33, 0x4f, 0x1b, 0xcd, 0xe9, 0xdb, 0xf4, 0x3d, 0xdd, 0x9d, 0x31, 0xf3,
+	0xc2, 0x9b, 0x76, 0x50, 0xf1, 0x5f, 0x27, 0x9d, 0x29, 0x05, 0x79, 0xcd,
+	0x87, 0x6e, 0x05, 0xbd, 0xfc, 0xc3, 0xc8, 0x73, 0xf9, 0x7a, 0xa0, 0x93,
+	0x96, 0x96, 0x10, 0x6b, 0xf1, 0x47, 0x7b, 0x64, 0x7c, 0x71, 0x9a, 0xe9,
+	0x72, 0x80, 0xd7, 0x47, 0x43, 0xed, 0x1d, 0xe1, 0x1a, 0x74, 0x89, 0xa8,
+	0x37, 0x1a, 0xf8, 0xd2, 0x44, 0x90, 0xed, 0x02, 0xb9, 0xf7, 0x70, 0x88,
+	0x9f, 0xfd, 0xfd, 0x52, 0x1a, 0xfe, 0xb2, 0xd0, 0x11, 0x7e, 0x7e, 0x92,
+	0xf1, 0x44, 0x9c, 0x3a, 0xa9, 0xb2, 0xd4, 0xc9, 0x76, 0x41, 0x27, 0xe3,
+	0x89, 0xb1, 0xd0, 0xa8, 0x4f, 0xbc, 0x4b, 0xe4, 0xd4, 0x3c, 0x1c, 0x38,
+	0xc0, 0x7c, 0x85, 0x77, 0xbd, 0xae, 0xde, 0xe5, 0x7e, 0xc7, 0x2f, 0x6a,
+	0x38, 0x3f, 0xe2, 0x37, 0x2f, 0xdc, 0xc2, 0xef, 0x51, 0xcd, 0xcf, 0x30,
+	0x76, 0x0e, 0x53, 0x7e, 0xbe, 0x83, 0xc7, 0x10, 0x63, 0x3b, 0x22, 0xca,
+	0xe7, 0x8f, 0x50, 0xb6, 0x7a, 0x92, 0x7e, 0xbf, 0xea, 0xf4, 0x09, 0x3f,
+	0xc2, 0x7d, 0x96, 0x39, 0xfd, 0x5d, 0xdc, 0xaf, 0x0f, 0x6d, 0xb7, 0x8e,
+	0x09, 0x92, 0xff, 0x7b, 0x61, 0xea, 0x7c, 0x0e, 0xbe, 0x97, 0x1a, 0x15,
+	0xa3, 0xd6, 0xa5, 0x3b, 0x24, 0xfd, 0xcf, 0x2f, 0x88, 0xb8, 0x5a, 0xbe,
+	0x9f, 0x9f, 0x39, 0x87, 0x76, 0x2f, 0x98, 0x74, 0xd3, 0x96, 0xf4, 0x7e,
+	0x23, 0x10, 0x26, 0xff, 0xcb, 0x88, 0x7d, 0x02, 0x56, 0x33, 0x2f, 0xd8,
+	0xfb, 0x58, 0xbf, 0x3f, 0x87, 0xfb, 0xf8, 0xf3, 0x65, 0x9c, 0x07, 0x79,
+	0x9c, 0x58, 0xaf, 0x11, 0xef, 0x02, 0xbd, 0x78, 0x20, 0x12, 0x12, 0xfc,
+	0xf7, 0x08, 0xf3, 0x54, 0x87, 0xf0, 0x35, 0xf6, 0xa3, 0xad, 0x3d, 0xc4,
+	0xd8, 0xc2, 0xbc, 0x30, 0xb1, 0x0f, 0xe7, 0xf1, 0x3e, 0x3f, 0xd3, 0x48,
+	0xf2, 0x10, 0xc6, 0xd3, 0xc4, 0xdc, 0x81, 0x43, 0x13, 0xc4, 0xf3, 0x09,
+	0xfc, 0xc1, 0xf3, 0x19, 0x42, 0x7d, 0xa7, 0x20, 0xa5, 0xf8, 0x1d, 0xc9,
+	0x92, 0x1c, 0xf7, 0x5c, 0xd5, 0x4f, 0xd2, 0x4f, 0x75, 0x74, 0x44, 0xff,
+	0x9e, 0x21, 0x0d, 0xe2, 0xd9, 0x5a, 0x56, 0x70, 0xdc, 0x4b, 0x77, 0x4b,
+	0x3d, 0x74, 0x4f, 0xed, 0x69, 0xdd, 0x15, 0x76, 0x19, 0xeb, 0xf0, 0x74,
+	0x2f, 0xdd, 0x59, 0xea, 0x20, 0xea, 0x0f, 0x8a, 0x3d, 0xe7, 0xbb, 0xa5,
+	0x32, 0xbf, 0x3f, 0x31, 0x22, 0xfd, 0x3a, 0x0d, 0x1e, 0xb9, 0xeb, 0xc1,
+	0x23, 0x1f, 0x08, 0x1e, 0xd9, 0x37, 0xb2, 0x36, 0x8f, 0xec, 0x52, 0xb6,
+	0x48, 0x90, 0x3a, 0x15, 0x7f, 0xbc, 0xc4, 0xfc, 0xf1, 0x2c, 0xf3, 0xc7,
+	0xe1, 0x36, 0xfc, 0x61, 0xb8, 0xf8, 0xe3, 0x88, 0xe0, 0x8f, 0x87, 0x46,
+	0xd6, 0xe2, 0x8f, 0xc3, 0xfe, 0xb5, 0x7c, 0x4d, 0xe2, 0xb7, 0x3c, 0x2f,
+	0xcc, 0xd9, 0xbb, 0x99, 0xd7, 0x6d, 0xaa, 0xcc, 0x23, 0x67, 0x61, 0x25,
+	0x6a, 0xd0, 0xbf, 0x08, 0x9b, 0x6c, 0x55, 0xd8, 0xfc, 0x31, 0x11, 0xc3,
+	0xba, 0x28, 0xf8, 0x8b, 0xd7, 0xff, 0x18, 0x72, 0xaa, 0xdc, 0x73, 0xd1,
+	0x4d, 0x37, 0xa3, 0x98, 0x0b, 0x53, 0xcd, 0x05, 0xae, 0x75, 0xe9, 0xfa,
+	0x90, 0x01, 0xbe, 0x7e, 0xe1, 0x03, 0xf0, 0xe8, 0x72, 0x4f, 0x20, 0x59,
+	0xf8, 0xe6, 0x08, 0xf0, 0x5f, 0x7e, 0x99, 0x1c, 0xd7, 0x03, 0x7c, 0x3d,
+	0x2c, 0x7e, 0xfb, 0x09, 0xb2, 0xf2, 0x8f, 0x88, 0x71, 0x64, 0x9e, 0xbc,
+	0x59, 0x1a, 0xa6, 0x5b, 0xa5, 0xdd, 0xb4, 0x5a, 0x1a, 0xa1, 0x37, 0x45,
+	0x2d, 0x0d, 0x99, 0x1b, 0xb9, 0x2a, 0xe6, 0xc8, 0xa0, 0x43, 0x61, 0x6e,
+	0xb3, 0xb4, 0x9b, 0x56, 0x96, 0x34, 0x7f, 0x83, 0xb7, 0xc1, 0x2f, 0xf1,
+	0x3e, 0x99, 0x2f, 0xd7, 0xca, 0x33, 0xc9, 0x26, 0x9e, 0x91, 0xf7, 0x80,
+	0x57, 0xf2, 0xad, 0xb9, 0xbe, 0xdd, 0xa1, 0x18, 0x62, 0xf5, 0x82, 0xd4,
+	0x81, 0xb8, 0x45, 0xc3, 0x9a, 0x3c, 0xe4, 0x07, 0x86, 0xfe, 0x2a, 0xaf,
+	0xb9, 0x3c, 0x67, 0x36, 0xe2, 0x9c, 0x46, 0x18, 0x0f, 0x6f, 0x17, 0xf8,
+	0x37, 0x61, 0x07, 0x22, 0x49, 0xaa, 0x5d, 0x30, 0x6c, 0xd4, 0x73, 0x4c,
+	0xf3, 0xf3, 0x0c, 0xe5, 0x6f, 0xda, 0xe6, 0xe0, 0x3f, 0x37, 0xd6, 0xc5,
+	0x5e, 0xf2, 0x63, 0xdc, 0x67, 0xac, 0xc3, 0x8d, 0xfd, 0x1a, 0xaa, 0xef,
+	0xd7, 0x74, 0xf3, 0xb8, 0xa5, 0xec, 0xcd, 0xda, 0xdc, 0xae, 0xca, 0xed,
+	0xaa, 0xd8, 0xfb, 0xe3, 0xeb, 0x4b, 0xd8, 0x77, 0x1e, 0xa6, 0xd5, 0x79,
+	0xc8, 0x28, 0xfc, 0x21, 0x8d, 0xbd, 0xde, 0xd5, 0x65, 0x5c, 0x87, 0x4f,
+	0xa4, 0xb1, 0xd7, 0xbb, 0xaa, 0xf6, 0x7a, 0x57, 0x97, 0x63, 0x42, 0x6f,
+	0xe7, 0x4b, 0x4c, 0xf7, 0x92, 0x5f, 0xc5, 0x39, 0xee, 0x53, 0xbf, 0x2d,
+	0xf4, 0x98, 0xf0, 0x69, 0xf7, 0xd9, 0x6b, 0xd3, 0xf0, 0x50, 0x0b, 0x0d,
+	0x63, 0x02, 0x67, 0xa5, 0xf8, 0x99, 0xc9, 0xd2, 0x63, 0xff, 0x3b, 0x60,
+	0x78, 0x46, 0x00, 0xf3, 0x9e, 0x30, 0x34, 0xef, 0xc1, 0xe6, 0x8e, 0xf9,
+	0x19, 0x20, 0xf7, 0x14, 0xd9, 0x80, 0xfb, 0x16, 0x90, 0xf2, 0x4a, 0x06,
+	0xad, 0xbc, 0x02, 0xa6, 0x09, 0x75, 0x88, 0xfe, 0xa6, 0xf5, 0x9f, 0xe5,
+	0x60, 0xe3, 0x80, 0x4d, 0x40, 0x73, 0x9b, 0xa7, 0x90, 0x32, 0xf7, 0x0c,
+	0xac, 0x6f, 0xb1, 0xae, 0x6d, 0xb4, 0x01, 0xef, 0xb1, 0x5e, 0x34, 0x85,
+	0x85, 0x61, 0x49, 0x0f, 0x03, 0xb0, 0x7e, 0x00, 0xa5, 0x75, 0x50, 0x1d,
+	0x01, 0x4f, 0xef, 0x02, 0x4d, 0x40, 0xf7, 0x39, 0x01, 0xdb, 0xa2, 0xce,
+	0xfd, 0xca, 0xe0, 0xb5, 0xb2, 0x0d, 0xd0, 0x73, 0xab, 0x16, 0xf5, 0x88,
+	0xc9, 0x83, 0xf2, 0x99, 0x93, 0x0a, 0x03, 0x19, 0x79, 0x81, 0x0d, 0x9a,
+	0x17, 0xc0, 0xe1, 0x04, 0x4c, 0xeb, 0xc0, 0x32, 0x6a, 0x8d, 0x2e, 0xd0,
+	0x3c, 0x1e, 0x16, 0x97, 0x7e, 0x90, 0x18, 0x03, 0x54, 0x8c, 0x05, 0xc8,
+	0x97, 0x01, 0xb6, 0x29, 0x41, 0x7e, 0x05, 0xe5, 0x05, 0x90, 0xd9, 0x20,
+	0xbf, 0x83, 0xca, 0x4e, 0x50, 0x5e, 0x04, 0xb2, 0x97, 0x08, 0x41, 0xfd,
+	0x0c, 0xa4, 0x81, 0xec, 0xe6, 0x29, 0x22, 0x60, 0x7e, 0x52, 0x80, 0x10,
+	0x43, 0x03, 0x3c, 0x1f, 0x10, 0x1b, 0xc6, 0x30, 0xf5, 0x31, 0x64, 0xe4,
+	0x1b, 0x88, 0x19, 0x88, 0x7c, 0xc3, 0xce, 0x70, 0x40, 0x00, 0x16, 0x56,
+	0xff, 0xff, 0x1f, 0x53, 0x61, 0x01, 0xa6, 0x53, 0xd0, 0x3a, 0xd6, 0xdf,
+	0xff, 0x0f, 0x88, 0xb0, 0x30, 0xb4, 0xc0, 0xd7, 0x23, 0xe6, 0xc8, 0x83,
+	0xca, 0xd0, 0x05, 0x40, 0x56, 0x1b, 0xbc, 0x4d, 0xc0, 0x02, 0xbe, 0xef,
+	0x79, 0x01, 0xc3, 0x2f, 0x60, 0x99, 0xf5, 0xff, 0xff, 0x52, 0xb8, 0x5a,
+	0x10, 0x00, 0x00, 0x19, 0x3f, 0x16, 0x21, 0xc4, 0x7d, 0x00, 0x00, 0x00 };
+
+static const u32 bnx2_COM_b09FwData[(0x0/4) + 1] = { 0x0 };
+static const u32 bnx2_COM_b09FwRodata[(0x88/4) + 1] = {
+	0x08001b68, 0x08001ba4, 0x08001ba4, 0x08001ba4, 0x08001ba4, 0x08001ba4,
+	0x08001ab4, 0x08001ba4, 0x08001b28, 0x08001ba4, 0x08001a3c, 0x08001ba4,
+	0x08001ba4, 0x08001ba4, 0x08001a48, 0x00000000, 0x08002abc, 0x08002b0c,
+	0x08002b3c, 0x08002b6c, 0x08002b9c, 0x00000000, 0x0800604c, 0x0800604c,
+	0x0800604c, 0x0800604c, 0x0800604c, 0x08006078, 0x08006078, 0x080060b8,
+	0x080060c4, 0x080060c4, 0x0800604c, 0x00000000, 0x00000000 };
+static const u32 bnx2_COM_b09FwBss[(0x88/4) + 1] = { 0x0 };
+static const u32 bnx2_COM_b09FwSbss[(0x60/4) + 1] = { 0x0 };
 
 static struct fw_info bnx2_com_fw_09 = {
-	.ver_major			= 0x1,
-	.ver_minor			= 0x0,
-	.ver_fix			= 0x0,
+	.ver_major			= 0x3,
+	.ver_minor			= 0x4,
+	.ver_fix			= 0x3,
 
-	.start_addr			= 0x080000b0,
+	.start_addr			= 0x080000b4,
 
 	.text_addr			= 0x08000000,
-	.text_len			= 0x7c5c,
+	.text_len			= 0x7dc0,
 	.text_index			= 0x0,
 	.gz_text			= bnx2_COM_b09FwText,
 	.gz_text_len			= sizeof(bnx2_COM_b09FwText),
 
-	.data_addr			= 0x08007d00,
+	.data_addr			= 0x08007e60,
 	.data_len			= 0x0,
 	.data_index			= 0x0,
 	.data				= bnx2_COM_b09FwData,
 
-	.sbss_addr			= 0x08007d00,
-	.sbss_len			= 0x5c,
+	.sbss_addr			= 0x08007e60,
+	.sbss_len			= 0x60,
 	.sbss_index			= 0x0,
 	.sbss				= bnx2_COM_b09FwSbss,
 
-	.bss_addr			= 0x08007d60,
+	.bss_addr			= 0x08007ec0,
 	.bss_len			= 0x88,
 	.bss_index			= 0x0,
 	.bss				= bnx2_COM_b09FwBss,
 
-	.rodata_addr			= 0x08007c60,
+	.rodata_addr			= 0x08007dc0,
 	.rodata_len			= 0x88,
 	.rodata_index			= 0x0,
 	.rodata				= bnx2_COM_b09FwRodata,
 };
 
 static u8 bnx2_CP_b09FwText[] = {
-	0x1f, 0x8b, 0x08, 0x08, 0x8e, 0xfc, 0x2f, 0x45, 0x00, 0x03, 0x74, 0x65,
-	0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, 0xbd, 0x7d, 0x0d, 0x74,
-	0x5c, 0x57, 0x7d, 0xe7, 0xff, 0xdd, 0x79, 0x92, 0xc6, 0xb2, 0x2c, 0x3f,
-	0xcb, 0x63, 0x65, 0x22, 0x0b, 0x7b, 0x46, 0x7a, 0xb2, 0x95, 0x58, 0x64,
-	0xc7, 0xae, 0x00, 0x6d, 0x3b, 0x85, 0xe9, 0x48, 0xb2, 0x9d, 0x0f, 0x8a,
-	0x4c, 0x44, 0x4f, 0x5a, 0xe8, 0x22, 0xc6, 0x76, 0x48, 0x80, 0xb2, 0x4e,
-	0x09, 0x69, 0x80, 0x04, 0x0f, 0x23, 0xf9, 0x83, 0x74, 0xec, 0x51, 0x12,
-	0xc5, 0x76, 0x4f, 0x73, 0x58, 0x55, 0x92, 0x1d, 0x43, 0xa7, 0x1e, 0x27,
-	0x71, 0x68, 0xf6, 0x6c, 0x68, 0xb4, 0x4a, 0xe2, 0xa6, 0x3d, 0xd9, 0xd6,
-	0xf4, 0x84, 0x6e, 0xda, 0x43, 0x77, 0x85, 0x71, 0x88, 0x4b, 0xb3, 0x4b,
-	0xf8, 0x68, 0x61, 0xa1, 0xe5, 0xed, 0xef, 0x77, 0xef, 0x7d, 0xd2, 0xe8,
-	0xc3, 0x09, 0xa1, 0xbb, 0xf5, 0x39, 0xcf, 0x6f, 0xde, 0xfd, 0xfc, 0xdf,
-	0xff, 0xfd, 0x7f, 0xdf, 0x0f, 0xad, 0x17, 0xa9, 0x17, 0xfb, 0x6f, 0x15,
-	0x9e, 0x6d, 0x89, 0x7d, 0xbb, 0xb7, 0x5e, 0xd7, 0x73, 0x1d, 0x7e, 0x6e,
-	0x75, 0x57, 0x46, 0x95, 0xbc, 0x89, 0x7f, 0x89, 0x9f, 0xa1, 0x4c, 0x44,
-	0xc4, 0x0b, 0xfb, 0xe2, 0x23, 0x51, 0x95, 0x1e, 0xfc, 0x64, 0xd6, 0x97,
-	0x68, 0x24, 0x7d, 0xf6, 0xb3, 0xbb, 0x7d, 0x91, 0x4c, 0x79, 0x4b, 0xa2,
-	0x57, 0xfe, 0x25, 0xc8, 0xc7, 0x5c, 0x61, 0xfa, 0x5b, 0xd2, 0xff, 0xfc,
-	0x9f, 0xbe, 0xf2, 0x8e, 0xe4, 0x6b, 0xe3, 0x11, 0x89, 0x7a, 0xe9, 0x8f,
-	0x89, 0xb7, 0x49, 0xa2, 0xad, 0xe9, 0x81, 0x4f, 0x3e, 0xbc, 0xf9, 0x6f,
-	0x44, 0x1a, 0xc3, 0xb6, 0x2e, 0x07, 0x5f, 0xd9, 0x2c, 0xf9, 0x96, 0x74,
-	0x7c, 0xc8, 0x4d, 0x7b, 0xf2, 0x74, 0x45, 0x06, 0x0a, 0xc5, 0xa8, 0x44,
-	0xd2, 0x1d, 0x2f, 0xf5, 0x46, 0xf6, 0x07, 0x11, 0xdf, 0xf7, 0x7a, 0xa5,
-	0xa1, 0x27, 0xdb, 0x8d, 0xf4, 0xf2, 0x56, 0x51, 0x7e, 0x54, 0xb2, 0x15,
-	0x69, 0x50, 0xbe, 0x8f, 0x77, 0xbd, 0xa8, 0x74, 0xd2, 0xcb, 0x46, 0x5c,
-	0x29, 0x54, 0x2e, 0xac, 0x30, 0x6d, 0x96, 0xec, 0xfb, 0x6f, 0xa2, 0xe6,
-	0x8d, 0x36, 0x4b, 0x51, 0x99, 0x8d, 0xc4, 0x05, 0xfd, 0x00, 0xe6, 0x06,
-	0x19, 0x2e, 0x25, 0x24, 0x5b, 0x64, 0xbf, 0xae, 0xe4, 0x3c, 0xf6, 0xd9,
-	0x80, 0xfa, 0x2b, 0x9d, 0xe5, 0xcb, 0xb3, 0xec, 0x4b, 0x28, 0x9b, 0x40,
-	0xb9, 0x56, 0x79, 0xbc, 0x12, 0x97, 0xc7, 0x2a, 0x31, 0x79, 0xb4, 0x72,
-	0x87, 0x64, 0x50, 0xf7, 0x6c, 0x05, 0x7d, 0x97, 0x6a, 0xa5, 0x77, 0xac,
-	0x5e, 0xb2, 0x63, 0xed, 0xf1, 0x9c, 0x04, 0xc1, 0x27, 0x52, 0x1f, 0x95,
-	0xa1, 0x26, 0x94, 0x2f, 0x31, 0x2f, 0xbe, 0x20, 0x2f, 0x97, 0xda, 0xe2,
-	0xe5, 0x94, 0x23, 0x99, 0xc1, 0x64, 0x7c, 0x48, 0xf1, 0xbb, 0x46, 0xb2,
-	0x5d, 0xf8, 0x1e, 0x70, 0x25, 0xe2, 0x07, 0xc1, 0x1d, 0xa9, 0x26, 0xc0,
-	0x91, 0x4c, 0x24, 0x14, 0xeb, 0xb2, 0x5e, 0x32, 0x9f, 0x50, 0x51, 0xc9,
-	0x57, 0xae, 0x93, 0x44, 0x53, 0x10, 0xbc, 0x37, 0xe5, 0x21, 0x5d, 0xa4,
-	0xb7, 0x28, 0xfb, 0x54, 0xda, 0x47, 0x9b, 0x92, 0x52, 0xe9, 0xb5, 0x18,
-	0xc7, 0x16, 0xe0, 0xa9, 0x56, 0x32, 0x31, 0xc9, 0xa8, 0xb4, 0x24, 0x54,
-	0x7a, 0x05, 0xd2, 0x1c, 0xa9, 0xf1, 0xa7, 0x2c, 0x9d, 0xac, 0xc6, 0xb7,
-	0x0c, 0xa8, 0x74, 0xd3, 0xa2, 0xf4, 0x64, 0x42, 0xd4, 0x8f, 0xea, 0xd0,
-	0x67, 0x67, 0x46, 0x31, 0x0d, 0x6f, 0x9d, 0x76, 0xfd, 0x32, 0x69, 0x1f,
-	0x74, 0x16, 0xa6, 0x3d, 0xb5, 0x8a, 0xb0, 0x8a, 0xe2, 0xef, 0x28, 0xe0,
-	0x6a, 0x41, 0xff, 0xed, 0x5e, 0x0d, 0xc6, 0x35, 0x90, 0x4a, 0x7a, 0xfd,
-	0xea, 0xc5, 0x40, 0x9a, 0x09, 0x33, 0xf3, 0x14, 0xf2, 0x50, 0x34, 0x9d,
-	0xc2, 0xbc, 0xb9, 0x72, 0x08, 0x63, 0xbb, 0x38, 0x96, 0xf4, 0xda, 0x14,
-	0xde, 0x53, 0xfc, 0xdd, 0x34, 0x14, 0x49, 0x07, 0x41, 0x36, 0x35, 0x2e,
-	0xb9, 0x72, 0xd2, 0x9b, 0x05, 0x70, 0xbd, 0x63, 0x71, 0x8c, 0x1f, 0xe3,
-	0x88, 0x65, 0x92, 0x6b, 0xa4, 0xcb, 0xce, 0xcf, 0x5f, 0xa2, 0xef, 0x76,
-	0xef, 0x0e, 0xd5, 0xee, 0xa5, 0x54, 0xd2, 0x9b, 0x90, 0x3f, 0xc4, 0x77,
-	0x10, 0xec, 0x4a, 0x25, 0xe3, 0x79, 0xcc, 0xdd, 0xa5, 0x62, 0x4c, 0x5e,
-	0x2e, 0x26, 0x41, 0xa9, 0xc9, 0xce, 0x49, 0xd9, 0x92, 0x9a, 0x04, 0xdc,
-	0x05, 0x3c, 0x07, 0x99, 0x57, 0x46, 0x5e, 0x99, 0x75, 0x83, 0xe0, 0xe6,
-	0xd4, 0x89, 0x60, 0xa8, 0xd9, 0xd0, 0xfe, 0xd3, 0x25, 0xcc, 0x2b, 0xe6,
-	0xe9, 0xb1, 0x12, 0xe6, 0xb5, 0x84, 0x39, 0xd5, 0xf3, 0xdf, 0x89, 0xf9,
-	0x27, 0x8d, 0x90, 0x3e, 0xb6, 0x59, 0x7a, 0x7d, 0xb7, 0x7d, 0x8b, 0x64,
-	0x4b, 0x8e, 0x64, 0x53, 0x3f, 0x09, 0x32, 0x9a, 0x27, 0xc4, 0xe9, 0x2d,
-	0x91, 0x26, 0x6b, 0x00, 0x2b, 0x3f, 0x7f, 0xdd, 0x96, 0x8b, 0x3a, 0x18,
-	0x06, 0xe7, 0x83, 0xf9, 0x51, 0xe5, 0xd7, 0xd9, 0xfc, 0x90, 0xf6, 0xf9,
-	0x0f, 0x74, 0xe7, 0xcf, 0x97, 0xcb, 0x92, 0x36, 0x2b, 0x22, 0xb9, 0x07,
-	0x03, 0xe9, 0x4d, 0x01, 0x5f, 0x6c, 0xd3, 0x4b, 0x89, 0xae, 0xeb, 0xb1,
-	0x8c, 0x2e, 0x8b, 0x7f, 0x3f, 0xae, 0x41, 0x1f, 0x4e, 0x5f, 0x69, 0xbe,
-	0x6e, 0x5f, 0xe9, 0x85, 0x98, 0x85, 0x0f, 0xdf, 0x3d, 0x4e, 0xb6, 0xf2,
-	0x77, 0x76, 0x8e, 0xc3, 0x71, 0x74, 0x2d, 0x43, 0xe3, 0x2e, 0xf8, 0xc1,
-	0x93, 0x5c, 0xb1, 0x07, 0xfd, 0xc6, 0xf0, 0x0e, 0x82, 0x91, 0x54, 0x26,
-	0xe9, 0x4a, 0x1a, 0xdf, 0x03, 0x98, 0xaf, 0x0e, 0xe0, 0x4f, 0xdc, 0xec,
-	0xe6, 0x94, 0xf4, 0x55, 0x40, 0x7b, 0x95, 0x37, 0x96, 0x14, 0x7a, 0x0c,
-	0xa9, 0x7f, 0xb1, 0xb8, 0x61, 0x3f, 0x7c, 0xbb, 0x32, 0x02, 0xfa, 0x28,
-	0x8c, 0xf9, 0x32, 0x5c, 0x9c, 0xf6, 0x94, 0x24, 0x41, 0xbb, 0x69, 0xe9,
-	0xad, 0xf8, 0x52, 0x28, 0xe2, 0x5d, 0x6a, 0x07, 0xfd, 0xba, 0x92, 0x89,
-	0x9b, 0x39, 0x29, 0x14, 0x7f, 0x09, 0xe3, 0x02, 0x8e, 0x7d, 0xfe, 0xee,
-	0xb1, 0xb0, 0x80, 0xf7, 0xbb, 0x53, 0x1a, 0x3f, 0x6f, 0x0e, 0x06, 0xf6,
-	0x8d, 0x31, 0x60, 0x9c, 0x85, 0xb2, 0x8b, 0x77, 0x0c, 0xef, 0x90, 0x16,
-	0xe3, 0x80, 0xa9, 0x55, 0x86, 0x41, 0x8b, 0xbd, 0x82, 0xdf, 0x53, 0x84,
-	0x91, 0xfd, 0xb6, 0xe8, 0xdf, 0xc3, 0x63, 0x1b, 0xf4, 0x77, 0x6e, 0xa0,
-	0x45, 0xf2, 0x53, 0xe1, 0x58, 0x28, 0x0f, 0x28, 0x03, 0x92, 0x87, 0x45,
-	0x28, 0x13, 0x82, 0xe0, 0xc1, 0x14, 0xe5, 0x42, 0x10, 0x3c, 0x96, 0xa2,
-	0x9c, 0x38, 0x07, 0xfe, 0xa7, 0x6c, 0x20, 0xaf, 0xae, 0x55, 0x9c, 0x83,
-	0x6c, 0x11, 0x7d, 0x40, 0x4e, 0xe4, 0xba, 0x4e, 0x40, 0x6e, 0x50, 0xae,
-	0x5c, 0xf8, 0x44, 0xd6, 0xcf, 0xc7, 0x23, 0x1a, 0x0f, 0x98, 0x6f, 0xc8,
-	0xbc, 0x8c, 0x86, 0xbc, 0x4d, 0x0a, 0x5d, 0xa3, 0xb6, 0xcc, 0x65, 0x5d,
-	0xc6, 0x5d, 0x52, 0xe6, 0x76, 0x65, 0xf8, 0xae, 0x15, 0xf3, 0xb1, 0x42,
-	0x11, 0x4f, 0x6d, 0x9b, 0xf8, 0x2d, 0xd1, 0x9a, 0xf4, 0x97, 0x90, 0x37,
-	0x7d, 0xd7, 0x49, 0x7f, 0xb9, 0xbc, 0x59, 0x77, 0x69, 0xde, 0x88, 0xb8,
-	0x7e, 0xb2, 0x73, 0x97, 0x9a, 0x01, 0x3d, 0x05, 0xc1, 0xc9, 0x54, 0x98,
-	0xfe, 0x8f, 0xee, 0xd2, 0x3e, 0x12, 0x35, 0x4b, 0xd3, 0xee, 0x5d, 0x26,
-	0xed, 0xc4, 0x32, 0x69, 0x1b, 0x6a, 0x97, 0xa6, 0xbd, 0x7f, 0x99, 0xb4,
-	0xfb, 0x97, 0x49, 0xfb, 0x5f, 0xcb, 0xa4, 0x7d, 0x67, 0x99, 0xb4, 0xef,
-	0x2d, 0x93, 0xd6, 0x52, 0xb7, 0x34, 0xcd, 0x05, 0x3f, 0x6d, 0x92, 0x42,
-	0xec, 0x73, 0x1c, 0xbb, 0xc5, 0xcd, 0xfe, 0xc8, 0x52, 0xdc, 0xd4, 0xa0,
-	0x5c, 0xeb, 0xa2, 0x72, 0x53, 0xcb, 0x94, 0xab, 0x45, 0xb9, 0xa6, 0x45,
-	0xe5, 0x92, 0xcb, 0xe0, 0xba, 0x4e, 0xeb, 0xaf, 0x85, 0xe5, 0x0a, 0xcb,
-	0x94, 0x63, 0xfa, 0x1e, 0xdb, 0xcf, 0x16, 0x68, 0x99, 0xd7, 0x9b, 0xaf,
-	0x5a, 0x91, 0x66, 0xa6, 0xb7, 0x42, 0x47, 0xac, 0x50, 0x86, 0xdf, 0x29,
-	0x5b, 0x98, 0xe6, 0x81, 0xee, 0xa3, 0xa0, 0x3b, 0xca, 0x47, 0xf0, 0x91,
-	0x4f, 0xfe, 0x5d, 0x25, 0x43, 0xb1, 0x2d, 0xde, 0x2f, 0xa8, 0x06, 0xd0,
-	0x58, 0xd2, 0x4b, 0x28, 0xf2, 0x97, 0xe4, 0x23, 0x69, 0x3f, 0xdf, 0x2b,
-	0x2a, 0xa6, 0x24, 0x90, 0xbe, 0x94, 0x6a, 0x52, 0xb2, 0x1f, 0xfc, 0x93,
-	0x81, 0x4e, 0xda, 0x15, 0xf4, 0x6a, 0x1e, 0x32, 0x65, 0xaf, 0x2c, 0x2b,
-	0x7d, 0x39, 0x48, 0x19, 0x97, 0xce, 0xdc, 0x95, 0xf5, 0xa7, 0x7b, 0x6a,
-	0x41, 0xb3, 0x17, 0x51, 0x67, 0x07, 0x6a, 0xee, 0x2d, 0xbb, 0xd2, 0x57,
-	0xee, 0x04, 0x2f, 0x38, 0x72, 0xde, 0x5f, 0x2d, 0xe7, 0x53, 0x28, 0x5b,
-	0x89, 0xc8, 0x4c, 0xcc, 0x91, 0x19, 0x7c, 0x67, 0x53, 0xc8, 0xab, 0x84,
-	0xbc, 0xd5, 0x29, 0x07, 0x4a, 0xbe, 0x1c, 0x2e, 0xfd, 0x92, 0x0a, 0xf5,
-	0x56, 0x7f, 0x6a, 0xa5, 0x9c, 0xf6, 0x4c, 0xdb, 0x3b, 0xfc, 0x69, 0x68,
-	0x4c, 0x57, 0x2e, 0xfa, 0xc9, 0xf8, 0x8c, 0xe6, 0x89, 0x1f, 0x06, 0x7d,
-	0x68, 0x67, 0xc2, 0x4f, 0x7a, 0x7f, 0x8a, 0xef, 0xa1, 0x32, 0xed, 0x90,
-	0xf9, 0xb6, 0x86, 0xd1, 0xd6, 0xa1, 0xd2, 0x2a, 0xf9, 0xb0, 0xad, 0xbf,
-	0xdd, 0x9f, 0xee, 0x04, 0xcf, 0x79, 0xa7, 0x28, 0x23, 0x8a, 0x80, 0x6b,
-	0x10, 0xbc, 0x8d, 0xba, 0xcf, 0x69, 0x39, 0x05, 0xbb, 0xa5, 0xb8, 0x1a,
-	0x72, 0xf7, 0x1f, 0x83, 0x0f, 0xc7, 0x58, 0x9e, 0x69, 0xd4, 0x25, 0x32,
-	0xaa, 0xd2, 0x90, 0x09, 0xdd, 0x94, 0x85, 0x09, 0xc8, 0x41, 0xc8, 0x96,
-	0xd2, 0x4f, 0x83, 0x8c, 0x5b, 0x2d, 0xdf, 0x24, 0x3f, 0x5f, 0x86, 0x69,
-	0x09, 0x23, 0x2f, 0x4b, 0xb3, 0x73, 0xb2, 0x22, 0x0f, 0xf9, 0xf2, 0x74,
-	0x85, 0x72, 0xe1, 0x7a, 0xf0, 0x68, 0xab, 0xf4, 0x15, 0x93, 0xf9, 0x8c,
-	0x6c, 0xc2, 0xfc, 0x7d, 0x1e, 0x73, 0xea, 0xe2, 0xb9, 0xaf, 0x5e, 0x1a,
-	0x53, 0xd0, 0xcd, 0x4c, 0x47, 0xa3, 0xcd, 0x51, 0xc8, 0xa8, 0xdf, 0x03,
-	0x1e, 0x86, 0x39, 0xe7, 0xf1, 0x6c, 0xc4, 0x19, 0xa0, 0x3d, 0x32, 0x40,
-	0xfd, 0x50, 0x66, 0xdb, 0x84, 0x37, 0x6e, 0x7f, 0x47, 0xb5, 0x8c, 0x31,
-	0xbf, 0x1b, 0xf0, 0x3b, 0x61, 0x7f, 0x7b, 0xf8, 0xed, 0xdb, 0xdf, 0x31,
-	0xfc, 0xee, 0xb4, 0xbf, 0xa1, 0x5b, 0x8b, 0x5d, 0xfa, 0xf7, 0x48, 0x69,
-	0xfb, 0x76, 0xe5, 0x5f, 0x27, 0xb9, 0xa9, 0x56, 0x39, 0x50, 0xf4, 0xad,
-	0x6c, 0xc1, 0x23, 0x4f, 0x3a, 0x66, 0x9c, 0x80, 0x9b, 0xb2, 0xb3, 0x94,
-	0x77, 0x06, 0x08, 0x3f, 0x68, 0xa0, 0xb7, 0xb8, 0xc5, 0x5b, 0x23, 0xa4,
-	0x81, 0x11, 0xa7, 0xb7, 0xe2, 0x64, 0x60, 0xaf, 0xc5, 0x87, 0xe5, 0x30,
-	0x7e, 0x8b, 0x17, 0x49, 0x3f, 0x89, 0xb7, 0xc1, 0x01, 0xf5, 0xce, 0x70,
-	0x89, 0xf2, 0xd2, 0xc7, 0xd8, 0x13, 0x72, 0x6e, 0x81, 0x0d, 0x45, 0x5c,
-	0x28, 0xc9, 0x8d, 0x25, 0x4f, 0xe4, 0x25, 0x99, 0x1f, 0x07, 0x43, 0xec,
-	0x4a, 0xb9, 0xf2, 0xde, 0x14, 0x68, 0xf7, 0x3a, 0x47, 0xb6, 0x5f, 0xe7,
-	0xc2, 0xe6, 0xf1, 0xc7, 0xb7, 0x83, 0xfe, 0x31, 0xcf, 0x9a, 0x1e, 0xd4,
-	0x19, 0x81, 0x9d, 0x08, 0x6c, 0x9f, 0xe9, 0xea, 0x1b, 0x2e, 0xe6, 0x3e,
-	0xa6, 0xd2, 0xfb, 0x3e, 0x95, 0xed, 0xbe, 0x46, 0x72, 0x83, 0x0a, 0x38,
-	0x6a, 0x1e, 0x82, 0x1e, 0xc4, 0xb8, 0x82, 0x00, 0xf4, 0x0c, 0x79, 0x7e,
-	0xf3, 0xcd, 0x91, 0x74, 0x8d, 0xf4, 0x0e, 0x36, 0xa3, 0x0e, 0xf3, 0x88,
-	0xaf, 0xaf, 0xa2, 0x9d, 0x64, 0xa2, 0x4f, 0xe4, 0x9e, 0x91, 0xee, 0x59,
-	0x67, 0x78, 0xf4, 0x37, 0xc0, 0x93, 0x5b, 0x51, 0xff, 0x01, 0xd4, 0x7f,
-	0xcd, 0x29, 0x8c, 0xfd, 0xc8, 0x19, 0x1e, 0xfb, 0x9e, 0x33, 0x32, 0xb6,
-	0x61, 0x43, 0x7f, 0xcf, 0x86, 0x0d, 0xbb, 0x7b, 0x5c, 0x99, 0x00, 0x8f,
-	0x65, 0xbc, 0x0d, 0x1b, 0x46, 0x7a, 0xba, 0x80, 0x83, 0x2d, 0x5e, 0x9f,
-	0xf8, 0xde, 0x76, 0x01, 0xff, 0xc4, 0xd8, 0x67, 0x14, 0xf9, 0x49, 0xe4,
-	0xb3, 0x7e, 0x5c, 0xe7, 0xf7, 0xca, 0x96, 0x78, 0x93, 0xb0, 0xff, 0x88,
-	0x2d, 0x53, 0x13, 0x91, 0xfa, 0x07, 0xec, 0xfc, 0x66, 0x9c, 0x1a, 0x9f,
-	0xe9, 0x1c, 0x0b, 0xd3, 0x39, 0xb7, 0x7f, 0x67, 0x6d, 0xd5, 0xd5, 0x48,
-	0xe7, 0x37, 0x71, 0x46, 0xbc, 0xd0, 0xc6, 0xa8, 0xd1, 0xb6, 0x61, 0xae,
-	0x48, 0x9a, 0x71, 0x65, 0x4f, 0xd1, 0x41, 0x1d, 0xd0, 0xc5, 0x19, 0xfb,
-	0x1c, 0x05, 0x6c, 0x83, 0x68, 0xeb, 0xe8, 0x21, 0xd4, 0xa3, 0xcc, 0x48,
-	0x76, 0x8a, 0xfa, 0x00, 0xca, 0x6c, 0xf1, 0xd6, 0x0a, 0x6d, 0x89, 0x3b,
-	0x25, 0x57, 0x22, 0x7f, 0x77, 0x00, 0x9e, 0xa8, 0x24, 0x9a, 0xf1, 0x5d,
-	0x81, 0x4d, 0xf1, 0x60, 0x8d, 0x58, 0xdb, 0x45, 0xe6, 0x6d, 0x91, 0x3b,
-	0x94, 0xc0, 0xde, 0x18, 0x9a, 0x5c, 0x8f, 0x72, 0x0e, 0xf0, 0x42, 0xfb,
-	0x03, 0xb4, 0x36, 0x99, 0x91, 0xec, 0x26, 0xf0, 0xc9, 0xa4, 0x87, 0x6f,
-	0xc0, 0x35, 0xf9, 0x16, 0xbc, 0x23, 0xfa, 0xdb, 0xc0, 0x09, 0xbc, 0xa6,
-	0x22, 0x56, 0x67, 0x75, 0xa1, 0xef, 0xf7, 0x48, 0x76, 0x34, 0x4e, 0x5b,
-	0x62, 0x75, 0xd6, 0xcf, 0x40, 0xd7, 0x2b, 0x28, 0x41, 0x8c, 0x61, 0xd2,
-	0x81, 0x3c, 0xa9, 0x95, 0xdd, 0x8f, 0xe0, 0xf7, 0x83, 0xc6, 0xe6, 0xdd,
-	0x3d, 0xc9, 0x7e, 0x1a, 0x00, 0x13, 0x6c, 0x90, 0x47, 0x60, 0x9b, 0x3e,
-	0x02, 0x1b, 0xe4, 0x91, 0x66, 0x3c, 0x1c, 0x1b, 0xdb, 0x9f, 0x59, 0x03,
-	0x31, 0xa9, 0xbf, 0x73, 0xa4, 0x57, 0xd8, 0xea, 0xb9, 0x62, 0xca, 0x94,
-	0x2f, 0x76, 0xeb, 0xb7, 0xa1, 0xeb, 0x1e, 0xfb, 0x3b, 0xae, 0xf9, 0x3a,
-	0xdf, 0x04, 0x9a, 0xaf, 0x74, 0x69, 0x99, 0x93, 0xf5, 0xf1, 0x86, 0xcd,
-	0x99, 0x69, 0xe2, 0x18, 0xe3, 0x36, 0x2d, 0xae, 0xd3, 0x12, 0x4d, 0xd6,
-	0xde, 0x28, 0x59, 0x5b, 0x03, 0xb8, 0x19, 0x6a, 0x06, 0xc4, 0x94, 0xcf,
-	0x12, 0xe2, 0x93, 0x32, 0x00, 0xf4, 0x0b, 0x9b, 0xe2, 0xdc, 0x15, 0xe5,
-	0xdf, 0xac, 0xb6, 0xb1, 0xce, 0x56, 0x48, 0xc7, 0xa4, 0xed, 0x20, 0xb8,
-	0x3f, 0x55, 0x87, 0xf6, 0xc9, 0xf3, 0xb0, 0x40, 0x8e, 0x02, 0x26, 0x60,
-	0xa2, 0xc6, 0x3f, 0xab, 0x69, 0xa0, 0xd6, 0x27, 0x0d, 0x57, 0xf3, 0x97,
-	0xe8, 0xf1, 0x9e, 0x05, 0x8f, 0xc1, 0xbe, 0x81, 0xfd, 0xd6, 0x01, 0xdb,
-	0x98, 0x7d, 0x1c, 0xe6, 0xb7, 0xa7, 0xc0, 0x53, 0xd9, 0x39, 0x9e, 0x12,
-	0x99, 0x28, 0x12, 0x37, 0xa1, 0x5d, 0xc7, 0x79, 0x26, 0x7e, 0x32, 0x18,
-	0x33, 0xdf, 0x7d, 0x16, 0x4f, 0x3b, 0x2d, 0x9e, 0x6e, 0xb2, 0xef, 0x11,
-	0xbc, 0x69, 0xe3, 0x0d, 0xe0, 0xcd, 0xf9, 0x19, 0xc4, 0x9b, 0xbc, 0x75,
-	0x0b, 0xde, 0x28, 0x5b, 0xca, 0xc8, 0x6e, 0x6d, 0x87, 0x45, 0xe4, 0x57,
-	0xb4, 0x6c, 0xfb, 0x02, 0xe6, 0xb2, 0x48, 0xfa, 0x95, 0x7c, 0x2c, 0x02,
-	0x9c, 0x14, 0xf0, 0xfb, 0x4e, 0xd7, 0xd0, 0x2a, 0x71, 0xb2, 0xc0, 0x57,
-	0xaa, 0x82, 0x29, 0x66, 0xe5, 0x5c, 0x42, 0xdb, 0xfa, 0xb9, 0xe2, 0x07,
-	0x34, 0x5c, 0xb7, 0x42, 0xde, 0xe5, 0x45, 0x35, 0x43, 0x37, 0x80, 0x16,
-	0x54, 0x0c, 0x9a, 0x2b, 0x78, 0x06, 0x7a, 0x29, 0x37, 0x49, 0xdb, 0xb8,
-	0x8d, 0x7e, 0x49, 0x34, 0xd7, 0xd5, 0x48, 0x3a, 0x52, 0x0a, 0xf6, 0x17,
-	0xbe, 0x55, 0xae, 0x4b, 0xd3, 0xa9, 0xa3, 0xfc, 0x98, 0xb6, 0x7f, 0x5d,
-	0x1f, 0xd2, 0xd6, 0xf8, 0xbd, 0xae, 0xf2, 0xd7, 0x2e, 0x4e, 0x4b, 0x50,
-	0x0f, 0xa3, 0x5e, 0x22, 0xd7, 0xd5, 0x4c, 0x1e, 0xf3, 0x40, 0xbf, 0x19,
-	0xe5, 0x6b, 0xdf, 0x27, 0xaf, 0xba, 0x57, 0x2f, 0x2a, 0xaf, 0xdf, 0x8e,
-	0xfd, 0x76, 0xed, 0xdb, 0xb3, 0xef, 0x84, 0x7d, 0xe7, 0xdd, 0x6e, 0xbe,
-	0x1d, 0x71, 0xd3, 0x7c, 0x83, 0x92, 0xd3, 0x6c, 0x43, 0xf3, 0x95, 0x95,
-	0x33, 0x1d, 0x5e, 0x41, 0xc8, 0x57, 0x9f, 0x93, 0x5b, 0x27, 0x8d, 0xfc,
-	0xdd, 0x0e, 0x19, 0x04, 0xff, 0xcc, 0x9b, 0x11, 0xc0, 0x3f, 0x98, 0x96,
-	0x5b, 0x2b, 0xc4, 0xdb, 0xef, 0x02, 0x7f, 0x60, 0xe2, 0x7a, 0xea, 0x74,
-	0xca, 0xdd, 0x3b, 0x61, 0xf7, 0xa2, 0x7c, 0x91, 0x38, 0x1f, 0xd2, 0x73,
-	0x53, 0x28, 0xee, 0xd1, 0x73, 0x73, 0xb0, 0x38, 0x03, 0xfc, 0xdc, 0x06,
-	0xba, 0x0f, 0x82, 0x99, 0x54, 0x01, 0x94, 0xf3, 0x11, 0xfc, 0x86, 0x1d,
-	0x50, 0xfc, 0x18, 0xf2, 0x1b, 0xa5, 0x30, 0x4a, 0x9e, 0x73, 0x2d, 0x0f,
-	0xbf, 0x13, 0xfc, 0x14, 0x45, 0xbb, 0x48, 0xeb, 0xe6, 0xef, 0x9f, 0x20,
-	0x0f, 0xef, 0x49, 0x4c, 0x62, 0x33, 0x6d, 0x1d, 0xf6, 0xcd, 0xb9, 0xe3,
-	0x9c, 0xc5, 0xb4, 0x2c, 0x3f, 0x3b, 0x37, 0x6f, 0x97, 0xe7, 0xe8, 0x36,
-	0x4f, 0x1f, 0x8f, 0xf9, 0x1a, 0x56, 0xd2, 0xfd, 0xb7, 0xb4, 0x5c, 0x72,
-	0x8f, 0xce, 0xac, 0x30, 0xef, 0xc5, 0x75, 0x39, 0xe7, 0xd5, 0x34, 0x48,
-	0xbf, 0x25, 0xd9, 0x93, 0x07, 0x3f, 0x61, 0x9c, 0xd2, 0xa7, 0x7d, 0x1d,
-	0xd2, 0x04, 0x69, 0x60, 0xdc, 0xd2, 0xe6, 0x94, 0xa5, 0xcd, 0x27, 0xf1,
-	0xc6, 0x53, 0xba, 0x60, 0x69, 0xf3, 0x29, 0xbc, 0xf1, 0x94, 0x5e, 0x9c,
-	0xe3, 0xe3, 0x5e, 0xf8, 0x72, 0xdb, 0xa1, 0xdf, 0x76, 0x57, 0x40, 0xbf,
-	0xe0, 0xbb, 0x1c, 0x7c, 0x80, 0x5c, 0x69, 0x1f, 0xde, 0xec, 0x67, 0xa3,
-	0x6d, 0x3f, 0x23, 0x7b, 0x4a, 0x01, 0xc6, 0x78, 0x37, 0xc6, 0xfb, 0x39,
-	0xbc, 0x3f, 0xa3, 0xe5, 0x8c, 0xf2, 0x0f, 0x5b, 0x79, 0xf5, 0x79, 0xbc,
-	0xdb, 0xe3, 0x07, 0xa5, 0xdd, 0x8b, 0xc8, 0x34, 0xda, 0xfa, 0xba, 0xec,
-	0xa9, 0xcc, 0xe2, 0xb9, 0x84, 0xe7, 0x55, 0x3c, 0x97, 0xd1, 0xde, 0x0b,
-	0x48, 0x5f, 0x29, 0xd3, 0x5e, 0x3d, 0xca, 0xbf, 0x86, 0xdf, 0xcf, 0xcb,
-	0xd0, 0x23, 0x2f, 0xe1, 0xf9, 0x01, 0xf2, 0x9f, 0x45, 0xfd, 0x60, 0xf5,
-	0x8c, 0x4f, 0x19, 0xf6, 0x9c, 0x6d, 0x3b, 0xe5, 0xe4, 0x2a, 0xa0, 0xe9,
-	0xd2, 0x00, 0xfa, 0xde, 0xa3, 0x79, 0xa6, 0x0f, 0x32, 0x3f, 0x07, 0x19,
-	0x37, 0xa4, 0x61, 0x6a, 0x07, 0x7c, 0x79, 0xcc, 0x05, 0xde, 0x93, 0xb5,
-	0x32, 0x1b, 0xa3, 0x1d, 0x79, 0x93, 0x2e, 0x9f, 0x2b, 0x35, 0x69, 0xbb,
-	0x7a, 0x7c, 0x09, 0xff, 0xd0, 0xef, 0x0a, 0xe5, 0x81, 0x91, 0xc6, 0x13,
-	0x45, 0xca, 0x02, 0xe8, 0x9f, 0xe2, 0x08, 0xde, 0xb5, 0x5a, 0x26, 0x14,
-	0x24, 0x94, 0x07, 0xac, 0x47, 0x99, 0x50, 0x2d, 0x77, 0x28, 0x6b, 0x28,
-	0x7b, 0x28, 0x4b, 0xcc, 0x7c, 0xec, 0x7e, 0x90, 0x32, 0x1c, 0xb4, 0x10,
-	0xa3, 0xfd, 0xe1, 0x19, 0x1f, 0x64, 0xec, 0x3e, 0x2b, 0x4f, 0x47, 0xf5,
-	0x5c, 0xec, 0x29, 0xaa, 0x98, 0x2b, 0xa7, 0x91, 0x86, 0xe7, 0xf8, 0xc3,
-	0x78, 0x7f, 0x49, 0xf6, 0xe0, 0xc9, 0x1d, 0xff, 0x02, 0x7e, 0x73, 0x6e,
-	0xca, 0x28, 0x87, 0xa7, 0x74, 0x02, 0x6f, 0x3c, 0xa5, 0x31, 0x2b, 0x47,
-	0xc6, 0xad, 0x1c, 0xe1, 0x9c, 0xde, 0x04, 0x3c, 0x70, 0x7c, 0x4a, 0xc7,
-	0x17, 0xc0, 0xcf, 0x4e, 0x6e, 0xf2, 0x5d, 0xd6, 0x8f, 0x6d, 0x14, 0xc3,
-	0x83, 0x78, 0x3a, 0xc9, 0xcf, 0x0d, 0xda, 0x0e, 0xce, 0x69, 0xda, 0xfd,
-	0x2b, 0xd7, 0xf0, 0x62, 0xcc, 0xe8, 0x14, 0xaf, 0x59, 0x34, 0xef, 0xcf,
-	0xe1, 0x31, 0x63, 0xf1, 0xc8, 0xdf, 0xca, 0xfe, 0x86, 0xdc, 0x82, 0x4d,
-	0x9b, 0xf5, 0x7d, 0xcc, 0x03, 0xc6, 0x72, 0x7c, 0x14, 0x7d, 0x3b, 0xb2,
-	0xdb, 0xa7, 0x0c, 0x67, 0x0c, 0x81, 0xe3, 0x63, 0xbb, 0x48, 0xd7, 0x38,
-	0x48, 0xc9, 0xbc, 0x6f, 0x7e, 0x13, 0xe6, 0x2c, 0x23, 0x7b, 0x4b, 0xf7,
-	0x6a, 0x5f, 0xb9, 0xf6, 0x68, 0x93, 0xf5, 0x73, 0xc2, 0x72, 0xa0, 0xd5,
-	0x18, 0x6d, 0x9b, 0x2f, 0xc5, 0x0c, 0xcd, 0xf3, 0x37, 0xe5, 0x73, 0xb5,
-	0xbc, 0x37, 0x76, 0x4d, 0x61, 0x81, 0xac, 0xa3, 0x6d, 0x81, 0x39, 0x2b,
-	0x57, 0xe3, 0x9d, 0xbe, 0x3b, 0xf9, 0x8a, 0xfc, 0x74, 0x10, 0x3c, 0xf1,
-	0x5d, 0xcb, 0xfb, 0xf4, 0x35, 0xd8, 0xe7, 0x62, 0x7e, 0xf2, 0x60, 0xfb,
-	0xba, 0x72, 0x0a, 0xb6, 0xdb, 0xf6, 0xb9, 0x36, 0xae, 0x06, 0x3c, 0x51,
-	0x79, 0xa4, 0xd8, 0x20, 0x93, 0x45, 0xd5, 0x1c, 0xb1, 0xb2, 0x33, 0x22,
-	0x09, 0x4d, 0xdf, 0xb4, 0xef, 0x7a, 0xc7, 0x22, 0x96, 0xee, 0xd6, 0xd5,
-	0x48, 0xfd, 0xef, 0x42, 0xc7, 0xa6, 0xa1, 0x63, 0x1b, 0xa1, 0x83, 0x17,
-	0xcb, 0x88, 0x35, 0x35, 0x4b, 0x65, 0x04, 0xeb, 0x24, 0xe1, 0x75, 0x1f,
-	0x44, 0xbd, 0x90, 0xfe, 0xa2, 0x9a, 0xd6, 0x72, 0x92, 0x77, 0xb6, 0x57,
-	0x46, 0x9c, 0x1d, 0x95, 0xc5, 0x3a, 0x68, 0x8b, 0xe7, 0x8a, 0x81, 0xf5,
-	0x91, 0x22, 0x6d, 0xd4, 0x64, 0x2a, 0x0b, 0x9c, 0xec, 0x00, 0xcc, 0xcf,
-	0x8c, 0xc2, 0x4f, 0xa7, 0x5c, 0x06, 0xcc, 0xa7, 0x01, 0xf3, 0xc4, 0xa8,
-	0x13, 0xda, 0x06, 0xc2, 0xa0, 0xc8, 0xc4, 0x58, 0x97, 0xcc, 0x4c, 0x91,
-	0x0e, 0x21, 0x03, 0x46, 0x31, 0x9f, 0xa9, 0x15, 0xb0, 0x03, 0xd8, 0x3f,
-	0xe4, 0xf6, 0x58, 0x8b, 0xce, 0x33, 0xfa, 0xbc, 0x55, 0x66, 0xca, 0x69,
-	0x0b, 0xdb, 0xe1, 0x2a, 0xd8, 0x56, 0xcc, 0xc1, 0xb6, 0x03, 0xb0, 0xed,
-	0x5c, 0x16, 0xb6, 0xe5, 0x74, 0x71, 0x1b, 0x6c, 0x1a, 0xa3, 0x8b, 0x0d,
-	0x5e, 0x9b, 0x2d, 0x3d, 0xbc, 0xdf, 0xda, 0xbb, 0xb4, 0x89, 0x7e, 0x0a,
-	0x78, 0x48, 0x63, 0xf8, 0x3d, 0x79, 0x2f, 0x65, 0x19, 0xd2, 0xf9, 0xbd,
-	0x07, 0x65, 0xf0, 0x3d, 0xf9, 0x67, 0x2b, 0x4c, 0xd9, 0xbb, 0x2d, 0x2c,
-	0xb4, 0x13, 0x32, 0xb0, 0x89, 0xfb, 0x9c, 0xec, 0x24, 0x61, 0xf8, 0x8f,
-	0x80, 0x17, 0x79, 0x95, 0xea, 0x36, 0xf9, 0x66, 0xbb, 0xd7, 0xda, 0x76,
-	0xd8, 0x76, 0x38, 0x96, 0x95, 0x56, 0xcf, 0x87, 0xf4, 0x15, 0xda, 0xd7,
-	0x23, 0x4e, 0x66, 0xc9, 0xb8, 0xaa, 0x69, 0x8e, 0xf2, 0xd6, 0x95, 0x7e,
-	0xd0, 0x49, 0xff, 0x02, 0x5a, 0x33, 0x72, 0xc3, 0xd0, 0xf1, 0x0a, 0x3b,
-	0xbe, 0x1a, 0xc3, 0x37, 0xa9, 0x28, 0xf4, 0x21, 0xe5, 0xcd, 0x0e, 0xe3,
-	0x9b, 0xcb, 0x43, 0x80, 0x35, 0xfc, 0x3e, 0xa8, 0x6d, 0xce, 0xa7, 0x4b,
-	0x94, 0x49, 0xf3, 0xb4, 0x68, 0x7c, 0x97, 0x56, 0xf4, 0x55, 0x6d, 0xaf,
-	0xbb, 0x32, 0x60, 0xe6, 0xfc, 0x30, 0xe7, 0x9c, 0xbe, 0x48, 0xfb, 0x03,
-	0x03, 0x96, 0xbf, 0x92, 0xa3, 0x79, 0x79, 0xbb, 0x1d, 0xfb, 0x1f, 0x2e,
-	0x33, 0x77, 0x8d, 0x73, 0x73, 0x37, 0x50, 0x59, 0x3c, 0x46, 0x91, 0xb6,
-	0x07, 0x58, 0xcf, 0x85, 0x8d, 0x94, 0x92, 0x5a, 0x9f, 0xf2, 0x93, 0xb6,
-	0x12, 0xd2, 0x27, 0xb6, 0x78, 0x4d, 0xf0, 0x01, 0x9e, 0x5e, 0x62, 0x77,
-	0x25, 0xac, 0xdc, 0xa4, 0x1f, 0x1c, 0xf6, 0x91, 0xb7, 0x72, 0x32, 0x8f,
-	0xf6, 0x47, 0x9c, 0xfe, 0xca, 0x72, 0xf2, 0x32, 0x94, 0x93, 0x1c, 0x8f,
-	0x23, 0x77, 0x3c, 0x48, 0x1e, 0x7d, 0xbf, 0xb6, 0xaf, 0xb7, 0x6e, 0xab,
-	0x01, 0xfe, 0x08, 0xc7, 0xcc, 0x1a, 0xa2, 0x33, 0xf7, 0x08, 0x6c, 0x22,
-	0x3b, 0x6f, 0xbb, 0xe7, 0xe6, 0x5f, 0xd3, 0x05, 0x7e, 0x33, 0x8e, 0x6a,
-	0x68, 0xa4, 0xc6, 0x77, 0x34, 0x2d, 0xd4, 0x2e, 0xb1, 0x65, 0x39, 0x06,
-	0xda, 0xb3, 0xb5, 0xc6, 0x16, 0x2c, 0xd1, 0xfe, 0xa4, 0xec, 0xa2, 0xfd,
-	0xf9, 0x43, 0xe0, 0x88, 0xe3, 0xe9, 0xb2, 0x69, 0xb4, 0x53, 0x17, 0x8f,
-	0x6f, 0xb1, 0xff, 0x48, 0x38, 0x09, 0xb7, 0xa1, 0xad, 0x84, 0x22, 0x6c,
-	0x81, 0x0c, 0x80, 0x97, 0x39, 0x07, 0x8a, 0xb6, 0xeb, 0xb6, 0xbf, 0xa8,
-	0x31, 0x31, 0xe4, 0xd5, 0xb5, 0x52, 0xcf, 0x3e, 0xc9, 0x7f, 0x7c, 0xaf,
-	0xd2, 0xf6, 0xef, 0x52, 0x59, 0x56, 0xad, 0x7b, 0xae, 0x9e, 0xc3, 0x5f,
-	0xff, 0x82, 0x39, 0x0a, 0xf1, 0x17, 0xd2, 0x45, 0x35, 0x0e, 0x49, 0x13,
-	0x86, 0x16, 0x0c, 0x2d, 0x6e, 0xb4, 0xfa, 0x26, 0xa4, 0xbd, 0xab, 0x40,
-	0x7b, 0xf7, 0x81, 0xc6, 0x28, 0xc3, 0x19, 0x97, 0x5b, 0x8b, 0xef, 0x23,
-	0xf8, 0x0e, 0xf9, 0xe4, 0x4a, 0x32, 0x9c, 0xf2, 0x9b, 0x75, 0xb2, 0x56,
-	0xee, 0x87, 0x7e, 0x2e, 0xeb, 0x70, 0xdc, 0x94, 0xff, 0xff, 0x15, 0xed,
-	0xac, 0xad, 0x35, 0xf6, 0xca, 0x8d, 0xb5, 0x94, 0xaf, 0x6b, 0xe4, 0x60,
-	0x55, 0xda, 0x95, 0xe4, 0x77, 0xf5, 0x98, 0xd7, 0xff, 0x3f, 0x18, 0x73,
-	0x7c, 0xd1, 0x98, 0x3d, 0x3b, 0xe6, 0x77, 0x21, 0xbf, 0xc9, 0xf8, 0x38,
-	0x1e, 0xf9, 0x2e, 0x1c, 0xb3, 0xc5, 0x85, 0x1e, 0x57, 0xb5, 0x9c, 0x08,
-	0x65, 0x04, 0xc7, 0x35, 0x60, 0xc7, 0xf0, 0xb9, 0xaa, 0x71, 0x0d, 0xbc,
-	0x89, 0x71, 0xb5, 0x2e, 0x18, 0xd7, 0xf6, 0x2b, 0x8e, 0x6b, 0x39, 0x1e,
-	0x27, 0x2f, 0x87, 0xe3, 0x8b, 0xca, 0xae, 0x22, 0xc7, 0xd8, 0x8f, 0x31,
-	0x1e, 0xd4, 0xfe, 0x80, 0x19, 0x63, 0xda, 0x8e, 0x51, 0x54, 0xdb, 0xb6,
-	0x7f, 0x8f, 0xdf, 0xd5, 0xe3, 0xa3, 0xee, 0xff, 0x3e, 0x68, 0xba, 0x4e,
-	0xb2, 0x5d, 0x75, 0x56, 0xfe, 0xdf, 0x24, 0x1f, 0x2e, 0x71, 0xae, 0x93,
-	0x19, 0x91, 0x51, 0xe8, 0xe0, 0xff, 0x5c, 0xcb, 0xd8, 0xfd, 0xf6, 0x94,
-	0xd5, 0x63, 0xd0, 0x17, 0x3b, 0x60, 0xf3, 0xf5, 0x17, 0x55, 0x77, 0x44,
-	0x82, 0xe0, 0xb6, 0xd4, 0xa7, 0xd1, 0xf7, 0x7e, 0xed, 0xab, 0x2e, 0x8d,
-	0x9b, 0x3f, 0x57, 0x2b, 0x3e, 0xed, 0x0d, 0xea, 0x73, 0xe8, 0xbb, 0xe3,
-	0xb4, 0xc1, 0xb2, 0xb0, 0x93, 0x33, 0xf1, 0x88, 0xb6, 0xc5, 0xa8, 0x13,
-	0x93, 0xf1, 0x8c, 0xa4, 0xd1, 0x5f, 0x26, 0xae, 0x84, 0x7d, 0xc0, 0x56,
-	0x83, 0x0d, 0xf9, 0xe1, 0xca, 0x3e, 0x3c, 0x0f, 0xcb, 0xad, 0xb0, 0x77,
-	0x6e, 0x7d, 0xe4, 0x0b, 0x72, 0x1b, 0x6c, 0x9d, 0xdb, 0x1e, 0x19, 0x93,
-	0xbd, 0xb0, 0x6d, 0xf6, 0xc2, 0xce, 0xd9, 0x5b, 0xa1, 0xed, 0x39, 0x8e,
-	0xb2, 0xad, 0x55, 0xb4, 0x46, 0x1b, 0x87, 0xe3, 0x23, 0xee, 0x0f, 0x72,
-	0x0e, 0x52, 0x09, 0xf5, 0x8a, 0x9e, 0x97, 0xa6, 0x05, 0x69, 0xaf, 0x27,
-	0xab, 0x42, 0xfd, 0xb4, 0xca, 0xc6, 0x8d, 0x8c, 0x0d, 0x78, 0x65, 0xda,
-	0x22, 0x8d, 0x78, 0xc0, 0x33, 0xf1, 0x47, 0xda, 0xaa, 0x1e, 0x7f, 0x63,
-	0x9d, 0xf8, 0x2b, 0xeb, 0xa4, 0xfe, 0x73, 0x90, 0xaf, 0xd5, 0x34, 0xc5,
-	0xb7, 0x67, 0x75, 0x0d, 0x69, 0x8b, 0x32, 0x38, 0xa4, 0x87, 0x8d, 0xaf,
-	0x23, 0x7f, 0xaf, 0x48, 0x4f, 0xfb, 0xb9, 0x2e, 0xb3, 0xbb, 0x5b, 0x56,
-	0x33, 0x1e, 0x90, 0xad, 0xcc, 0xc7, 0x04, 0x94, 0x5f, 0x1d, 0x13, 0xa0,
-	0x9f, 0xf5, 0x01, 0xe0, 0xec, 0x16, 0x3c, 0xfb, 0x64, 0x88, 0x71, 0x87,
-	0x4a, 0x68, 0x97, 0x7f, 0xd5, 0xda, 0xe5, 0x21, 0x1c, 0x09, 0xc0, 0x61,
-	0xe4, 0xf3, 0x52, 0x3d, 0xb7, 0x50, 0x7f, 0xe7, 0xe7, 0x6c, 0xda, 0x84,
-	0xec, 0x2a, 0x71, 0xdc, 0x94, 0xc1, 0xc4, 0x4d, 0xb5, 0x0c, 0x8e, 0x5b,
-	0x3b, 0x0a, 0x65, 0xb4, 0xfc, 0x5c, 0x2a, 0x3b, 0x29, 0xf7, 0x18, 0x9f,
-	0x7f, 0x20, 0x45, 0x5a, 0x7f, 0xb7, 0x64, 0xe6, 0xe2, 0xf3, 0x02, 0x7a,
-	0x93, 0x54, 0x24, 0xad, 0xd7, 0xd3, 0xbc, 0x09, 0xd9, 0x21, 0xbd, 0x31,
-	0xc6, 0x3a, 0x19, 0xcf, 0xf3, 0xf3, 0x13, 0xb0, 0x1f, 0x86, 0x4b, 0x0a,
-	0x16, 0x7c, 0xad, 0x0c, 0x79, 0x81, 0x6c, 0x4f, 0x39, 0x3a, 0x76, 0x6c,
-	0x74, 0x6d, 0xa9, 0xce, 0xd8, 0xae, 0x8e, 0x8e, 0xff, 0xce, 0x80, 0xfa,
-	0x66, 0xb4, 0x7d, 0xab, 0xb4, 0xfe, 0x9d, 0xd6, 0x65, 0x46, 0xeb, 0xc2,
-	0x38, 0xe6, 0x8c, 0x17, 0xb1, 0xe5, 0xaa, 0xd3, 0xa7, 0xea, 0x42, 0x5b,
-	0xb0, 0x50, 0x09, 0xd3, 0x9e, 0x5c, 0x26, 0xed, 0x85, 0x65, 0xd2, 0xfe,
-	0x76, 0x99, 0x34, 0x13, 0x17, 0xec, 0x2f, 0x5e, 0x46, 0xde, 0x88, 0xe6,
-	0x55, 0x69, 0x36, 0xf6, 0x75, 0x7e, 0xae, 0xcc, 0x2a, 0xeb, 0x97, 0x31,
-	0x46, 0x6c, 0x62, 0xc3, 0x39, 0x1d, 0x1b, 0xde, 0xe2, 0x6d, 0x53, 0x8c,
-	0x75, 0x11, 0x17, 0x09, 0xd9, 0xab, 0xf1, 0x42, 0x9c, 0x7c, 0x85, 0x31,
-	0xe0, 0x3c, 0xd7, 0x5a, 0x13, 0xea, 0x4a, 0xb4, 0x3d, 0x6f, 0x9b, 0x98,
-	0x79, 0x8b, 0xe9, 0x75, 0xd5, 0x3e, 0xd8, 0x0a, 0xfd, 0xc5, 0x26, 0xd9,
-	0x3e, 0x96, 0x58, 0x41, 0xbd, 0xb5, 0x63, 0xcc, 0xf8, 0x83, 0x7b, 0xc1,
-	0x57, 0x19, 0x21, 0x8c, 0xc9, 0x94, 0x08, 0x6d, 0xe2, 0xa5, 0xb6, 0xf0,
-	0xeb, 0xb7, 0xd7, 0x7b, 0x85, 0xf6, 0x1c, 0xd8, 0x0e, 0x3f, 0x6b, 0x7b,
-	0xf5, 0xd2, 0x37, 0x16, 0xe2, 0x4a, 0xfd, 0x9c, 0xf5, 0x22, 0x57, 0xa8,
-	0xa7, 0xed, 0x12, 0x79, 0x66, 0x4e, 0x16, 0x6f, 0x84, 0xcd, 0x24, 0x41,
-	0xb6, 0x5b, 0x5a, 0x23, 0xa2, 0x63, 0x3c, 0x29, 0x23, 0x9b, 0x3b, 0xb8,
-	0xb6, 0x03, 0xfa, 0x37, 0xb6, 0x8a, 0x89, 0x9b, 0x86, 0x76, 0xca, 0x72,
-	0xb4, 0x7b, 0xbd, 0xa5, 0x5d, 0xae, 0xa9, 0xee, 0xa0, 0xcc, 0xc5, 0x9c,
-	0x18, 0x3a, 0xde, 0x5e, 0x94, 0x44, 0x48, 0xc7, 0x33, 0xf0, 0x8b, 0xab,
-	0xe9, 0x78, 0x46, 0x52, 0x9a, 0x8e, 0x6b, 0x17, 0xd0, 0x71, 0xab, 0xa5,
-	0xe3, 0x77, 0x44, 0x0d, 0x5d, 0x28, 0xad, 0xa7, 0x48, 0xa7, 0x86, 0x8e,
-	0x1d, 0x4d, 0xc7, 0x33, 0x78, 0xbb, 0x7e, 0x8f, 0x2d, 0x13, 0xb1, 0x69,
-	0xfc, 0x1d, 0xa6, 0x51, 0x2e, 0xfe, 0x66, 0xd4, 0xe8, 0xa5, 0x14, 0xe8,
-	0x28, 0x4c, 0xff, 0x60, 0xd4, 0xd0, 0x67, 0x75, 0x9a, 0x89, 0x8f, 0xf4,
-	0x17, 0xdf, 0x13, 0x5d, 0x48, 0x9f, 0x29, 0xd0, 0x67, 0x58, 0xe6, 0xf5,
-	0xe8, 0xb3, 0xde, 0xae, 0x5b, 0x44, 0xf5, 0xba, 0x7b, 0x26, 0x66, 0x68,
-	0xf5, 0x56, 0x3d, 0x76, 0x8e, 0xfb, 0xd9, 0x9f, 0x81, 0x56, 0xcd, 0xdc,
-	0x9c, 0x9f, 0xf7, 0xb7, 0x19, 0x8b, 0x4a, 0x98, 0x18, 0x36, 0xe3, 0xa4,
-	0x57, 0xb2, 0x1d, 0x8d, 0x7c, 0xaa, 0xd1, 0xf2, 0xa9, 0x71, 0x48, 0xa5,
-	0xab, 0x65, 0x76, 0x37, 0x74, 0x05, 0x6d, 0x6c, 0x2d, 0xa7, 0x91, 0xd7,
-	0x9a, 0xc8, 0x16, 0xff, 0xd9, 0xee, 0x5f, 0xe0, 0xba, 0x80, 0x0c, 0x39,
-	0x48, 0x6b, 0x2b, 0x9b, 0x71, 0x29, 0xbf, 0x11, 0xdf, 0xdd, 0xd2, 0x56,
-	0x56, 0x72, 0xfb, 0x58, 0x83, 0xec, 0x2b, 0xba, 0xf2, 0x51, 0xd4, 0xff,
-	0x48, 0xd1, 0x83, 0x3f, 0x3e, 0x1e, 0xa5, 0x5d, 0xb8, 0xb7, 0xc8, 0xf5,
-	0x49, 0xc7, 0xac, 0x19, 0x2d, 0x58, 0xf3, 0x8c, 0x48, 0x5b, 0x47, 0x01,
-	0x9e, 0x8a, 0xb8, 0x3b, 0x01, 0x47, 0x5d, 0x3a, 0x2d, 0xaf, 0x74, 0x0f,
-	0x38, 0xda, 0x97, 0x70, 0x7a, 0xe4, 0xc6, 0x4a, 0x5a, 0x6e, 0xa8, 0x98,
-	0x75, 0xd2, 0xf9, 0x75, 0xd0, 0xa4, 0x37, 0x0d, 0x9d, 0x93, 0xf1, 0x82,
-	0xe0, 0x3c, 0xe4, 0xb7, 0x3a, 0xe2, 0x4a, 0xb4, 0x23, 0x19, 0x9f, 0x16,
-	0xf3, 0x7d, 0xb1, 0xfc, 0xe3, 0x60, 0x28, 0xe6, 0xca, 0x2b, 0x3e, 0xc7,
-	0xd5, 0x23, 0xd7, 0x97, 0xab, 0xfb, 0xe3, 0x5a, 0xe9, 0x13, 0x51, 0xae,
-	0x4d, 0x64, 0x2b, 0xe5, 0x28, 0xe3, 0xe7, 0x22, 0x79, 0x69, 0x7b, 0x2b,
-	0x7c, 0x37, 0x48, 0xeb, 0xb6, 0xb7, 0x82, 0x56, 0x62, 0xd0, 0xf3, 0x5b,
-	0x01, 0xd7, 0x56, 0xc6, 0xbb, 0x18, 0xe7, 0xe2, 0xf7, 0x5f, 0xa2, 0x5f,
-	0xd6, 0xfd, 0x5d, 0xbd, 0x66, 0x25, 0x8a, 0x73, 0x6e, 0xf8, 0x65, 0x79,
-	0x5d, 0xd3, 0x38, 0x14, 0x4d, 0x8b, 0x13, 0x7d, 0x5b, 0x5c, 0x56, 0xf8,
-	0xd5, 0xfd, 0x73, 0xed, 0x57, 0x14, 0x70, 0xe8, 0xee, 0xd8, 0xdc, 0x23,
-	0x7d, 0x18, 0x5f, 0xff, 0x92, 0xf1, 0xed, 0x17, 0xc6, 0x54, 0x2f, 0x16,
-	0x39, 0x86, 0xf9, 0x71, 0xa9, 0x3f, 0x32, 0xe3, 0x8a, 0x76, 0x2c, 0x1e,
-	0x8f, 0xae, 0xaf, 0x4e, 0x01, 0x96, 0xe7, 0xf4, 0x1e, 0x81, 0x20, 0xb8,
-	0xa6, 0xe3, 0x62, 0x90, 0x58, 0x97, 0xec, 0x9c, 0x9e, 0x5f, 0xd3, 0x19,
-	0x8a, 0xa4, 0x33, 0x1a, 0xff, 0xf8, 0x4e, 0xe4, 0xca, 0xdd, 0x98, 0x3b,
-	0x71, 0x73, 0x5d, 0xae, 0xe6, 0x8d, 0x9c, 0xdf, 0x6d, 0xd7, 0xad, 0x42,
-	0xbf, 0x29, 0x08, 0x94, 0xbf, 0x58, 0x56, 0x50, 0x47, 0x61, 0xec, 0xb2,
-	0xdb, 0xee, 0x4b, 0x49, 0x31, 0x6e, 0x38, 0xe4, 0xa6, 0xa3, 0x89, 0x42,
-	0xb9, 0x0b, 0xbf, 0x1b, 0xf0, 0xfe, 0x45, 0xd8, 0x28, 0x3d, 0xb0, 0x61,
-	0x24, 0xa6, 0x8c, 0x3c, 0x00, 0xfd, 0x76, 0xe4, 0x95, 0x22, 0x3f, 0x7a,
-	0x89, 0xe1, 0x72, 0x2c, 0x31, 0x5a, 0xde, 0xcb, 0xfa, 0x28, 0x7b, 0xa5,
-	0xf8, 0x1d, 0xfb, 0x62, 0x1f, 0xf4, 0x79, 0x7f, 0x96, 0x3e, 0x5c, 0xdb,
-	0x36, 0xdb, 0x0c, 0xf1, 0xe2, 0xd2, 0x0d, 0xc7, 0xbf, 0x6e, 0xeb, 0x8f,
-	0x70, 0x7c, 0x7b, 0x2d, 0xdc, 0x8b, 0xfb, 0x7d, 0x49, 0xdb, 0x2c, 0x8f,
-	0x55, 0x68, 0x27, 0x72, 0x4d, 0x27, 0x79, 0x62, 0x5c, 0x08, 0x47, 0x10,
-	0x5c, 0x48, 0x19, 0x7d, 0xfd, 0x74, 0x85, 0xeb, 0x1a, 0x41, 0xf0, 0x5d,
-	0xda, 0xc2, 0x83, 0x25, 0xf4, 0x17, 0xe2, 0x60, 0x63, 0xde, 0x85, 0x2c,
-	0x1c, 0xe9, 0x26, 0x7e, 0x05, 0x5e, 0x69, 0x87, 0xb7, 0x4b, 0xa2, 0x89,
-	0xdf, 0x2e, 0x37, 0x24, 0x3e, 0x51, 0xf6, 0x80, 0x67, 0x8e, 0x3b, 0x96,
-	0xd8, 0x63, 0xc7, 0xcc, 0xfd, 0x20, 0xaf, 0xbf, 0x4f, 0xe3, 0xa5, 0x05,
-	0x3e, 0x12, 0x61, 0x9a, 0x87, 0x85, 0xb0, 0x25, 0x2c, 0x6e, 0x82, 0xe0,
-	0xfb, 0x29, 0xf6, 0xd9, 0xcd, 0xfd, 0x00, 0x23, 0xe8, 0x37, 0xbf, 0x56,
-	0x11, 0x0f, 0xd1, 0xc4, 0x1d, 0xe8, 0xfb, 0xb7, 0xd1, 0xf7, 0xbe, 0x32,
-	0xfb, 0x83, 0x7c, 0xc0, 0xd8, 0x47, 0x2a, 0x21, 0xbc, 0xcb, 0xf5, 0x1d,
-	0xce, 0x79, 0xa7, 0xb5, 0xeb, 0xc2, 0x6f, 0x8d, 0x48, 0x4f, 0xc1, 0x97,
-	0xcb, 0x56, 0x66, 0xd6, 0xb8, 0xf2, 0x2e, 0xc8, 0xda, 0x40, 0x4e, 0x42,
-	0x86, 0xcd, 0x68, 0xba, 0xc9, 0xae, 0xe7, 0xff, 0x11, 0xf9, 0xe4, 0x0a,
-	0xc6, 0x94, 0x7b, 0x7d, 0xda, 0xab, 0xb3, 0xc1, 0x8c, 0x4f, 0x99, 0xbc,
-	0x4a, 0xc6, 0xbd, 0x7c, 0x27, 0xf4, 0x03, 0xd2, 0x1a, 0xe9, 0x63, 0x27,
-	0xb2, 0x91, 0x64, 0x62, 0x58, 0xb8, 0xc7, 0x89, 0xfb, 0x13, 0xb8, 0xef,
-	0x87, 0xf2, 0xc0, 0x85, 0x9c, 0xe3, 0x1c, 0x9a, 0xfe, 0x86, 0xcb, 0xf3,
-	0x65, 0x0f, 0x08, 0xd7, 0x09, 0x93, 0xf1, 0xbd, 0xda, 0x26, 0x01, 0xd5,
-	0x15, 0x59, 0x76, 0x33, 0x2c, 0x12, 0xbf, 0xaa, 0xbc, 0xde, 0x73, 0x05,
-	0x3e, 0x67, 0x1c, 0x21, 0x1a, 0xcd, 0x16, 0xe5, 0xb5, 0x48, 0xb7, 0xbc,
-	0x96, 0x4d, 0xd5, 0x4b, 0xaf, 0x96, 0xf9, 0xcc, 0xd3, 0xe9, 0xb3, 0x26,
-	0xdd, 0x85, 0x2e, 0xe1, 0x9c, 0xf4, 0x40, 0x46, 0x4f, 0x00, 0x6e, 0xe2,
-	0xb0, 0x87, 0x32, 0x89, 0xf3, 0xa7, 0x54, 0x3a, 0x16, 0xcd, 0x95, 0xa5,
-	0x2f, 0x57, 0xb4, 0xb1, 0x9e, 0x01, 0x8e, 0x7f, 0x95, 0xc5, 0x43, 0xa3,
-	0xb8, 0x80, 0xad, 0x2f, 0x92, 0x70, 0xe0, 0x2b, 0x43, 0xd7, 0x3f, 0xba,
-	0x4a, 0x1a, 0x89, 0x9b, 0x1e, 0xf0, 0x52, 0x0d, 0x74, 0xd1, 0xfd, 0xcd,
-	0x5c, 0x37, 0xd5, 0x36, 0x64, 0xec, 0x63, 0xbf, 0xac, 0xd2, 0x7f, 0x1b,
-	0x57, 0xe9, 0x51, 0x2b, 0x2f, 0xa3, 0x7d, 0x94, 0x97, 0x4f, 0x97, 0x08,
-	0x8f, 0x78, 0x11, 0x3f, 0xd1, 0xd7, 0x5b, 0x16, 0x15, 0x49, 0x7b, 0xd1,
-	0xde, 0xf2, 0x42, 0xfa, 0x7f, 0xba, 0xf2, 0x61, 0x6b, 0x0b, 0x56, 0xc7,
-	0x54, 0xab, 0xf3, 0xc8, 0x83, 0xcb, 0xe5, 0x11, 0x26, 0x89, 0xae, 0x48,
-	0x5f, 0xf8, 0x54, 0x7b, 0x47, 0xde, 0xab, 0x15, 0xe2, 0x39, 0x80, 0xdc,
-	0x06, 0xae, 0xcb, 0x5c, 0xaf, 0xde, 0x8f, 0x79, 0xfb, 0x3f, 0x41, 0x26,
-	0xc6, 0x7c, 0x4f, 0xea, 0xe0, 0xdb, 0xbe, 0x0c, 0xdd, 0xf9, 0x8a, 0x7f,
-	0xe1, 0x53, 0x9d, 0x1d, 0x41, 0xf0, 0xac, 0x9f, 0x4f, 0xb8, 0x90, 0x1f,
-	0x87, 0x2d, 0xbe, 0x87, 0x81, 0xef, 0x89, 0x39, 0x7c, 0x27, 0xe4, 0x62,
-	0xd7, 0xf7, 0x03, 0xae, 0xf5, 0x0d, 0x97, 0x6f, 0xbd, 0x55, 0xa5, 0x3f,
-	0xfe, 0xa1, 0x6c, 0x37, 0xfb, 0x1b, 0x91, 0xc3, 0x95, 0x9b, 0x88, 0xbf,
-	0x28, 0xc6, 0x7a, 0x4f, 0x9f, 0x6f, 0xfa, 0xed, 0x5b, 0xd0, 0x2f, 0xe9,
-	0xe5, 0x47, 0xac, 0x8b, 0x32, 0xd5, 0x75, 0x33, 0xa0, 0xcb, 0xbc, 0xad,
-	0x3b, 0x70, 0x85, 0xba, 0xde, 0x15, 0xea, 0x1e, 0x46, 0xdd, 0x3d, 0xb6,
-	0xee, 0x85, 0xcf, 0xbc, 0xb9, 0x7e, 0x07, 0xb8, 0xc7, 0x0e, 0x3e, 0x80,
-	0xb8, 0x11, 0xff, 0x36, 0xfc, 0xbe, 0x85, 0xed, 0x28, 0xda, 0xf7, 0x23,
-	0x95, 0x21, 0x19, 0xae, 0xec, 0xc4, 0x33, 0x88, 0xb4, 0x3e, 0x3c, 0xfb,
-	0xf0, 0x3b, 0x8d, 0x47, 0xa2, 0x6e, 0xfa, 0xc2, 0x5d, 0xc3, 0x7e, 0x88,
-	0x57, 0xae, 0xcd, 0xb3, 0x0f, 0xd8, 0x17, 0x5d, 0x3f, 0x41, 0x1f, 0x61,
-	0xfa, 0x07, 0x50, 0x67, 0x1a, 0x69, 0x2b, 0x69, 0x7b, 0x62, 0xae, 0xab,
-	0xeb, 0x54, 0xc3, 0x36, 0x1d, 0xce, 0x05, 0xf2, 0x0d, 0x8d, 0xf6, 0x16,
-	0x43, 0x18, 0xef, 0x44, 0x1b, 0xe3, 0x57, 0x29, 0xff, 0x1e, 0xc2, 0x15,
-	0x57, 0xfe, 0xc7, 0xf0, 0x7e, 0x2d, 0xd8, 0x9d, 0x62, 0x4c, 0x9e, 0xf3,
-	0x7e, 0xdd, 0xaa, 0xa5, 0x7b, 0x9f, 0x42, 0x1a, 0xe8, 0x84, 0x4e, 0x69,
-	0xb0, 0x74, 0x5a, 0x80, 0xe5, 0x43, 0x1a, 0xe5, 0x98, 0x17, 0x97, 0x4d,
-	0x76, 0xe6, 0xa5, 0x07, 0xba, 0x8c, 0xb2, 0xf6, 0xd3, 0xf5, 0x26, 0x0e,
-	0x03, 0xcb, 0xd1, 0xef, 0x04, 0x3d, 0x37, 0x88, 0x87, 0xfa, 0x03, 0x11,
-	0x0f, 0x34, 0x18, 0xd6, 0x4f, 0x7a, 0x03, 0x11, 0x8e, 0x19, 0x1c, 0x5f,
-	0xe6, 0xba, 0x34, 0x6d, 0x6b, 0xd6, 0x0f, 0x6d, 0x1c, 0xfe, 0x7b, 0x59,
-	0xc4, 0x67, 0x1a, 0xdb, 0x0b, 0xde, 0x55, 0xe3, 0x2f, 0x59, 0x63, 0xc1,
-	0x38, 0xf3, 0x49, 0x68, 0x30, 0xaf, 0x4f, 0xcb, 0xe9, 0xfc, 0x35, 0x35,
-	0xd2, 0xe0, 0xf5, 0xeb, 0xdf, 0x2c, 0xd3, 0xe0, 0x81, 0x4f, 0x17, 0x95,
-	0x61, 0x1a, 0xf3, 0x0a, 0x6b, 0x94, 0xde, 0xab, 0xa4, 0xf7, 0x28, 0xc9,
-	0x83, 0xa9, 0x64, 0x62, 0x48, 0x25, 0xbd, 0x71, 0xd9, 0x0f, 0xb9, 0x43,
-	0x39, 0x39, 0x73, 0x7f, 0x44, 0xb8, 0x9f, 0xef, 0x5d, 0x92, 0xf5, 0x29,
-	0x3f, 0x0b, 0x9f, 0x57, 0x94, 0x75, 0x95, 0x97, 0x1a, 0xcc, 0xd8, 0xb8,
-	0x0f, 0x01, 0x70, 0x36, 0xd1, 0x86, 0xbb, 0xb5, 0x81, 0x3c, 0x94, 0x50,
-	0x11, 0xd9, 0x45, 0x3f, 0x5f, 0x7d, 0xb1, 0x5e, 0xea, 0xa7, 0xd7, 0x78,
-	0x52, 0xd1, 0xe9, 0x66, 0x7f, 0x60, 0xb2, 0x73, 0x48, 0x89, 0x1e, 0x7b,
-	0x46, 0xbd, 0x91, 0xcc, 0x9e, 0xb5, 0xfa, 0x23, 0x90, 0xc7, 0xb4, 0xbe,
-	0x98, 0xf9, 0xbc, 0x2b, 0x17, 0x82, 0xb6, 0x4d, 0x17, 0xda, 0xb3, 0x5d,
-	0xb4, 0x73, 0x57, 0xd9, 0xfd, 0x95, 0x8c, 0x63, 0xbd, 0x4b, 0x9e, 0xf3,
-	0x0b, 0x18, 0xf7, 0x7e, 0xb9, 0xe0, 0xb3, 0xbf, 0x99, 0xcf, 0x79, 0xc2,
-	0x74, 0xc2, 0x6e, 0xfa, 0x13, 0xf5, 0xa7, 0x80, 0x87, 0x7d, 0x52, 0x07,
-	0x5f, 0xc9, 0xee, 0x4b, 0x0e, 0xe4, 0x45, 0xcf, 0x4b, 0x8f, 0xa0, 0xad,
-	0x15, 0x3e, 0xf8, 0x10, 0x76, 0x73, 0xcd, 0x91, 0xab, 0x21, 0x77, 0x1d,
-	0xbd, 0xc7, 0x02, 0x93, 0xe1, 0x4d, 0x61, 0xde, 0x33, 0x03, 0x2c, 0x57,
-	0x2f, 0xd3, 0x31, 0xf2, 0xba, 0xe6, 0x97, 0x4f, 0x65, 0xfd, 0x76, 0x4f,
-	0x39, 0xc3, 0x8c, 0x31, 0x00, 0xaf, 0xa4, 0xcd, 0x54, 0x6c, 0xbb, 0xcf,
-	0xb6, 0x58, 0xe6, 0x2a, 0xf9, 0xf6, 0xc0, 0x85, 0x7f, 0x78, 0xd6, 0xff,
-	0x7b, 0xc0, 0x91, 0x81, 0x4c, 0xe0, 0xf3, 0x6a, 0x90, 0x8f, 0x31, 0xa6,
-	0xf5, 0xbf, 0xeb, 0xad, 0x9d, 0xac, 0x79, 0x7f, 0x58, 0xef, 0x93, 0x79,
-	0xfe, 0x33, 0x59, 0xae, 0x77, 0xc0, 0x36, 0xc9, 0x69, 0xb9, 0x18, 0xfd,
-	0x69, 0x0e, 0xf0, 0x14, 0x2a, 0xb4, 0x43, 0xfe, 0x06, 0x76, 0x88, 0xd6,
-	0x93, 0xf2, 0xed, 0x41, 0xe6, 0xb1, 0xdd, 0xec, 0xd5, 0xae, 0xd6, 0x0b,
-	0x21, 0x2c, 0xc9, 0xce, 0x1c, 0xf2, 0x47, 0xb4, 0x1d, 0xef, 0xc9, 0xac,
-	0xe7, 0xea, 0x7d, 0x27, 0xf9, 0xc1, 0x20, 0x78, 0xc5, 0x77, 0xe5, 0xa4,
-	0x86, 0xf9, 0x05, 0xf4, 0xe1, 0xc8, 0xc4, 0x80, 0xfb, 0xd3, 0x93, 0x3e,
-	0xc7, 0xc7, 0x3c, 0xae, 0x2b, 0x6d, 0x8e, 0x1b, 0xf8, 0x68, 0x9b, 0x7e,
-	0x2f, 0x98, 0x8d, 0x71, 0xdd, 0x02, 0x3c, 0x5d, 0x6a, 0xf7, 0x6e, 0x90,
-	0xdb, 0xe6, 0x6c, 0x9a, 0x69, 0x31, 0x36, 0xa3, 0xd1, 0x69, 0x17, 0xfe,
-	0x61, 0xc4, 0xbf, 0xb0, 0xba, 0x80, 0xb9, 0x81, 0x0e, 0x5b, 0x0c, 0x4b,
-	0x8a, 0xb0, 0x0c, 0x6b, 0x58, 0x62, 0xc0, 0xa5, 0x0b, 0xd9, 0x77, 0x9b,
-	0x1c, 0x02, 0xde, 0x87, 0x06, 0x45, 0x9e, 0x85, 0x4d, 0x76, 0xbe, 0x0a,
-	0x9e, 0x19, 0xc0, 0x73, 0xde, 0xe7, 0x5e, 0x00, 0xe6, 0xf9, 0xde, 0xb0,
-	0x70, 0x2f, 0x00, 0x71, 0xd8, 0x81, 0xdf, 0x22, 0x33, 0xd0, 0xbf, 0x27,
-	0xfd, 0xd7, 0x82, 0xf1, 0x18, 0x75, 0x23, 0xda, 0x99, 0xdb, 0x1b, 0x14,
-	0xc8, 0xe7, 0x53, 0xd4, 0x43, 0xb5, 0xd2, 0xb6, 0x8e, 0x7e, 0x88, 0x91,
-	0x9f, 0x37, 0xf8, 0x19, 0xf4, 0xf5, 0x5b, 0x2b, 0xa5, 0x3e, 0x2f, 0xfd,
-	0x1d, 0x75, 0xc8, 0x73, 0x6d, 0xde, 0x80, 0xce, 0xeb, 0xef, 0x38, 0x8c,
-	0xfc, 0x8f, 0xaf, 0x64, 0xbc, 0xdb, 0xf5, 0xd7, 0x4b, 0xdb, 0x1a, 0xe6,
-	0x55, 0xf3, 0xe0, 0xab, 0xdc, 0x83, 0x69, 0x75, 0x38, 0x64, 0x59, 0x29,
-	0xef, 0x71, 0xa7, 0xdd, 0x21, 0xcc, 0xc5, 0x6e, 0x9f, 0xb2, 0xed, 0xbf,
-	0xa3, 0x6e, 0x4a, 0x6e, 0xf4, 0x07, 0x91, 0x37, 0x8d, 0xbc, 0xc3, 0x36,
-	0x6f, 0xd0, 0xe6, 0x6d, 0x43, 0xde, 0x3e, 0xe0, 0xef, 0x6e, 0x9d, 0x9e,
-	0xe5, 0x6f, 0x53, 0xc7, 0x5b, 0xd9, 0x71, 0xe1, 0x33, 0x37, 0xf8, 0x84,
-	0x0b, 0x79, 0x25, 0xae, 0x8b, 0xde, 0x26, 0x79, 0x2f, 0x79, 0x0b, 0x7b,
-	0xfd, 0x66, 0xb1, 0x0e, 0xb2, 0x89, 0x7b, 0x80, 0x69, 0xb3, 0x6e, 0xf1,
-	0x5e, 0x96, 0xff, 0x40, 0xba, 0xeb, 0xc9, 0x38, 0x5f, 0x5b, 0xc9, 0xb8,
-	0xd8, 0x88, 0x4f, 0xfb, 0x3a, 0x90, 0x9c, 0x5e, 0x3f, 0xa1, 0x7f, 0x5b,
-	0x44, 0x3a, 0xe9, 0x41, 0x35, 0x45, 0xf4, 0x3e, 0x2d, 0x7e, 0x47, 0x61,
-	0xf7, 0x06, 0x42, 0x9f, 0x8f, 0x36, 0x5d, 0xc6, 0xe3, 0xda, 0x50, 0x98,
-	0xe7, 0x21, 0x4f, 0x6d, 0x8a, 0xc0, 0x26, 0xaa, 0xf5, 0x1d, 0x1d, 0xa3,
-	0x2e, 0xe8, 0x75, 0x00, 0xc6, 0xdf, 0x32, 0xf0, 0x63, 0x02, 0xe9, 0x47,
-	0xdf, 0xa4, 0xfd, 0x68, 0x87, 0xef, 0x1d, 0x10, 0xee, 0x67, 0x65, 0x7a,
-	0xbb, 0xf7, 0x6d, 0x99, 0xa7, 0xf3, 0x19, 0x49, 0x66, 0x94, 0x03, 0xff,
-	0x75, 0xab, 0x23, 0xf5, 0xb0, 0x3d, 0x6e, 0x30, 0xfa, 0xcd, 0xe3, 0x9e,
-	0xc4, 0x8b, 0xda, 0x56, 0x6b, 0xb4, 0xf3, 0x91, 0x05, 0x6e, 0xb8, 0x1f,
-	0x7c, 0xe0, 0x9e, 0xdd, 0x7e, 0x21, 0x09, 0x6a, 0xd4, 0xba, 0x71, 0x18,
-	0xb4, 0x91, 0x4d, 0x19, 0xdd, 0x78, 0xc3, 0x9c, 0x6e, 0xfc, 0xf3, 0x95,
-	0xe4, 0x89, 0xe1, 0x72, 0x1c, 0x75, 0xf5, 0x3a, 0x4a, 0x82, 0x75, 0x6b,
-	0x31, 0x9f, 0xe7, 0xfd, 0xec, 0x35, 0xa0, 0x2f, 0xc8, 0xe1, 0x64, 0xe7,
-	0x29, 0xd4, 0x2d, 0xa0, 0xee, 0xe4, 0x5c, 0x5d, 0x47, 0x46, 0x7c, 0xbd,
-	0xef, 0x59, 0x26, 0xcb, 0x21, 0x1d, 0x26, 0xe3, 0xb7, 0x6a, 0x5e, 0xe0,
-	0x7e, 0x30, 0x37, 0x71, 0x9f, 0x6c, 0xd6, 0xb4, 0xdd, 0x27, 0xdc, 0x27,
-	0xc5, 0xb6, 0xef, 0x0b, 0xda, 0xd6, 0x10, 0xbe, 0x12, 0xde, 0xa4, 0x8d,
-	0x31, 0xbc, 0xc3, 0xf9, 0x37, 0xf3, 0x3e, 0xe4, 0x10, 0xdf, 0xbf, 0x1f,
-	0xe4, 0x07, 0x39, 0x2f, 0xfc, 0x9e, 0xa7, 0xb9, 0x11, 0xd0, 0x5c, 0xc4,
-	0x7f, 0xbb, 0x0c, 0xeb, 0x3d, 0x10, 0x29, 0x99, 0xd0, 0xf1, 0xcc, 0x0b,
-	0xc1, 0x23, 0x0b, 0xe4, 0xf8, 0x47, 0x94, 0xa1, 0x21, 0xfe, 0x2e, 0x24,
-	0xea, 0x64, 0x66, 0x4d, 0x9d, 0xde, 0xf1, 0x41, 0x7c, 0x8c, 0xde, 0x73,
-	0x3b, 0xf8, 0xf5, 0xfa, 0xb9, 0xb1, 0x00, 0xdf, 0xc0, 0xe3, 0x4e, 0x63,
-	0xeb, 0x63, 0x1c, 0x19, 0xed, 0xbf, 0x67, 0x8b, 0x4a, 0xef, 0x0b, 0xa2,
-	0x8e, 0x3f, 0x00, 0x9d, 0x6a, 0xf6, 0xa4, 0xe0, 0x5d, 0xe1, 0xbc, 0x29,
-	0xed, 0x73, 0x1c, 0x04, 0x0f, 0x1f, 0xf4, 0xb3, 0x6b, 0x6a, 0x75, 0xdb,
-	0x49, 0xef, 0x7a, 0x6d, 0x13, 0x6e, 0x94, 0x99, 0x14, 0xdb, 0x23, 0x5e,
-	0xfe, 0x47, 0x30, 0xe4, 0xcd, 0xa0, 0x7f, 0x43, 0xff, 0x59, 0x5f, 0xb5,
-	0xd4, 0x49, 0xf5, 0x3e, 0x53, 0xe2, 0xc9, 0x85, 0xbd, 0xd2, 0x01, 0xfc,
-	0x18, 0x78, 0x73, 0xe5, 0xb7, 0x49, 0x21, 0xe6, 0xda, 0xb1, 0x45, 0xb4,
-	0x2f, 0x37, 0x91, 0xaa, 0x83, 0x2d, 0xf8, 0x17, 0xc1, 0xe4, 0x82, 0x31,
-	0x1e, 0xac, 0x1a, 0xe3, 0x4c, 0x02, 0xd8, 0x68, 0x89, 0xcc, 0xc9, 0x01,
-	0xf6, 0x65, 0x64, 0x52, 0x38, 0xc6, 0x3a, 0x8c, 0x71, 0xc7, 0xdc, 0x18,
-	0x0f, 0x2f, 0x1a, 0xe3, 0x61, 0x8c, 0x11, 0xf6, 0x42, 0x29, 0xd3, 0xe9,
-	0xce, 0xcf, 0xfb, 0xd5, 0x35, 0x73, 0xf3, 0x29, 0xdc, 0xeb, 0x84, 0xf1,
-	0xd3, 0xa6, 0xd8, 0x08, 0x78, 0x74, 0x5b, 0x90, 0x71, 0x0e, 0x64, 0x5b,
-	0x76, 0x4d, 0x8d, 0x1d, 0xff, 0x76, 0x96, 0x2b, 0x1b, 0x1c, 0x9c, 0x4c,
-	0xb9, 0x9d, 0x8f, 0xa0, 0xbf, 0xbd, 0x76, 0x5c, 0xbd, 0xe5, 0xab, 0x31,
-	0xae, 0x0b, 0xdf, 0xc1, 0x18, 0xe0, 0xb3, 0x9d, 0xa0, 0x0f, 0x9c, 0x18,
-	0x92, 0x05, 0xb2, 0xeb, 0x33, 0xf3, 0x72, 0xd4, 0xc0, 0x4c, 0xdb, 0xba,
-	0x30, 0x07, 0xf3, 0xdd, 0x8b, 0x60, 0xbe, 0x1b, 0x30, 0xef, 0xb3, 0xf3,
-	0xb2, 0xaf, 0x6a, 0xcf, 0x62, 0x48, 0x47, 0xfc, 0xfd, 0xbc, 0xf5, 0x45,
-	0x3e, 0x20, 0xf7, 0x97, 0x3a, 0xe5, 0xcb, 0x95, 0xe4, 0x59, 0xc6, 0xd1,
-	0xcf, 0x55, 0x92, 0xe3, 0x22, 0x5d, 0xf2, 0xc7, 0xb0, 0x73, 0xae, 0x82,
-	0x6f, 0xf1, 0x34, 0xfc, 0xd7, 0x3f, 0xa9, 0xf8, 0xf2, 0xc4, 0xdc, 0x7e,
-	0x38, 0xea, 0xba, 0xb4, 0x9c, 0x84, 0x4f, 0xbb, 0xed, 0x68, 0x1b, 0xf7,
-	0x2a, 0x11, 0xbe, 0xbb, 0xa8, 0x73, 0xda, 0x94, 0xe6, 0xc5, 0xef, 0x62,
-	0xbc, 0xa7, 0xa9, 0x6b, 0xd6, 0xfa, 0xbe, 0x77, 0xb3, 0x5a, 0x47, 0x99,
-	0x90, 0xff, 0x5a, 0xe4, 0x03, 0xf5, 0x26, 0xc6, 0x92, 0xf1, 0x9a, 0xc9,
-	0x1b, 0xdb, 0x3a, 0x12, 0x7d, 0x42, 0x5b, 0x82, 0xfe, 0x36, 0x6c, 0xa1,
-	0xd2, 0xe6, 0xf8, 0x5a, 0xa1, 0x4c, 0xa2, 0x5d, 0x94, 0x96, 0x09, 0xc0,
-	0x3e, 0x06, 0x89, 0x50, 0x68, 0xf6, 0x47, 0x7b, 0xd5, 0x44, 0x03, 0x79,
-	0x70, 0xdb, 0x19, 0xd0, 0xd7, 0x36, 0x8c, 0xa9, 0x2b, 0x79, 0x76, 0x46,
-	0x65, 0x4e, 0xac, 0x95, 0x57, 0x82, 0xa1, 0x66, 0x47, 0x9e, 0xd8, 0xc4,
-	0x3c, 0x2d, 0xb7, 0x3f, 0xd5, 0x0b, 0xf9, 0xd4, 0xce, 0x73, 0x0b, 0x03,
-	0xf2, 0x2f, 0x77, 0x80, 0x06, 0x7f, 0xb8, 0xe9, 0x6b, 0xc1, 0x6c, 0xb3,
-	0x2b, 0x5b, 0x37, 0x25, 0xbd, 0xbc, 0xc2, 0x78, 0x4a, 0x18, 0x4f, 0x09,
-	0xe3, 0xe3, 0x98, 0x4b, 0x18, 0xd7, 0x15, 0xf7, 0x4a, 0xf5, 0x2c, 0x88,
-	0xcb, 0x1a, 0x3f, 0x2d, 0x93, 0x77, 0x65, 0x83, 0xdd, 0x2b, 0x35, 0x5c,
-	0x1f, 0xae, 0xb1, 0x65, 0x64, 0x3c, 0x28, 0xf8, 0x7f, 0x70, 0x55, 0xb6,
-	0x2b, 0xb6, 0x58, 0xe7, 0xdc, 0x35, 0xaf, 0x73, 0x44, 0x9e, 0x33, 0xf3,
-	0x86, 0x39, 0xf3, 0xbd, 0x49, 0x6e, 0x86, 0x87, 0x0e, 0xdc, 0xaa, 0xf7,
-	0x3c, 0x77, 0xe0, 0x9b, 0x36, 0xd5, 0xa7, 0xf5, 0x3a, 0xe2, 0x4c, 0xf9,
-	0x1e, 0x3b, 0x77, 0xf7, 0x68, 0x3d, 0xbb, 0x75, 0xd3, 0xa5, 0x80, 0xfb,
-	0xdc, 0xbc, 0x4d, 0xcb, 0xc5, 0x22, 0x68, 0xef, 0xd5, 0x69, 0xde, 0xe7,
-	0x7a, 0x76, 0x41, 0x9f, 0x13, 0x01, 0xde, 0xe6, 0xe2, 0x62, 0xf5, 0x48,
-	0xa3, 0xbe, 0xf8, 0x69, 0x83, 0x59, 0x47, 0xa5, 0x6c, 0x58, 0x83, 0x34,
-	0xd7, 0xec, 0x05, 0x5e, 0x90, 0xf7, 0xdf, 0xea, 0xcd, 0x9e, 0x8f, 0xea,
-	0xb2, 0xe0, 0x31, 0xbd, 0x2f, 0x84, 0xfb, 0x03, 0x7f, 0x79, 0xa5, 0xb1,
-	0x4d, 0xc3, 0x7c, 0xa6, 0xff, 0x38, 0x98, 0xd0, 0x31, 0x36, 0xf6, 0xf5,
-	0x43, 0xfc, 0x5e, 0xbc, 0x5f, 0x24, 0xb4, 0x5d, 0xeb, 0x40, 0xf7, 0xda,
-	0x5f, 0x16, 0x94, 0x89, 0xe7, 0x25, 0x22, 0x13, 0x55, 0x30, 0x4e, 0x10,
-	0xee, 0x52, 0xd7, 0xaa, 0xf9, 0xd8, 0xdd, 0x6a, 0xa4, 0x11, 0xc6, 0x75,
-	0x8b, 0xf2, 0xc8, 0x1b, 0xad, 0x2b, 0x49, 0x37, 0xd3, 0xc2, 0xb4, 0xf9,
-	0x31, 0xcd, 0x68, 0xfb, 0xb9, 0x6d, 0x95, 0xde, 0xfb, 0xc4, 0x35, 0x46,
-	0xc6, 0x08, 0x63, 0x26, 0xdf, 0xf5, 0xff, 0x56, 0xd7, 0x19, 0x9a, 0xab,
-	0xa3, 0xe7, 0x02, 0xf9, 0x6e, 0x55, 0x5e, 0x35, 0xdc, 0xd4, 0x5f, 0x43,
-	0x9d, 0x75, 0xd0, 0x89, 0x17, 0x53, 0xab, 0xc3, 0xbd, 0xf0, 0xb0, 0x21,
-	0xb2, 0xd7, 0xd4, 0x5a, 0x99, 0x3f, 0x81, 0x79, 0x7d, 0x26, 0x65, 0x78,
-	0x51, 0xf3, 0x61, 0xf1, 0x36, 0xf8, 0xeb, 0xa1, 0xde, 0xa0, 0x9c, 0x26,
-	0x6f, 0x22, 0xad, 0x42, 0x9f, 0xe0, 0xc2, 0xea, 0x99, 0xae, 0x57, 0x03,
-	0xee, 0xb3, 0x7c, 0x45, 0xdb, 0x51, 0x43, 0xb2, 0xb0, 0xed, 0xd1, 0x7b,
-	0x5e, 0xbf, 0xed, 0xa1, 0x65, 0xda, 0x1e, 0xb2, 0x6d, 0x8b, 0x6b, 0xda,
-	0x8e, 0x5e, 0xa1, 0xed, 0x81, 0x37, 0x68, 0x7b, 0x70, 0x99, 0xb6, 0x07,
-	0xc3, 0xb6, 0x95, 0x69, 0xdb, 0x0b, 0xdb, 0x4e, 0x2c, 0xc2, 0xc9, 0x67,
-	0x5e, 0xbf, 0xed, 0x7d, 0xcb, 0xb4, 0xbd, 0x6f, 0x11, 0xdc, 0xc4, 0x49,
-	0x2d, 0x74, 0xff, 0x3d, 0xda, 0xe6, 0xac, 0x03, 0xdf, 0x5c, 0x84, 0xfc,
-	0x36, 0xfe, 0xc8, 0x85, 0xbb, 0x66, 0xcb, 0xe0, 0x2b, 0xf8, 0xd7, 0x99,
-	0x72, 0x03, 0x9e, 0x71, 0xd8, 0x33, 0x28, 0x07, 0x7b, 0xbc, 0x26, 0x1d,
-	0xc8, 0xc9, 0x6e, 0x96, 0xcd, 0xc7, 0x6b, 0xe7, 0xf4, 0xc6, 0x3d, 0xe8,
-	0x8f, 0x6d, 0xfb, 0x5e, 0xbf, 0xbc, 0xa6, 0xfb, 0xcb, 0x95, 0xe9, 0x8f,
-	0x21, 0xbd, 0x42, 0x1f, 0x97, 0xf5, 0x42, 0x19, 0x58, 0x67, 0xd7, 0x3e,
-	0x68, 0x6b, 0x32, 0x0e, 0xa7, 0xed, 0x51, 0x29, 0x94, 0x7f, 0x12, 0x4c,
-	0x83, 0x2e, 0x46, 0xe6, 0x74, 0xc8, 0x93, 0xab, 0x68, 0xb3, 0x8f, 0x53,
-	0xb3, 0x54, 0xc5, 0xa0, 0x46, 0x7c, 0xa6, 0xfd, 0x98, 0x6d, 0xc2, 0x0e,
-	0x0c, 0xcb, 0x32, 0x6e, 0x6c, 0x62, 0x4e, 0x67, 0x21, 0x33, 0xcd, 0x9e,
-	0x0e, 0xfa, 0x2a, 0x4f, 0x81, 0x97, 0xf7, 0x43, 0x76, 0x24, 0xf3, 0x22,
-	0x3d, 0x8d, 0xe6, 0xac, 0x45, 0x4c, 0x72, 0x5d, 0xbf, 0x69, 0xf1, 0xb8,
-	0xef, 0xce, 0xe5, 0xcf, 0x59, 0x40, 0x3e, 0x38, 0x94, 0x91, 0xd7, 0x37,
-	0x9a, 0x75, 0xbb, 0xb7, 0x36, 0x32, 0x1e, 0xa3, 0x36, 0x75, 0xaf, 0xd6,
-	0xf2, 0xc7, 0x09, 0xbf, 0xbf, 0xb2, 0xe8, 0x3b, 0xac, 0xf7, 0x93, 0xd5,
-	0x0b, 0xeb, 0x85, 0xe9, 0x70, 0x4d, 0x16, 0xa4, 0x1f, 0x58, 0xb3, 0xb0,
-	0x7e, 0xac, 0x69, 0xe1, 0xf7, 0xe0, 0xa2, 0xef, 0xcf, 0x2c, 0xfa, 0x7e,
-	0x61, 0xd1, 0xf7, 0x75, 0x6b, 0x17, 0x95, 0x5f, 0xf4, 0xfd, 0xe5, 0xb5,
-	0xcb, 0xc3, 0xfb, 0x57, 0x6b, 0x17, 0xc2, 0xf5, 0x94, 0x5e, 0x73, 0x1d,
-	0xaf, 0xb8, 0xb2, 0xbd, 0x88, 0x7c, 0xe7, 0xd6, 0x18, 0xf2, 0xe1, 0xcb,
-	0x54, 0xe7, 0x73, 0x8d, 0xe3, 0x1d, 0xb1, 0x85, 0xed, 0xcd, 0xd7, 0xdb,
-	0x31, 0x5f, 0x2f, 0x35, 0x5f, 0xcf, 0xf8, 0x23, 0x13, 0x15, 0xe6, 0x31,
-	0x3d, 0x6c, 0xd7, 0xd4, 0x1d, 0x29, 0x79, 0xfa, 0x3c, 0xc2, 0x80, 0x3e,
-	0x8f, 0x90, 0x80, 0x6f, 0xf4, 0x94, 0x8e, 0xeb, 0xaf, 0x51, 0x48, 0xaf,
-	0x34, 0xea, 0xd8, 0xbe, 0xe8, 0x33, 0x09, 0x03, 0xb0, 0xb9, 0x78, 0x0e,
-	0x21, 0x90, 0x9d, 0x29, 0xf3, 0x36, 0xe7, 0x12, 0x0e, 0x07, 0xbd, 0x5e,
-	0x10, 0x0c, 0xfb, 0x67, 0xad, 0x2c, 0xc7, 0xbb, 0x62, 0xea, 0xd0, 0xd7,
-	0x7c, 0x14, 0xfa, 0x66, 0xde, 0xc7, 0x7c, 0x8a, 0xf6, 0x3a, 0x68, 0xa6,
-	0x1b, 0x7a, 0x37, 0xf9, 0xa4, 0x68, 0xdd, 0xd1, 0x05, 0x9d, 0xeb, 0xdd,
-	0xfb, 0x3e, 0xd8, 0x3a, 0x5f, 0x06, 0xad, 0x1f, 0x4b, 0xf5, 0x68, 0xff,
-	0xff, 0x1c, 0x74, 0x31, 0xe3, 0x84, 0x8f, 0x69, 0xda, 0x22, 0x8d, 0x35,
-	0xe8, 0xb3, 0x50, 0x27, 0x53, 0x4e, 0x34, 0xdb, 0x75, 0xde, 0xc4, 0xcd,
-	0x53, 0xed, 0xde, 0x73, 0xe0, 0xb5, 0x7e, 0x7f, 0x03, 0x6c, 0x66, 0xd1,
-	0x3a, 0xbf, 0x50, 0x5a, 0x6f, 0x6d, 0x83, 0x66, 0x19, 0x77, 0xb9, 0x56,
-	0x93, 0xec, 0x19, 0x32, 0x3e, 0x66, 0x3c, 0xa1, 0x18, 0x23, 0xe6, 0xfa,
-	0x05, 0xcf, 0x39, 0x70, 0x9d, 0x9b, 0xf1, 0x90, 0xf1, 0x7b, 0x47, 0xfc,
-	0xbc, 0x17, 0xb1, 0x67, 0x23, 0xb2, 0x45, 0x43, 0x9b, 0x7b, 0xb4, 0xad,
-	0x1a, 0x05, 0x3f, 0x7d, 0x0f, 0x74, 0xcf, 0xba, 0xa4, 0xfd, 0xef, 0x04,
-	0x93, 0xae, 0x89, 0x4f, 0x29, 0xd4, 0xcb, 0x6a, 0x5c, 0x3d, 0x25, 0x07,
-	0x4a, 0xe4, 0xff, 0xa8, 0x96, 0xe5, 0xbb, 0x53, 0x94, 0x07, 0x51, 0xe0,
-	0x71, 0x0a, 0xf8, 0x6b, 0x90, 0xdd, 0x5d, 0x45, 0x94, 0x89, 0xc8, 0xd0,
-	0x40, 0x03, 0x78, 0x8f, 0x76, 0x09, 0xdf, 0x2e, 0xca, 0x7b, 0x32, 0x55,
-	0x1c, 0xd7, 0x7b, 0x9e, 0x1f, 0x43, 0xdd, 0xc7, 0xf1, 0x4c, 0x14, 0xcb,
-	0xa8, 0xf3, 0xb0, 0x2e, 0x3f, 0x31, 0xca, 0x73, 0x22, 0x02, 0x7b, 0xff,
-	0x49, 0x29, 0x4c, 0xb6, 0xc1, 0x2f, 0x99, 0x1e, 0x77, 0xe7, 0xe2, 0xe4,
-	0xff, 0xa5, 0x91, 0xeb, 0xcc, 0x85, 0xeb, 0xb8, 0x27, 0x47, 0xdc, 0x81,
-	0xcd, 0xaa, 0xb3, 0x49, 0xaf, 0xf9, 0xf4, 0x48, 0x3f, 0x6c, 0x8a, 0x9b,
-	0x2b, 0xcf, 0xc4, 0xcc, 0xda, 0xc0, 0x82, 0xf5, 0x86, 0xc3, 0xc4, 0x8a,
-	0x3a, 0xea, 0xf2, 0xdc, 0xa7, 0x4c, 0x9c, 0x81, 0xf6, 0x39, 0x1a, 0xae,
-	0xe7, 0x30, 0xcd, 0x93, 0xb6, 0xeb, 0x00, 0xd7, 0x99, 0x7f, 0xd2, 0xf2,
-	0xf5, 0x89, 0x4d, 0x61, 0x5f, 0xf9, 0x60, 0x6c, 0x53, 0x5e, 0x3e, 0x81,
-	0x27, 0x77, 0x5d, 0x72, 0x34, 0xab, 0xd8, 0xef, 0x37, 0x02, 0xc6, 0x02,
-	0x54, 0xba, 0x55, 0xf2, 0x4d, 0xd5, 0xfd, 0x33, 0xad, 0xc3, 0x2b, 0xa8,
-	0xd7, 0x83, 0x63, 0x26, 0x11, 0x03, 0x0e, 0xf2, 0x6f, 0x08, 0xcf, 0x16,
-	0xcf, 0x57, 0xcb, 0xc1, 0x73, 0xc2, 0xae, 0xd7, 0x70, 0x0d, 0x66, 0x05,
-	0xf0, 0xd2, 0x80, 0xf4, 0x09, 0x19, 0x39, 0xfe, 0x3b, 0x31, 0xee, 0x17,
-	0xaa, 0xd1, 0x7e, 0xf5, 0x7d, 0xf5, 0x26, 0x06, 0xf2, 0x2c, 0xca, 0x30,
-	0x7f, 0x1c, 0x75, 0x92, 0xf9, 0x6c, 0x64, 0xad, 0x0c, 0xe9, 0x7e, 0x83,
-	0x48, 0xdb, 0xb6, 0x7a, 0xbd, 0x4f, 0x5f, 0xce, 0x30, 0x6e, 0x11, 0xd6,
-	0x7d, 0x56, 0xef, 0x83, 0x73, 0xd3, 0xc9, 0x7c, 0x5f, 0x84, 0xf2, 0xa9,
-	0x53, 0x7a, 0xb9, 0xce, 0x73, 0x66, 0x5c, 0xd3, 0x76, 0xfb, 0x26, 0x9e,
-	0x07, 0xdd, 0x02, 0xfb, 0xef, 0x3b, 0x80, 0x89, 0x30, 0x9e, 0x40, 0x3a,
-	0x7c, 0xc2, 0xd7, 0x85, 0x61, 0xfa, 0x4d, 0xc2, 0x30, 0xfd, 0x26, 0x61,
-	0x20, 0x2e, 0x00, 0x47, 0xa5, 0x7d, 0x75, 0x68, 0x53, 0x5c, 0x85, 0x71,
-	0x1c, 0x2c, 0x4d, 0xc3, 0xbf, 0xd5, 0x31, 0x94, 0xce, 0x69, 0x45, 0x9e,
-	0xf7, 0xc0, 0x73, 0xe0, 0xad, 0x12, 0x78, 0x0f, 0xb6, 0xe1, 0x97, 0x61,
-	0x1b, 0x3e, 0x01, 0xdb, 0xf0, 0x1c, 0x6c, 0xc3, 0xc7, 0x31, 0x37, 0x8f,
-	0x2d, 0xe0, 0xd5, 0x8c, 0xe6, 0xd5, 0x42, 0xe9, 0x02, 0x78, 0xb5, 0xeb,
-	0x0a, 0xfc, 0xe8, 0xc2, 0xc6, 0xa7, 0x0d, 0xed, 0xc0, 0x96, 0xff, 0xb8,
-	0xf6, 0x8b, 0x1f, 0x4c, 0x8d, 0xb1, 0x0e, 0x68, 0x38, 0x49, 0x9f, 0x16,
-	0xf2, 0x3f, 0x99, 0x07, 0xef, 0x61, 0xac, 0x8e, 0xa3, 0xae, 0x5b, 0x23,
-	0xd4, 0x1f, 0xee, 0x36, 0xee, 0xef, 0xe6, 0x58, 0x13, 0x8b, 0xf0, 0x64,
-	0xf8, 0x73, 0x8f, 0x4f, 0x3d, 0x42, 0xbe, 0x4c, 0x7c, 0x76, 0xc4, 0xaf,
-	0xe6, 0xc5, 0x1d, 0x1c, 0x5f, 0xe0, 0x6d, 0x5a, 0xae, 0xee, 0x7c, 0xf9,
-	0x35, 0x73, 0xe5, 0x75, 0xff, 0xa3, 0xe4, 0x37, 0xe8, 0x6e, 0xe2, 0x3e,
-	0x91, 0x8d, 0x6c, 0xb0, 0xb8, 0xdf, 0x2f, 0x6d, 0xdb, 0x60, 0xaf, 0x0f,
-	0x82, 0x7e, 0xa7, 0x02, 0xf1, 0xb7, 0x85, 0x6d, 0xce, 0xb7, 0xe3, 0xd9,
-	0x76, 0x76, 0xc3, 0x96, 0xed, 0xdb, 0xc4, 0xb5, 0x5e, 0xd8, 0xf2, 0xa9,
-	0x70, 0x3e, 0x60, 0xf9, 0xea, 0x39, 0xa7, 0x0c, 0xa5, 0xec, 0x6c, 0xb0,
-	0xf1, 0x7e, 0xb6, 0x77, 0x61, 0xd1, 0x3c, 0x5d, 0x0a, 0x78, 0xce, 0x76,
-	0xc4, 0x1f, 0xab, 0xa2, 0x95, 0xbf, 0xb2, 0xb4, 0xa2, 0x16, 0x8d, 0xe3,
-	0x9c, 0xa5, 0x95, 0x10, 0xde, 0x58, 0x48, 0x2b, 0x75, 0x21, 0xad, 0xe4,
-	0xc7, 0x43, 0x5a, 0x61, 0xdd, 0x73, 0x21, 0xad, 0x24, 0xaa, 0x69, 0x25,
-	0x3f, 0xee, 0xe0, 0x59, 0x0c, 0x07, 0xe9, 0x85, 0xed, 0x90, 0x5e, 0x00,
-	0x4b, 0xa5, 0x32, 0x47, 0x2f, 0x31, 0xb4, 0x73, 0xa8, 0xa4, 0x34, 0xad,
-	0x0c, 0xa9, 0x50, 0x47, 0x78, 0x98, 0x73, 0xcc, 0xfd, 0x15, 0x69, 0x24,
-	0x65, 0x69, 0x64, 0xfe, 0x2c, 0xd1, 0x22, 0xda, 0x00, 0xee, 0x79, 0x5e,
-	0x60, 0xb3, 0xa6, 0x8d, 0xfb, 0x53, 0x2f, 0xa0, 0xec, 0x28, 0x68, 0x23,
-	0xc4, 0xc1, 0x03, 0x16, 0x07, 0x8b, 0xe7, 0xf2, 0xb4, 0xc5, 0xc1, 0xa8,
-	0xc5, 0x81, 0xe6, 0x97, 0x3c, 0xe7, 0x4c, 0x69, 0x1c, 0xd4, 0x69, 0x1c,
-	0x88, 0x0a, 0xeb, 0x9e, 0x5e, 0x06, 0x07, 0x2c, 0x33, 0xaa, 0xc7, 0x1f,
-	0xc1, 0xf8, 0xf7, 0x61, 0xfc, 0x4a, 0x8f, 0x9f, 0xf3, 0xc0, 0xf1, 0x03,
-	0x96, 0xca, 0x77, 0xe6, 0xc6, 0xdf, 0x84, 0x36, 0x0e, 0x6a, 0xdb, 0x99,
-	0xf1, 0x54, 0xea, 0x46, 0x33, 0xfe, 0xc7, 0x2a, 0xe6, 0x8c, 0xc9, 0x63,
-	0x4b, 0xf4, 0xd8, 0x0b, 0x96, 0x37, 0x7c, 0xbd, 0xce, 0xc6, 0x73, 0x6d,
-	0xe7, 0xa0, 0xbb, 0xc6, 0x52, 0x09, 0x7b, 0xe6, 0xd4, 0xd8, 0x43, 0x5f,
-	0x4d, 0x91, 0x77, 0x3e, 0xaa, 0xf7, 0xfa, 0x9d, 0xa5, 0x5d, 0x54, 0x6a,
-	0x92, 0xbe, 0xb1, 0x6a, 0xb8, 0x09, 0x6f, 0x3e, 0x50, 0x3e, 0x63, 0x37,
-	0xfb, 0xa1, 0x3b, 0x4c, 0xdc, 0x1a, 0xb4, 0x84, 0xf4, 0x64, 0xbe, 0x37,
-	0x52, 0x27, 0xea, 0x81, 0x0f, 0x60, 0xcc, 0x2e, 0x7c, 0xcc, 0x76, 0x6f,
-	0x9b, 0xa2, 0xae, 0xbb, 0xba, 0x4a, 0xd7, 0x35, 0x5b, 0x5d, 0xb7, 0x86,
-	0xba, 0x0e, 0x70, 0x3f, 0x25, 0x87, 0x4b, 0x9c, 0xbf, 0x7c, 0xa2, 0x4e,
-	0xc7, 0x40, 0x1d, 0x1b, 0xe7, 0x4b, 0xc6, 0x0f, 0x6b, 0x5a, 0xa6, 0xce,
-	0x4a, 0xea, 0xb8, 0xe4, 0x4c, 0xd7, 0x3f, 0xd9, 0x75, 0x10, 0xea, 0xb5,
-	0xef, 0x07, 0x7f, 0xb0, 0x8c, 0x5e, 0x83, 0xfe, 0xd1, 0xf6, 0x59, 0x0d,
-	0x64, 0xad, 0x9c, 0x6a, 0xc6, 0xb3, 0x9a, 0xe7, 0xc1, 0x3a, 0x3b, 0x54,
-	0xbd, 0xd4, 0x9c, 0x6a, 0x94, 0x3d, 0x63, 0x7a, 0xdd, 0x5c, 0xd4, 0x29,
-	0xe0, 0xff, 0x14, 0xcf, 0x14, 0x88, 0x3e, 0x03, 0x95, 0x1b, 0x85, 0x3f,
-	0x33, 0xf1, 0x94, 0xd9, 0x1b, 0x38, 0x56, 0xa3, 0x7f, 0xd3, 0xc6, 0x28,
-	0xa4, 0x32, 0xfa, 0xec, 0xd0, 0x1e, 0xb4, 0xd9, 0xbe, 0xa9, 0x16, 0x63,
-	0x8e, 0xa1, 0x2e, 0xf7, 0x16, 0xaa, 0x36, 0x57, 0x6a, 0xc5, 0x9d, 0x88,
-	0xea, 0xf3, 0x4b, 0x3c, 0x7f, 0x9f, 0xed, 0x69, 0x42, 0x5e, 0x44, 0xaf,
-	0x15, 0xd4, 0x9c, 0x9a, 0x3f, 0xa7, 0xae, 0x8e, 0x8a, 0x5d, 0xc3, 0x4f,
-	0x6b, 0xbd, 0x12, 0x39, 0x4a, 0x9d, 0xc3, 0xfd, 0x55, 0x3d, 0x98, 0xf7,
-	0xe5, 0xf4, 0x8d, 0x31, 0x62, 0xb3, 0x98, 0x3f, 0x75, 0x86, 0x67, 0x8d,
-	0x5b, 0xf1, 0x0e, 0xdb, 0x0b, 0xf5, 0x08, 0x74, 0xdf, 0xdb, 0x3f, 0xe1,
-	0x49, 0x3d, 0xf0, 0x3d, 0xa1, 0x80, 0x6b, 0x57, 0xd3, 0x42, 0x5e, 0x85,
-	0xb1, 0x69, 0x43, 0x0f, 0x8f, 0xbf, 0x21, 0x3f, 0x90, 0x26, 0x3a, 0x6d,
-	0x6c, 0xc1, 0xb7, 0x31, 0x7e, 0xd2, 0xb6, 0xa1, 0x87, 0x47, 0x53, 0x19,
-	0xc5, 0xbd, 0x51, 0x66, 0x1d, 0x94, 0xb4, 0x41, 0x9a, 0x4f, 0xe8, 0xf5,
-	0xd1, 0x8c, 0xbc, 0x2c, 0x99, 0xa6, 0x76, 0xd8, 0x5d, 0xff, 0xb6, 0x73,
-	0x6c, 0xee, 0x2e, 0xd0, 0x34, 0x07, 0xdd, 0xc4, 0x7d, 0xca, 0x9d, 0xf2,
-	0x5e, 0x9e, 0x57, 0x98, 0x70, 0xa0, 0x94, 0x9f, 0xd2, 0x7b, 0xbf, 0x77,
-	0x14, 0x57, 0xcb, 0xad, 0xa9, 0xa8, 0x5d, 0xe7, 0xac, 0x05, 0x1d, 0x40,
-	0x50, 0x9f, 0xaa, 0xc5, 0x13, 0x75, 0x38, 0x7f, 0x17, 0x53, 0x99, 0xa4,
-	0x22, 0xb3, 0xc3, 0xe7, 0x9f, 0x91, 0x2d, 0xde, 0x1e, 0x7d, 0xce, 0x4e,
-	0x9c, 0xba, 0x53, 0x7f, 0xe9, 0xd1, 0x06, 0x25, 0xfd, 0xcc, 0xf8, 0xb5,
-	0x7a, 0x5d, 0xab, 0x3f, 0x15, 0x04, 0x39, 0xcc, 0x5f, 0x41, 0x4c, 0xfc,
-	0x6c, 0xc2, 0x67, 0x1a, 0xfd, 0xda, 0x06, 0xa7, 0xf6, 0x4c, 0xa3, 0x63,
-	0x68, 0x45, 0x22, 0x2a, 0x5d, 0xef, 0xd4, 0x9c, 0xba, 0x93, 0x73, 0x06,
-	0xba, 0xf2, 0x1c, 0x43, 0x57, 0x31, 0x67, 0x9e, 0xae, 0xd6, 0xd9, 0xdf,
-	0x2a, 0x5d, 0x27, 0x99, 0x64, 0x1d, 0xc6, 0xdb, 0x5b, 0x0c, 0x61, 0x3c,
-	0x0c, 0xb8, 0x08, 0xcf, 0xdd, 0x18, 0xc3, 0x30, 0x9e, 0x3c, 0x60, 0x01,
-	0xb3, 0x9f, 0x2a, 0x00, 0xe6, 0x83, 0x78, 0x18, 0x27, 0x6b, 0x76, 0x22,
-	0x13, 0xd5, 0xf0, 0x12, 0xc6, 0x1f, 0x5b, 0x78, 0x5f, 0x0f, 0x56, 0x4f,
-	0x66, 0xba, 0x8b, 0x80, 0x87, 0x70, 0xde, 0x07, 0x18, 0x69, 0x97, 0x8e,
-	0xe2, 0xdb, 0x03, 0x7c, 0x63, 0x16, 0x26, 0xd0, 0xe3, 0xd8, 0x43, 0xf3,
-	0xbf, 0x8b, 0xb4, 0x93, 0x8f, 0xd9, 0xef, 0xd6, 0x45, 0x32, 0xe0, 0x15,
-	0x87, 0x78, 0x1e, 0x29, 0xbd, 0xe6, 0xc0, 0x0e, 0x00, 0xdf, 0xbf, 0xe4,
-	0x44, 0xce, 0xc4, 0xe5, 0x50, 0x91, 0x31, 0x84, 0xe3, 0x0e, 0xe7, 0x41,
-	0xf9, 0x57, 0xa1, 0x4c, 0x5c, 0xc9, 0xc4, 0xd5, 0x78, 0xde, 0x82, 0x67,
-	0x03, 0x9e, 0x8d, 0x78, 0xd6, 0xe3, 0x69, 0xc5, 0xf3, 0x2d, 0x94, 0x53,
-	0xb1, 0x3a, 0xe1, 0x7e, 0xd5, 0x16, 0xa5, 0x34, 0x1f, 0x71, 0xcf, 0xc2,
-	0x65, 0xc0, 0xe5, 0x2b, 0xd0, 0x3b, 0x1e, 0x9e, 0xf1, 0xf8, 0x3a, 0xfa,
-	0x98, 0xc5, 0xd3, 0xa9, 0xe4, 0x4c, 0x17, 0x9e, 0x14, 0x9e, 0x6e, 0x3c,
-	0x3d, 0x78, 0xd2, 0x78, 0x5e, 0x75, 0x0c, 0xcf, 0x5d, 0x02, 0xbe, 0x42,
-	0x1e, 0x01, 0xce, 0x17, 0xf0, 0x9c, 0xe7, 0xbc, 0x09, 0x9e, 0x73, 0x2c,
-	0xcf, 0x39, 0xf3, 0x3c, 0x57, 0xeb, 0xa8, 0x63, 0xf5, 0x4e, 0xe4, 0x18,
-	0x7d, 0x85, 0x5a, 0xc7, 0xf0, 0x7f, 0x44, 0x7a, 0x07, 0x41, 0x4b, 0xc7,
-	0x30, 0x67, 0xc7, 0x48, 0x57, 0x2e, 0xd2, 0xc7, 0x16, 0xf5, 0x3b, 0xfa,
-	0x26, 0xfa, 0x3d, 0x61, 0xfb, 0x7d, 0xb8, 0xaa, 0xdf, 0x83, 0x68, 0xfb,
-	0x3e, 0xdb, 0xef, 0xc1, 0xaa, 0x7e, 0x41, 0x2b, 0xc7, 0xf2, 0x78, 0x48,
-	0x17, 0x23, 0x48, 0x0f, 0x65, 0xc2, 0xdd, 0x6b, 0xa4, 0xbe, 0x46, 0x9f,
-	0x27, 0x8d, 0xf9, 0x35, 0x73, 0xba, 0x31, 0x53, 0xa5, 0x1f, 0x7e, 0x16,
-	0xfd, 0x38, 0x5c, 0xa2, 0x8d, 0x38, 0x5d, 0x25, 0x17, 0xe8, 0xfb, 0x04,
-	0x72, 0x5c, 0xfb, 0x39, 0xf4, 0x79, 0xe8, 0xff, 0x2c, 0xb6, 0xad, 0x3e,
-	0xae, 0xf7, 0xe7, 0xde, 0x55, 0x6c, 0x95, 0x4f, 0x14, 0x69, 0x13, 0x92,
-	0x5e, 0x82, 0x60, 0xcf, 0x36, 0xda, 0xa7, 0xf9, 0x60, 0x9d, 0x9f, 0xd4,
-	0xb1, 0xb5, 0x4f, 0x2e, 0xd5, 0x19, 0xa3, 0xbd, 0xf0, 0xcd, 0xb3, 0x47,
-	0x3f, 0x08, 0x9d, 0x51, 0x03, 0xb8, 0x9f, 0xd2, 0x77, 0x80, 0xec, 0x1a,
-	0x55, 0x23, 0x6b, 0x25, 0x2e, 0x37, 0x17, 0x6b, 0x61, 0xf7, 0x30, 0x56,
-	0x5e, 0x2f, 0xed, 0xdb, 0xa2, 0xe6, 0x6c, 0x8d, 0x17, 0xc3, 0x6f, 0xcf,
-	0x9c, 0xf5, 0x89, 0xc5, 0x91, 0x1f, 0x69, 0xa2, 0x1c, 0x8c, 0xf9, 0xef,
-	0xd4, 0xfb, 0x26, 0xdb, 0xb6, 0xd1, 0x6e, 0xb9, 0x41, 0xeb, 0x70, 0x77,
-	0x89, 0x9d, 0xa4, 0x5a, 0x3c, 0x99, 0xb7, 0xd1, 0x76, 0x17, 0x93, 0x09,
-	0xc2, 0xf5, 0x90, 0x70, 0x3f, 0xc1, 0x7e, 0x29, 0xa4, 0x1a, 0x25, 0x92,
-	0xe6, 0xba, 0x5c, 0xb2, 0x93, 0xb6, 0xd1, 0xc4, 0x98, 0x67, 0xcf, 0x9e,
-	0xac, 0x96, 0x0b, 0xba, 0x9f, 0x5a, 0x0d, 0xa3, 0x39, 0x8f, 0xc6, 0x35,
-	0x2f, 0x9e, 0x81, 0x72, 0xf1, 0x6e, 0xd0, 0x7a, 0x67, 0xa2, 0xcc, 0xb3,
-	0x4e, 0xf0, 0x97, 0xca, 0x31, 0x7d, 0xc6, 0xd4, 0x7b, 0x3b, 0xfc, 0xd8,
-	0xf2, 0x06, 0xd9, 0x3d, 0xb6, 0x82, 0xeb, 0x28, 0xb1, 0xb5, 0xd0, 0x1f,
-	0xac, 0xd3, 0xb6, 0x0d, 0xfe, 0xdf, 0xf8, 0x46, 0x79, 0x7c, 0x9c, 0x6d,
-	0xb7, 0xc8, 0xe4, 0x94, 0x38, 0xde, 0xdb, 0x57, 0xa2, 0x8c, 0xc7, 0xf1,
-	0x08, 0xf7, 0x3c, 0xb5, 0x6d, 0x13, 0xe5, 0xbd, 0xdd, 0x95, 0xf3, 0xdd,
-	0x11, 0xbd, 0x26, 0xe3, 0x82, 0x4e, 0xd8, 0xde, 0xf9, 0xee, 0x56, 0x39,
-	0x3b, 0x05, 0x9a, 0x80, 0xdc, 0xef, 0x3b, 0x45, 0x98, 0x44, 0xb6, 0x4f,
-	0xc0, 0x5e, 0x90, 0x76, 0x3c, 0xa0, 0x0f, 0xc8, 0xef, 0x5b, 0xbb, 0xd9,
-	0x17, 0xf4, 0x12, 0x74, 0x5c, 0xdb, 0x36, 0x23, 0x0b, 0x32, 0x13, 0x35,
-	0x48, 0x67, 0xbb, 0xf0, 0x0f, 0x07, 0xd9, 0x4e, 0x58, 0x57, 0x61, 0x4c,
-	0xb5, 0x9a, 0x5e, 0x66, 0x17, 0xe9, 0x8f, 0x73, 0x3f, 0x97, 0xfd, 0xcd,
-	0x36, 0x3a, 0x41, 0x2b, 0xbe, 0xde, 0xc3, 0x63, 0x6c, 0x2b, 0xce, 0x09,
-	0x6d, 0x22, 0xda, 0x55, 0xd7, 0x6a, 0xfb, 0x62, 0xb2, 0xc2, 0x19, 0xe4,
-	0xda, 0x48, 0x38, 0x47, 0x71, 0x39, 0x59, 0x9a, 0x9b, 0xa7, 0x0d, 0x35,
-	0x0b, 0xe7, 0x89, 0xb4, 0x92, 0x1a, 0xb2, 0xb6, 0xc7, 0x8c, 0x3c, 0x0f,
-	0xbb, 0xac, 0x53, 0xcf, 0xd9, 0x0c, 0x6c, 0x59, 0x3b, 0x67, 0xda, 0x9e,
-	0x2d, 0x84, 0x73, 0x36, 0x00, 0x8d, 0x53, 0xbe, 0x41, 0xcf, 0x99, 0x07,
-	0xba, 0xc9, 0x03, 0xef, 0x79, 0xcc, 0x53, 0x1e, 0x73, 0x94, 0x2f, 0xb7,
-	0xc8, 0xc4, 0x71, 0xd5, 0x5a, 0x23, 0x92, 0xd8, 0xed, 0xb7, 0xc8, 0xf0,
-	0x14, 0x63, 0x05, 0x1b, 0x60, 0x83, 0x6d, 0xc4, 0xd3, 0x8a, 0x6f, 0xd6,
-	0xe3, 0x1d, 0x1f, 0x0a, 0x75, 0xeb, 0x96, 0xd8, 0x59, 0x67, 0xd1, 0xf7,
-	0xd3, 0xc0, 0xc3, 0xa3, 0xc0, 0xc3, 0x3c, 0xef, 0xbc, 0x50, 0x15, 0x5f,
-	0xe2, 0x58, 0xb5, 0x0e, 0xc5, 0x78, 0x63, 0x7a, 0x3e, 0x75, 0x9c, 0xa9,
-	0x54, 0xfb, 0x66, 0xec, 0xa9, 0x38, 0xed, 0xa9, 0xdc, 0xa8, 0x67, 0xce,
-	0x60, 0x0d, 0xc0, 0x77, 0xf2, 0xf7, 0x69, 0x5a, 0x1f, 0x1a, 0x27, 0x5c,
-	0xd1, 0x10, 0xae, 0x05, 0x73, 0xc6, 0x33, 0xb3, 0x4b, 0xe3, 0x18, 0x2f,
-	0xcc, 0xed, 0x11, 0x87, 0x2e, 0x97, 0xd1, 0x14, 0xe3, 0x24, 0xad, 0xcb,
-	0xc0, 0xf4, 0x94, 0xb6, 0x61, 0x45, 0x9d, 0x96, 0x03, 0x25, 0x9e, 0xb7,
-	0xe5, 0x1a, 0xcc, 0xef, 0x31, 0x7e, 0xd4, 0x39, 0x21, 0xc7, 0xd0, 0x37,
-	0xd7, 0xc5, 0x95, 0x8d, 0xcf, 0xac, 0xb2, 0x7b, 0xf2, 0xaa, 0x63, 0x34,
-	0x66, 0xdd, 0x7c, 0xe1, 0xd9, 0x93, 0xe4, 0xc0, 0xac, 0x5e, 0x77, 0xe5,
-	0x9a, 0xa1, 0x8c, 0x46, 0xa0, 0xfd, 0x76, 0x77, 0x27, 0x7b, 0xcc, 0x59,
-	0xc3, 0x84, 0xf4, 0x97, 0xcc, 0xf8, 0x2f, 0xea, 0x7d, 0x93, 0x66, 0x7f,
-	0xb8, 0xd9, 0x53, 0xb9, 0x5f, 0x2e, 0xa6, 0xa2, 0x55, 0x73, 0x5b, 0x27,
-	0xc3, 0xc0, 0x85, 0x5e, 0xcb, 0x84, 0x5d, 0x9c, 0xeb, 0x7e, 0xbc, 0x89,
-	0x67, 0xd1, 0xa2, 0x98, 0x9f, 0xc2, 0x38, 0xcf, 0xa7, 0xb3, 0xdd, 0x2b,
-	0xb5, 0x45, 0x31, 0xcb, 0xb3, 0x4e, 0x90, 0x95, 0x6f, 0xdd, 0x12, 0xaf,
-	0xd7, 0xf9, 0x2b, 0xec, 0x99, 0x16, 0xd8, 0x0d, 0xbb, 0x02, 0xf9, 0x33,
-	0xe8, 0xc9, 0xd3, 0x76, 0x4c, 0x09, 0x1d, 0x93, 0x92, 0xe0, 0x7c, 0x2a,
-	0x6e, 0xe3, 0xce, 0x1c, 0xcb, 0x98, 0xa5, 0x6f, 0x63, 0xff, 0xcc, 0xdb,
-	0xd0, 0x5d, 0x9a, 0xd6, 0x1f, 0xd7, 0xb2, 0xb0, 0xcb, 0xda, 0xce, 0x3a,
-	0x8e, 0x73, 0x42, 0xf4, 0x1e, 0xac, 0xd0, 0x37, 0xea, 0xa8, 0xf2, 0x0b,
-	0x8c, 0x2f, 0x57, 0x18, 0x5b, 0x4e, 0x46, 0xcd, 0xfb, 0x84, 0xf4, 0xe5,
-	0xf6, 0x6c, 0xe2, 0xdd, 0x30, 0xa1, 0x2f, 0xd7, 0x65, 0x7d, 0xb9, 0x46,
-	0xed, 0xcb, 0x99, 0xd8, 0x43, 0xe3, 0x9c, 0x2f, 0x57, 0x18, 0xcb, 0x83,
-	0x56, 0x6a, 0xed, 0x59, 0x09, 0x63, 0x0b, 0x0d, 0x17, 0x5d, 0xbd, 0x6f,
-	0x24, 0x37, 0xa0, 0xe0, 0x37, 0x18, 0x1f, 0x8b, 0xb1, 0x0a, 0xa5, 0xfe,
-	0xce, 0xfa, 0x17, 0x1b, 0x24, 0xd3, 0xbc, 0x02, 0xe3, 0x7e, 0x4a, 0xcf,
-	0xb9, 0x59, 0xc3, 0x82, 0x5c, 0x1b, 0x64, 0xcc, 0x87, 0x67, 0x47, 0x35,
-	0x7f, 0x25, 0x7a, 0x23, 0x9d, 0xc6, 0x9e, 0xf5, 0x13, 0x6b, 0xa5, 0xfe,
-	0xb8, 0x53, 0x18, 0x8f, 0xda, 0x7e, 0x13, 0x80, 0xa9, 0x06, 0x73, 0xf3,
-	0x4e, 0x2b, 0x93, 0xd9, 0xf7, 0x3b, 0xea, 0x18, 0x1b, 0x98, 0x2a, 0x9a,
-	0x18, 0x60, 0x5f, 0x31, 0x12, 0x9e, 0x5b, 0x57, 0x5c, 0x47, 0xce, 0x0c,
-	0xae, 0x00, 0x2c, 0x2b, 0x96, 0xb5, 0x59, 0x1f, 0x7b, 0x43, 0x1d, 0x45,
-	0x9a, 0x7a, 0x4a, 0xef, 0x2f, 0x5c, 0xd9, 0x9d, 0xdc, 0xa9, 0xcf, 0x23,
-	0xe9, 0x58, 0x62, 0x5e, 0xb8, 0x7f, 0xf7, 0x9b, 0xf2, 0x36, 0x2d, 0xfb,
-	0x0f, 0xa4, 0xa8, 0xc7, 0xb6, 0xe9, 0xdf, 0xb5, 0xe9, 0x20, 0x38, 0xdf,
-	0xfd, 0x2c, 0x6c, 0x16, 0xdf, 0xfb, 0x96, 0xb4, 0xc7, 0x7b, 0xb5, 0x0d,
-	0x85, 0xb9, 0x1a, 0xac, 0x97, 0x15, 0xfe, 0xb8, 0xdd, 0xab, 0x68, 0xd6,
-	0x03, 0x0b, 0xc2, 0xfb, 0x17, 0x3a, 0x6c, 0x5e, 0x3e, 0xa8, 0x07, 0x3d,
-	0x7d, 0x44, 0x8c, 0xac, 0xc9, 0xcd, 0xcb, 0x1a, 0xee, 0xa7, 0xcb, 0x90,
-	0xa0, 0xdd, 0x23, 0x92, 0xe4, 0xdd, 0x49, 0xec, 0xbb, 0x20, 0x57, 0x41,
-	0x3f, 0xb3, 0x1e, 0x6d, 0x56, 0x7e, 0x73, 0x0f, 0x8a, 0xef, 0x1d, 0x84,
-	0x8e, 0xb9, 0x61, 0xa9, 0x8e, 0x89, 0xd3, 0xbf, 0xcf, 0x8d, 0xd2, 0x47,
-	0x5c, 0x89, 0x3a, 0x2d, 0xf2, 0xd1, 0xb1, 0xdf, 0x5a, 0x4b, 0x1e, 0x1b,
-	0x82, 0x7c, 0x57, 0xf7, 0x87, 0xe7, 0x2e, 0x99, 0xc6, 0x7c, 0xb6, 0x5b,
-	0x27, 0x89, 0xf7, 0x79, 0xf2, 0xc5, 0x4a, 0x32, 0x31, 0x0b, 0x1d, 0x35,
-	0xe4, 0x0c, 0xb7, 0x9a, 0xd8, 0xe9, 0xa7, 0xd6, 0x9a, 0x73, 0x5a, 0xf5,
-	0xc0, 0x69, 0x18, 0x4f, 0xad, 0xa6, 0xdd, 0x59, 0x2b, 0x97, 0x83, 0xa0,
-	0xbe, 0x5b, 0xcb, 0xe2, 0x9d, 0x94, 0xc5, 0x07, 0x52, 0x1d, 0x86, 0x07,
-	0xb4, 0xef, 0xc4, 0x3d, 0x00, 0xc0, 0x43, 0xb7, 0xcb, 0xbd, 0xd0, 0x96,
-	0x4f, 0xfd, 0xcc, 0x8c, 0x95, 0x4f, 0xca, 0x59, 0xca, 0x9f, 0x6a, 0x6b,
-	0x74, 0x81, 0xec, 0x3d, 0x34, 0x46, 0xbd, 0x9c, 0x9a, 0xfe, 0x26, 0xe4,
-	0x55, 0x4e, 0xe3, 0xa1, 0x45, 0xee, 0x1b, 0x93, 0xcc, 0x45, 0xe8, 0xac,
-	0xc2, 0xd4, 0x42, 0x1e, 0x5d, 0xda, 0x1e, 0xc7, 0x7a, 0x7a, 0xad, 0xf1,
-	0x71, 0x17, 0x8e, 0x75, 0x9a, 0x7b, 0x8c, 0xf4, 0x58, 0xb9, 0x37, 0xff,
-	0x9c, 0x1d, 0xeb, 0xca, 0x70, 0xac, 0x3d, 0x0b, 0xc7, 0x1a, 0xfa, 0xf8,
-	0xa1, 0xfc, 0x4d, 0xe8, 0xb3, 0x49, 0xfa, 0x4c, 0xcc, 0xd8, 0x4a, 0xe9,
-	0x1d, 0x6d, 0xb4, 0x72, 0xd3, 0x83, 0x0e, 0xe2, 0x79, 0xa1, 0xe9, 0xcf,
-	0x79, 0x62, 0x71, 0xa6, 0x88, 0x07, 0xca, 0xdc, 0x26, 0x7d, 0x9e, 0x71,
-	0x02, 0x7e, 0xd6, 0x87, 0x8b, 0x2c, 0x1b, 0xe6, 0x5f, 0x29, 0x46, 0x1c,
-	0xfa, 0xd6, 0xf4, 0x9f, 0x3a, 0x97, 0xc4, 0x16, 0x4c, 0x1c, 0x98, 0xf1,
-	0x5f, 0x73, 0xcf, 0x02, 0xf7, 0x7d, 0xdf, 0x01, 0xde, 0xfa, 0xed, 0x62,
-	0xb2, 0x27, 0x1b, 0xa1, 0x3c, 0x9d, 0x95, 0x43, 0x95, 0x3e, 0x69, 0xd3,
-	0x67, 0xed, 0xdf, 0x30, 0x46, 0x9c, 0xa9, 0x8e, 0x11, 0x8b, 0x63, 0x62,
-	0xc4, 0x3b, 0x7f, 0x8e, 0x18, 0xb1, 0x38, 0x26, 0x46, 0xbc, 0x9c, 0x9f,
-	0x35, 0x52, 0x9a, 0xc5, 0xb8, 0xea, 0x21, 0x53, 0x94, 0x93, 0x9b, 0x6a,
-	0xc0, 0xbb, 0x16, 0x6f, 0xc0, 0x32, 0x56, 0xc0, 0xdb, 0xc3, 0xfb, 0x20,
-	0xde, 0x31, 0x19, 0x99, 0xd3, 0x1d, 0xb3, 0x90, 0x1f, 0xd4, 0x69, 0xac,
-	0x6b, 0xfc, 0x82, 0xc9, 0x72, 0x33, 0xca, 0x5d, 0x72, 0x26, 0x58, 0xaf,
-	0xd4, 0x28, 0xc3, 0x63, 0x94, 0xdd, 0x4d, 0x32, 0x3a, 0x16, 0xda, 0xb8,
-	0x9f, 0x5d, 0xcf, 0xb5, 0x81, 0x21, 0x09, 0x6d, 0xd8, 0x67, 0xd6, 0x9b,
-	0xb5, 0xdb, 0x2d, 0x31, 0xa9, 0x5f, 0x8d, 0x39, 0x38, 0xee, 0x5c, 0x1c,
-	0x5f, 0xbd, 0xc0, 0x96, 0x4d, 0xd8, 0xd8, 0xe0, 0xb8, 0xd5, 0xc1, 0xcb,
-	0xcb, 0x88, 0xea, 0xf9, 0x8f, 0xdb, 0x73, 0xbc, 0x51, 0x7b, 0xd7, 0x5f,
-	0x42, 0xcf, 0xcf, 0x40, 0x65, 0x16, 0xfd, 0xad, 0x57, 0x99, 0x71, 0x8e,
-	0x73, 0xee, 0x7e, 0x1e, 0xc8, 0xc5, 0x56, 0x35, 0x34, 0xbe, 0x80, 0x2e,
-	0x41, 0xb7, 0x1c, 0x9b, 0x03, 0xda, 0xbd, 0x57, 0x26, 0x46, 0x09, 0x5f,
-	0x47, 0x3c, 0xa2, 0xcf, 0xf5, 0xe2, 0x7b, 0xdc, 0x9c, 0x27, 0xea, 0xad,
-	0x84, 0x67, 0x7a, 0xd7, 0x00, 0xde, 0xc5, 0xe7, 0x7a, 0xad, 0x9e, 0xd6,
-	0x36, 0x04, 0xcf, 0xf7, 0x86, 0x63, 0x58, 0x8e, 0x9e, 0x02, 0x19, 0xd6,
-	0xfb, 0x7d, 0xd7, 0xca, 0xe9, 0x07, 0xe7, 0xce, 0x17, 0x34, 0xc1, 0x56,
-	0x69, 0x85, 0xa9, 0x3c, 0xe0, 0xa6, 0xb9, 0xef, 0x82, 0xfb, 0x0b, 0x3a,
-	0xe2, 0xb7, 0xe9, 0x73, 0x1f, 0xf3, 0x67, 0xac, 0xe7, 0xcf, 0x7e, 0x84,
-	0x67, 0x5a, 0xe3, 0xd2, 0x07, 0x3a, 0xec, 0xd7, 0xe9, 0x31, 0x8c, 0x87,
-	0x6b, 0xbe, 0x1a, 0x0f, 0x90, 0x3d, 0x5c, 0xfb, 0xc5, 0xd8, 0x2b, 0x2d,
-	0x2a, 0xa7, 0xcf, 0x58, 0x47, 0x2d, 0x8d, 0x5d, 0x76, 0xf6, 0x94, 0x13,
-	0x6a, 0x4f, 0xd9, 0x57, 0x7b, 0xcb, 0x36, 0xaf, 0xfb, 0x01, 0xcc, 0x07,
-	0x7e, 0x8f, 0x17, 0x9d, 0x21, 0xe0, 0xab, 0x50, 0x3a, 0xe2, 0x64, 0xf4,
-	0xfb, 0xa8, 0x7d, 0x43, 0x0e, 0x60, 0xae, 0x7a, 0xc7, 0xa3, 0x5a, 0xde,
-	0xcf, 0xdf, 0xd3, 0x17, 0xce, 0xeb, 0x0b, 0x7a, 0x0d, 0x68, 0x5a, 0x88,
-	0x6b, 0xcf, 0xda, 0x10, 0xc7, 0x9d, 0x9c, 0xc6, 0x3d, 0xcb, 0x7c, 0x4b,
-	0xff, 0x06, 0x9d, 0x2b, 0xd3, 0x5e, 0x2b, 0xde, 0x8b, 0xf7, 0x4d, 0x86,
-	0xfa, 0x86, 0x70, 0xdf, 0x09, 0xbd, 0x16, 0xec, 0x37, 0xf2, 0x6a, 0x56,
-	0x46, 0x2a, 0x5c, 0xc3, 0x64, 0x3b, 0x48, 0x2f, 0xd7, 0xc0, 0x1e, 0x58,
-	0x78, 0xbe, 0xba, 0x7f, 0x7e, 0x1e, 0x12, 0xe3, 0x42, 0x58, 0xee, 0xd6,
-	0x67, 0x17, 0xab, 0xef, 0x1e, 0xb9, 0xf2, 0xbf, 0x70, 0xfd, 0xd0, 0xc8,
-	0x50, 0x0b, 0x47, 0x86, 0xf2, 0xce, 0xc8, 0x95, 0xaf, 0xcb, 0x41, 0xe0,
-	0xf1, 0x30, 0x60, 0x52, 0xf7, 0xf3, 0xce, 0xab, 0x57, 0xa5, 0x30, 0x59,
-	0x2f, 0xea, 0xa1, 0x82, 0xe3, 0x3e, 0x54, 0x2b, 0x91, 0x87, 0x94, 0x53,
-	0xf3, 0x50, 0xbb, 0xf6, 0xcf, 0x77, 0xa4, 0xda, 0xe3, 0x7b, 0xe5, 0xb8,
-	0xe3, 0xde, 0xaf, 0xf4, 0x59, 0xdb, 0x82, 0xc7, 0x58, 0xdf, 0x71, 0x27,
-	0x72, 0x7f, 0xd4, 0x9e, 0xd3, 0x37, 0xf1, 0xbd, 0x59, 0xcd, 0xf7, 0xdf,
-	0x58, 0x47, 0x9c, 0xcd, 0x0a, 0xf1, 0xf1, 0x59, 0xc8, 0xad, 0x4f, 0x4b,
-	0x76, 0x34, 0x31, 0x57, 0xc6, 0xec, 0xb3, 0xdf, 0xb0, 0xce, 0xf0, 0x0b,
-	0xcb, 0xbc, 0xe2, 0xf0, 0xce, 0x1c, 0xa3, 0x33, 0x3e, 0xdf, 0x12, 0xee,
-	0xb9, 0x37, 0x73, 0xca, 0xfc, 0xc6, 0x75, 0x52, 0xff, 0x0a, 0xe6, 0x8b,
-	0xfd, 0x11, 0x57, 0xab, 0xf4, 0x3d, 0x05, 0x9e, 0x6c, 0x89, 0xd7, 0xcd,
-	0xd9, 0x43, 0x46, 0xf6, 0xd6, 0x01, 0x6e, 0xc0, 0x6f, 0xec, 0x3b, 0x21,
-	0x9d, 0x0a, 0x24, 0x37, 0x69, 0xb6, 0xa3, 0x67, 0x87, 0x98, 0x39, 0x33,
-	0x34, 0xb3, 0xc2, 0xd8, 0x91, 0xf8, 0x36, 0x74, 0xa1, 0x64, 0xfb, 0xd8,
-	0x4b, 0x4e, 0x3f, 0xcf, 0x3c, 0x8a, 0xb6, 0x1b, 0x97, 0xb3, 0x09, 0xc1,
-	0x4b, 0xcf, 0x5b, 0xff, 0x32, 0x08, 0xc6, 0x52, 0x29, 0xde, 0x2b, 0xb8,
-	0x8c, 0x4f, 0xb9, 0xca, 0x99, 0x1c, 0x6d, 0x70, 0x26, 0x46, 0x03, 0xd9,
-	0x93, 0xe2, 0x9d, 0x49, 0xdc, 0x93, 0xa0, 0xe3, 0xe3, 0x48, 0x6b, 0x87,
-	0x6e, 0x7d, 0xc7, 0x3a, 0xee, 0x71, 0xbb, 0xd9, 0x6f, 0xb4, 0xe5, 0x88,
-	0x63, 0xfa, 0xca, 0xed, 0x27, 0x72, 0xc2, 0xbb, 0x8b, 0xb6, 0xc4, 0x63,
-	0x7a, 0x7f, 0xe2, 0x17, 0x50, 0x0f, 0x7d, 0x94, 0xd8, 0xaf, 0xeb, 0x4c,
-	0x40, 0x9e, 0x4d, 0x8e, 0xf1, 0xbe, 0x14, 0x9e, 0x63, 0x88, 0xb4, 0x2a,
-	0xb9, 0xd6, 0x1b, 0xb6, 0xf7, 0x69, 0xe6, 0xe1, 0x0a, 0x45, 0x74, 0xda,
-	0x16, 0x6f, 0xf7, 0xdc, 0x1d, 0x9b, 0x61, 0x5a, 0x78, 0xd7, 0xa6, 0xd2,
-	0x67, 0x56, 0xe0, 0xd3, 0x9e, 0x1e, 0x92, 0xb8, 0x33, 0x55, 0x6c, 0x75,
-	0x4e, 0x16, 0x33, 0x5b, 0xd7, 0x81, 0x3e, 0xce, 0xa7, 0x3e, 0x46, 0xf9,
-	0x05, 0xdb, 0xef, 0x45, 0xc9, 0x57, 0x3e, 0x24, 0xe3, 0x2d, 0xed, 0xde,
-	0xfd, 0x7a, 0x6e, 0x2e, 0x03, 0x67, 0x2d, 0x2a, 0x3b, 0xfa, 0xc4, 0x3a,
-	0xea, 0xb7, 0xdd, 0x45, 0x05, 0x5e, 0x56, 0xbf, 0x88, 0x07, 0x36, 0x6e,
-	0xad, 0xb6, 0x51, 0xf6, 0xa6, 0x58, 0xae, 0xc1, 0xe9, 0x1d, 0x5d, 0x85,
-	0x79, 0xdc, 0x05, 0xfd, 0xe9, 0xc0, 0x46, 0x22, 0xae, 0x1b, 0x9c, 0x3d,
-	0xa3, 0x79, 0xf4, 0xc8, 0x7d, 0xd6, 0xbc, 0xf7, 0xf0, 0x30, 0xc6, 0xa8,
-	0xe5, 0x2b, 0x78, 0xf7, 0x12, 0xd7, 0xdb, 0x83, 0x49, 0xd8, 0x06, 0xb9,
-	0xae, 0x7f, 0x67, 0xd7, 0xab, 0xa7, 0xaf, 0xb0, 0x5e, 0xed, 0xc9, 0x23,
-	0x15, 0x7d, 0x6f, 0x48, 0xe7, 0xb8, 0xe2, 0x3a, 0x6e, 0xf3, 0x55, 0x7a,
-	0x7e, 0x54, 0x87, 0xdd, 0x1b, 0x78, 0x72, 0x9d, 0xbd, 0xd3, 0x06, 0x70,
-	0x5c, 0x05, 0x18, 0x36, 0x62, 0xfc, 0x84, 0xc1, 0xd4, 0x11, 0x75, 0x4b,
-	0x9c, 0x3a, 0x70, 0x56, 0x4e, 0xaf, 0x0b, 0xf7, 0x7b, 0xa0, 0x1d, 0xc8,
-	0xb5, 0x47, 0xe3, 0x46, 0x37, 0xae, 0x5d, 0xa6, 0x9d, 0x70, 0x3c, 0x8e,
-	0x1d, 0x0f, 0x69, 0x75, 0x43, 0x0b, 0xfd, 0x89, 0x59, 0xa9, 0x5b, 0x54,
-	0x9e, 0xf1, 0xfc, 0x5d, 0xad, 0x66, 0xdf, 0x11, 0xcb, 0x7a, 0xb0, 0x4b,
-	0x69, 0xe3, 0x12, 0x77, 0x7a, 0xae, 0x8a, 0xdc, 0x5b, 0x9c, 0xf3, 0x2f,
-	0x43, 0x9e, 0x5c, 0xeb, 0xbd, 0x4d, 0x91, 0xf6, 0x42, 0xfc, 0x12, 0xb7,
-	0x09, 0xe0, 0x95, 0x71, 0x95, 0xd3, 0x41, 0x66, 0x80, 0x7c, 0xc5, 0x36,
-	0x98, 0xff, 0xa2, 0x8e, 0xe5, 0x0e, 0xa6, 0x18, 0x27, 0x6a, 0x3f, 0x71,
-	0x87, 0x0a, 0x65, 0xd3, 0x2c, 0xd7, 0x10, 0x1c, 0xde, 0x21, 0xba, 0x0b,
-	0x1d, 0x5e, 0x9c, 0x52, 0xce, 0x37, 0xc7, 0x5c, 0x7c, 0xd7, 0xd8, 0xfb,
-	0x42, 0x8d, 0x6e, 0x12, 0xf9, 0xeb, 0x70, 0xbc, 0xf1, 0x3c, 0xe6, 0xfb,
-	0x12, 0xe6, 0x7b, 0xf9, 0xfb, 0x41, 0x91, 0x57, 0x46, 0x5e, 0xf9, 0x43,
-	0x41, 0xa6, 0x89, 0xf4, 0x47, 0x9a, 0x7b, 0x3d, 0x9f, 0x59, 0xef, 0x63,
-	0x02, 0x6c, 0x67, 0xc1, 0x0b, 0x19, 0xae, 0x25, 0x07, 0xc7, 0x52, 0x37,
-	0x81, 0x17, 0x76, 0xca, 0x9f, 0xc0, 0x16, 0xf8, 0xe3, 0x4a, 0x1a, 0x3c,
-	0xd1, 0x03, 0x1e, 0xe9, 0x06, 0x5f, 0xa4, 0xb4, 0x5d, 0xfc, 0x28, 0x74,
-	0xde, 0xd9, 0x4a, 0xc9, 0xd9, 0x3b, 0x5a, 0x74, 0x72, 0xa3, 0x47, 0x41,
-	0x17, 0xdc, 0x03, 0xab, 0xae, 0xa9, 0x11, 0x37, 0x3e, 0x29, 0xa4, 0xff,
-	0x76, 0xee, 0xed, 0x68, 0x06, 0xae, 0xce, 0x10, 0x57, 0x93, 0x95, 0x2d,
-	0xde, 0x3a, 0xf0, 0x41, 0xb3, 0xe6, 0x83, 0x46, 0x27, 0xe3, 0xdd, 0x64,
-	0xf9, 0x60, 0x04, 0x7c, 0x50, 0x58, 0xc2, 0x07, 0xcf, 0x58, 0x9a, 0x9f,
-	0xae, 0xe2, 0x83, 0x49, 0x9b, 0x36, 0x7e, 0x05, 0x3e, 0xb8, 0xca, 0x4f,
-	0x3e, 0x39, 0x24, 0x27, 0xc0, 0x07, 0x0f, 0x6b, 0x3e, 0xb8, 0x4a, 0xf3,
-	0x01, 0xe3, 0x46, 0xe4, 0x85, 0x56, 0xc8, 0x0e, 0xf2, 0xc2, 0xb3, 0x32,
-	0x0b, 0x5e, 0x78, 0x51, 0xb1, 0xef, 0xcb, 0xb4, 0x0f, 0x46, 0xe9, 0x8f,
-	0x9d, 0x2a, 0x15, 0xc1, 0xbb, 0x4a, 0xbe, 0x30, 0x16, 0x04, 0x33, 0xf0,
-	0xd1, 0x1f, 0x84, 0x0d, 0xef, 0xea, 0x3b, 0x69, 0xa7, 0x61, 0xbb, 0x10,
-	0x36, 0xda, 0xe4, 0xe3, 0x0e, 0xe8, 0xfd, 0xf0, 0x04, 0xc6, 0xb0, 0x47,
-	0xfd, 0x3e, 0xfc, 0x60, 0x0f, 0xf3, 0x4a, 0xdb, 0xfe, 0xb8, 0xe6, 0x9b,
-	0x1a, 0xe8, 0x80, 0x93, 0xdd, 0x8c, 0x33, 0xf9, 0xde, 0x5e, 0xd5, 0x9e,
-	0xef, 0x03, 0xcc, 0x11, 0x75, 0xbf, 0x30, 0xc6, 0xd1, 0xb4, 0xc8, 0xb6,
-	0xa7, 0x5c, 0x18, 0x90, 0xfb, 0x6c, 0x5e, 0x3e, 0xa8, 0x83, 0x1d, 0x5a,
-	0xa7, 0x8c, 0x5d, 0xae, 0xb6, 0x25, 0xbd, 0xdf, 0x80, 0xd0, 0xac, 0x4d,
-	0x9b, 0x3d, 0x81, 0x7d, 0xc5, 0x6a, 0xbb, 0xfe, 0x5e, 0xd8, 0xf5, 0xac,
-	0x23, 0xae, 0xb1, 0xeb, 0xef, 0xb2, 0xbc, 0xc6, 0xdf, 0x9e, 0xb6, 0xf1,
-	0x0f, 0x00, 0xbe, 0x1d, 0x73, 0x36, 0x3e, 0xdb, 0xa0, 0xad, 0x21, 0x72,
-	0x03, 0xec, 0xbc, 0x1b, 0xc1, 0x83, 0x37, 0xc1, 0x8f, 0x7a, 0x77, 0xd1,
-	0x93, 0x9d, 0xc5, 0x66, 0xf8, 0xdb, 0xad, 0xf2, 0xab, 0x63, 0x1b, 0xa5,
-	0x7f, 0xf4, 0x77, 0x9a, 0xa1, 0x57, 0x61, 0x97, 0xbe, 0x08, 0x38, 0x23,
-	0x56, 0x56, 0x47, 0xc1, 0x03, 0xed, 0x89, 0x1f, 0xa8, 0x44, 0xab, 0x91,
-	0xed, 0x3c, 0x4b, 0xbe, 0x5c, 0x3b, 0x31, 0xd4, 0x67, 0x1c, 0xa5, 0x45,
-	0xce, 0x1c, 0xa7, 0xe7, 0x95, 0x80, 0x2d, 0x9e, 0x82, 0x1d, 0xb2, 0x01,
-	0xed, 0x31, 0x96, 0xbc, 0x5a, 0x9e, 0xd9, 0xea, 0xde, 0x9d, 0xd3, 0x7c,
-	0x78, 0xc9, 0xc9, 0x8e, 0xdd, 0x24, 0x85, 0xc1, 0x28, 0xc6, 0xa0, 0x9a,
-	0xd7, 0xca, 0xf5, 0xd2, 0xaf, 0xc7, 0x73, 0x59, 0x0e, 0x42, 0x1f, 0xff,
-	0x69, 0xb1, 0x5f, 0x66, 0x07, 0x9a, 0xf0, 0x1d, 0x95, 0x67, 0x8a, 0x5b,
-	0xe0, 0xef, 0xfc, 0x0a, 0x70, 0x54, 0x8b, 0xef, 0x5a, 0xe9, 0x5d, 0x47,
-	0x5e, 0x6d, 0x90, 0x19, 0xa4, 0xdf, 0x28, 0xbf, 0x64, 0xd3, 0x99, 0x46,
-	0xde, 0x68, 0x40, 0xdd, 0xa8, 0x9c, 0x2f, 0xd2, 0x96, 0xd4, 0x3c, 0xd1,
-	0xf3, 0xb2, 0x6c, 0xc9, 0xbc, 0x0c, 0xdb, 0xf4, 0x59, 0x3c, 0xcf, 0x4b,
-	0x72, 0xe7, 0x6e, 0x67, 0x4b, 0xa2, 0xdd, 0x81, 0xbe, 0xc4, 0xe3, 0x3a,
-	0x5b, 0xbc, 0x5a, 0xe7, 0x5a, 0xdb, 0x46, 0x8d, 0x3c, 0x3f, 0xa8, 0xe2,
-	0x0d, 0x98, 0x93, 0xcd, 0x4e, 0x87, 0x4d, 0xe3, 0xb7, 0xbe, 0x2f, 0x51,
-	0xda, 0xcf, 0xa8, 0x0d, 0xab, 0x44, 0xda, 0x1a, 0x60, 0xe7, 0xec, 0x11,
-	0xd5, 0xdc, 0x20, 0xae, 0xb4, 0x4f, 0xa8, 0x56, 0xa4, 0xf9, 0x36, 0x2d,
-	0xd6, 0x00, 0x9d, 0x80, 0xb4, 0x16, 0xa4, 0x6d, 0xb2, 0x69, 0x4d, 0x0d,
-	0x52, 0x8b, 0xb4, 0xcb, 0x9a, 0xe7, 0x2f, 0x76, 0xf8, 0x5e, 0xce, 0xa9,
-	0x97, 0xb6, 0x53, 0x0d, 0x90, 0x0d, 0xab, 0x65, 0x66, 0x6b, 0x9d, 0xb4,
-	0x21, 0x8f, 0x31, 0xee, 0xd4, 0xa9, 0xa8, 0xbc, 0xf3, 0x54, 0x7b, 0xfc,
-	0xa3, 0x18, 0x43, 0xfb, 0x19, 0xc6, 0xbc, 0xff, 0xac, 0x99, 0x31, 0x9f,
-	0xb6, 0x33, 0x7c, 0xd7, 0x69, 0xf9, 0x43, 0x7c, 0x98, 0x3b, 0xdf, 0x60,
-	0x63, 0x94, 0x8e, 0x3b, 0xc3, 0xa3, 0xd4, 0xdb, 0xed, 0xf6, 0x7e, 0xa2,
-	0xff, 0xd9, 0x4c, 0x5f, 0x6d, 0x82, 0x36, 0x54, 0x89, 0xfc, 0x48, 0xdd,
-	0x83, 0xf7, 0xb8, 0x23, 0x85, 0x79, 0x99, 0x35, 0x45, 0xbe, 0x3a, 0xae,
-	0xb8, 0x4f, 0x05, 0x69, 0x95, 0x77, 0x05, 0x66, 0x8e, 0xc9, 0x0b, 0x46,
-	0x2e, 0xfd, 0x9a, 0x91, 0x4b, 0xa7, 0xcf, 0x2d, 0x90, 0x4b, 0x05, 0x2d,
-	0x97, 0x06, 0x05, 0xef, 0xa9, 0x02, 0xe4, 0xd2, 0x08, 0xbe, 0x3d, 0x2d,
-	0x97, 0x62, 0x62, 0x6d, 0x64, 0x89, 0x5e, 0xc5, 0xfe, 0x27, 0x4b, 0xae,
-	0xb6, 0xa5, 0x0a, 0xe3, 0xb0, 0x43, 0x4a, 0x23, 0x56, 0x67, 0x4b, 0xba,
-	0x49, 0x3a, 0x7a, 0x7e, 0x2a, 0xa1, 0x9d, 0x39, 0xdb, 0xcc, 0x3b, 0x8f,
-	0x5f, 0x54, 0x94, 0x61, 0x27, 0x20, 0xc3, 0x1e, 0xbe, 0x82, 0x0c, 0x43,
-	0x5e, 0x19, 0x79, 0x65, 0xb6, 0xfb, 0xdd, 0x9f, 0x0e, 0x79, 0x94, 0x1f,
-	0x94, 0x19, 0x90, 0x49, 0x25, 0xc8, 0xa4, 0x12, 0xe4, 0x54, 0x09, 0x72,
-	0xa9, 0x04, 0xb9, 0x54, 0x82, 0x5c, 0x2a, 0x41, 0x2e, 0x41, 0xc6, 0x3d,
-	0x0a, 0x19, 0x67, 0x64, 0xda, 0x00, 0xed, 0x35, 0xb9, 0xcf, 0xea, 0x77,
-	0x13, 0x27, 0xe9, 0xb2, 0x7e, 0x91, 0xd9, 0xb3, 0x7a, 0xae, 0x2a, 0x2e,
-	0xb8, 0xeb, 0x88, 0xe6, 0x77, 0xcf, 0x57, 0xd7, 0x3a, 0xdc, 0x1f, 0xf3,
-	0x03, 0xed, 0xb3, 0x6f, 0xe6, 0x6f, 0xa9, 0x03, 0x5f, 0xbf, 0x62, 0xf9,
-	0x7a, 0xf3, 0x1c, 0x5f, 0x27, 0x1d, 0xc6, 0x89, 0x97, 0xe7, 0xeb, 0x16,
-	0x9b, 0x97, 0x0f, 0x56, 0x80, 0xaf, 0x57, 0x2c, 0xe2, 0xeb, 0x28, 0xf8,
-	0x7a, 0xe7, 0x12, 0xbe, 0x5e, 0xe5, 0xf4, 0xea, 0x3a, 0x3c, 0x83, 0xc6,
-	0xef, 0x5a, 0x67, 0x9e, 0xaf, 0xf7, 0x6b, 0xbe, 0x3e, 0x04, 0xbe, 0xbe,
-	0xbe, 0x8a, 0xaf, 0x77, 0x4a, 0xf2, 0x96, 0x6c, 0x64, 0xa3, 0xec, 0xbe,
-	0x5f, 0x35, 0xaf, 0x91, 0x7f, 0x11, 0x53, 0xdf, 0xf0, 0x58, 0xef, 0x58,
-	0xb3, 0xe4, 0x1e, 0xfa, 0x11, 0xd7, 0x06, 0xc8, 0x23, 0x43, 0x19, 0xc7,
-	0x93, 0x83, 0x47, 0x7e, 0x20, 0xd3, 0x9a, 0xb7, 0x44, 0xf6, 0x1c, 0x89,
-	0xca, 0xf0, 0x11, 0xc6, 0x1e, 0xbe, 0x63, 0xe9, 0xbd, 0x4e, 0x86, 0x07,
-	0xb9, 0x5f, 0xd2, 0x95, 0xdd, 0x47, 0xe0, 0x63, 0x1d, 0x61, 0xec, 0xe1,
-	0xf2, 0x1c, 0x8f, 0x4d, 0x43, 0xb6, 0xec, 0x3e, 0xa2, 0xe7, 0x1a, 0xed,
-	0x34, 0xc8, 0xa1, 0x23, 0x22, 0xb7, 0x1d, 0x71, 0xe5, 0xf6, 0x23, 0x73,
-	0xbc, 0x36, 0x10, 0xf2, 0xda, 0x9f, 0x83, 0xd7, 0xda, 0x2d, 0xaf, 0xa9,
-	0x39, 0x5e, 0xfb, 0x5a, 0x15, 0xaf, 0xb1, 0x3e, 0x79, 0xed, 0x82, 0x4d,
-	0xe3, 0xb7, 0x2b, 0x7b, 0x8f, 0xb4, 0xca, 0xee, 0x87, 0xde, 0x22, 0x7b,
-	0xee, 0x27, 0xac, 0xe6, 0x9e, 0x3c, 0xda, 0x5f, 0xe3, 0x95, 0x76, 0xb4,
-	0x1f, 0xee, 0x0f, 0xd2, 0x77, 0x65, 0x75, 0x4e, 0x48, 0x32, 0xcf, 0xfe,
-	0x6a, 0xe1, 0x3b, 0x9f, 0x82, 0x4f, 0xb1, 0x17, 0x30, 0xdd, 0x7a, 0x44,
-	0x92, 0xae, 0xbc, 0x26, 0x23, 0xa9, 0x47, 0x5b, 0x8d, 0x3d, 0x71, 0x09,
-	0xbc, 0x42, 0xfa, 0xcf, 0x48, 0xee, 0xed, 0x81, 0xf6, 0x2b, 0x46, 0xcb,
-	0x42, 0xff, 0x9f, 0x31, 0x73, 0xc7, 0xdc, 0x77, 0xc7, 0xf3, 0xbe, 0x35,
-	0xfa, 0xbc, 0x9b, 0x8e, 0xd7, 0x76, 0x33, 0xbf, 0x46, 0xef, 0x37, 0xcd,
-	0xe9, 0xb3, 0xdc, 0xac, 0xcf, 0x76, 0x62, 0x3a, 0x9e, 0x5e, 0x28, 0xf3,
-	0x8e, 0x30, 0xde, 0xbd, 0xcc, 0xbb, 0x06, 0xff, 0xf8, 0x2a, 0x13, 0x9b,
-	0x25, 0xdf, 0x7d, 0xdd, 0xc9, 0x15, 0x2f, 0xe9, 0x7d, 0x85, 0x59, 0x1f,
-	0xbf, 0xcb, 0xfc, 0x66, 0xf9, 0x4b, 0x8c, 0x71, 0x24, 0x12, 0xea, 0x81,
-	0x56, 0xee, 0x3b, 0x18, 0x9c, 0x32, 0x76, 0x94, 0xe1, 0xd1, 0x06, 0xed,
-	0x6b, 0x8c, 0xe0, 0x7b, 0xf7, 0x68, 0xa3, 0x53, 0xa0, 0x6d, 0x32, 0xd0,
-	0xe0, 0xe4, 0xc7, 0xf7, 0xb4, 0x1a, 0x9b, 0x79, 0x20, 0xce, 0x3d, 0x85,
-	0x19, 0xb5, 0x54, 0x26, 0x9f, 0x92, 0x50, 0x26, 0x27, 0x6f, 0xc9, 0xc0,
-	0xb6, 0xce, 0x1d, 0xd1, 0xf7, 0xf7, 0x25, 0xda, 0x15, 0xc7, 0xf4, 0x09,
-	0xc8, 0xd7, 0x90, 0x16, 0xe2, 0xf2, 0xf1, 0x23, 0xa4, 0x07, 0x15, 0x6b,
-	0x94, 0xdf, 0xb2, 0xf4, 0x70, 0x59, 0x8a, 0x90, 0x3b, 0x47, 0x8e, 0xdc,
-	0x2e, 0xe3, 0xbb, 0x16, 0xd3, 0xc3, 0x9e, 0x79, 0x7a, 0x88, 0xc1, 0x3e,
-	0x73, 0xaa, 0xe9, 0xe1, 0x37, 0xe7, 0xe8, 0x61, 0xdc, 0xf9, 0xd7, 0xd2,
-	0xc3, 0x0d, 0x0b, 0xe8, 0x61, 0x44, 0xd3, 0x43, 0xff, 0x1c, 0x3d, 0x8c,
-	0x1c, 0x61, 0xbf, 0x7a, 0x5d, 0xd4, 0x9b, 0x71, 0x38, 0xe7, 0x73, 0xb4,
-	0x90, 0x18, 0xd6, 0xfb, 0x44, 0x93, 0x79, 0x9e, 0x25, 0x5d, 0xa5, 0x18,
-	0x1b, 0x99, 0x9f, 0xff, 0xc6, 0x7f, 0xd3, 0xf9, 0x7f, 0x47, 0xfc, 0xff,
-	0xef, 0xfc, 0x5f, 0x8f, 0xf6, 0x29, 0x8b, 0x43, 0x79, 0x1c, 0xd2, 0xc3,
-	0x7b, 0xe2, 0x46, 0x2f, 0x70, 0x8e, 0xf9, 0x6d, 0xf6, 0xac, 0x9f, 0x83,
-	0xfc, 0x7b, 0x1c, 0xf2, 0xef, 0xb1, 0x05, 0xeb, 0x01, 0x3d, 0x36, 0x06,
-	0x11, 0xc8, 0xc1, 0xd4, 0x3c, 0x3e, 0x66, 0xba, 0x89, 0x0f, 0xb3, 0xf7,
-	0xe4, 0x6c, 0x65, 0x31, 0x4e, 0x5c, 0xbd, 0xdf, 0xe8, 0x64, 0xaa, 0x1a,
-	0x27, 0x84, 0x7b, 0xb6, 0x6a, 0x8c, 0xf8, 0x5d, 0xe6, 0xf7, 0x65, 0xbd,
-	0x87, 0xa4, 0xa0, 0xd7, 0x9f, 0x88, 0x17, 0xae, 0x3f, 0x11, 0x27, 0xae,
-	0xb6, 0xf7, 0x0b, 0xe5, 0x3a, 0xbd, 0x2f, 0xfc, 0xc0, 0x54, 0x4c, 0x66,
-	0x62, 0x8c, 0xeb, 0xf1, 0xde, 0x57, 0xfa, 0xca, 0x7e, 0xbc, 0x20, 0x79,
-	0x7b, 0xd6, 0x67, 0x95, 0xa5, 0x6d, 0xc6, 0x03, 0x79, 0x27, 0x42, 0xb8,
-	0x0e, 0xd1, 0x69, 0x65, 0x5d, 0x43, 0x55, 0x9c, 0x12, 0x78, 0x1f, 0x93,
-	0x44, 0xb6, 0x1b, 0xef, 0x29, 0xf6, 0xfd, 0xa4, 0x8c, 0x3c, 0x58, 0x86,
-	0x2d, 0xf7, 0x30, 0x74, 0x8e, 0x23, 0x10, 0x93, 0xfa, 0x2e, 0x14, 0xc2,
-	0x30, 0xa1, 0xef, 0xf5, 0xa3, 0xdf, 0x47, 0x7a, 0x88, 0xe3, 0xfb, 0xb2,
-	0x8d, 0x25, 0xc5, 0xa5, 0x50, 0xfc, 0x01, 0xe0, 0xe7, 0x1d, 0x94, 0x3f,
-	0xc2, 0xfb, 0x8d, 0xe6, 0xc3, 0xf8, 0x21, 0x03, 0xfa, 0xcd, 0xb9, 0x79,
-	0xcd, 0xc9, 0x94, 0xcd, 0xfe, 0x96, 0xaa, 0xfb, 0xf5, 0xe5, 0xb0, 0xb6,
-	0x9f, 0xd3, 0x76, 0x5f, 0x0b, 0xcf, 0xe7, 0x19, 0x1b, 0xfa, 0xcb, 0xb0,
-	0xa1, 0x9f, 0xa8, 0x64, 0xf4, 0x1a, 0xd6, 0x63, 0xb0, 0xa1, 0x1f, 0x85,
-	0xee, 0xa1, 0xce, 0x89, 0x59, 0x9d, 0x33, 0xa2, 0x76, 0x69, 0x9d, 0xf3,
-	0xd7, 0x5a, 0xe7, 0xfc, 0xea, 0x12, 0x9d, 0x73, 0x48, 0xb5, 0x8f, 0x52,
-	0xe7, 0xf4, 0xaa, 0x9d, 0x0e, 0xed, 0xc5, 0xb5, 0xcb, 0xe8, 0x9c, 0xf7,
-	0xca, 0xaf, 0xd8, 0xbc, 0xfd, 0xf2, 0xbe, 0x6d, 0x7a, 0xdd, 0xc6, 0x9b,
-	0x50, 0xbc, 0xcb, 0xce, 0xe8, 0xa0, 0xeb, 0x55, 0xa7, 0x5e, 0xef, 0xfd,
-	0x6a, 0x95, 0xce, 0x69, 0x53, 0xdd, 0x4e, 0xaf, 0xae, 0xc3, 0x78, 0x04,
-	0xbf, 0x53, 0x4e, 0x66, 0xa0, 0x0e, 0xdf, 0x71, 0x89, 0x1c, 0xc1, 0xd8,
-	0xcd, 0x7d, 0x7b, 0xca, 0xe4, 0x5d, 0x63, 0xf3, 0x54, 0x98, 0xee, 0x9a,
-	0xf4, 0x76, 0x9b, 0x6e, 0x74, 0x55, 0x9b, 0x6a, 0xd5, 0xba, 0x6a, 0x33,
-	0x18, 0x6a, 0x02, 0xfa, 0x75, 0xa2, 0x14, 0xea, 0x2c, 0xfe, 0x66, 0xbc,
-	0x99, 0x71, 0x89, 0x30, 0x6e, 0x9d, 0x40, 0x19, 0x3c, 0xa5, 0xd0, 0xa6,
-	0xe4, 0x6f, 0xf8, 0x0a, 0x78, 0xa6, 0x80, 0xd7, 0x5b, 0xc0, 0x3f, 0xbf,
-	0x5e, 0x64, 0xdc, 0xb3, 0x59, 0x8e, 0x8e, 0x55, 0xe7, 0xb5, 0xca, 0xbb,
-	0xc7, 0x36, 0xc8, 0xbe, 0x51, 0xff, 0x6a, 0xa9, 0xdf, 0x28, 0x23, 0xa3,
-	0x2f, 0xea, 0xfb, 0x40, 0xd6, 0xe8, 0x7b, 0x92, 0x78, 0x7f, 0x98, 0x91,
-	0x91, 0xfd, 0x8e, 0x91, 0x91, 0x19, 0x35, 0x6f, 0xb3, 0x86, 0x6d, 0xf2,
-	0x6e, 0xa6, 0xbe, 0xd1, 0xb8, 0xbe, 0x43, 0x7a, 0xa2, 0x72, 0xad, 0xfc,
-	0xd1, 0x71, 0x75, 0xa7, 0x9a, 0xbf, 0x4b, 0x41, 0xdb, 0xac, 0x93, 0x0b,
-	0x6c, 0xd6, 0xbf, 0x97, 0x99, 0xf7, 0x45, 0x31, 0x4e, 0xd0, 0xf0, 0x75,
-	0x2f, 0x73, 0x1d, 0xb4, 0x39, 0x26, 0x97, 0xa4, 0x4f, 0xe3, 0x8f, 0xf2,
-	0xb4, 0x01, 0x72, 0x70, 0x56, 0xeb, 0xd7, 0xb5, 0xbc, 0xf3, 0xf8, 0x08,
-	0x6d, 0xd7, 0xaf, 0x6b, 0x79, 0xb6, 0xd6, 0xda, 0xae, 0xd3, 0x90, 0xd3,
-	0x94, 0xa3, 0x37, 0xca, 0x5f, 0xdb, 0x74, 0xa6, 0x25, 0xe3, 0xb3, 0x42,
-	0x7d, 0x17, 0x83, 0x0c, 0xa5, 0x3c, 0xfd, 0x59, 0x6d, 0xd7, 0xe7, 0x6c,
-	0x1b, 0x94, 0x9f, 0x46, 0x76, 0x6f, 0x76, 0xa6, 0x6d, 0x1a, 0xbf, 0xc3,
-	0x18, 0xba, 0x9f, 0xc9, 0x59, 0x3e, 0x53, 0xce, 0x93, 0xc8, 0x5f, 0x83,
-	0x7c, 0xf2, 0xd9, 0x63, 0x9a, 0xcf, 0xb4, 0x7d, 0xe2, 0x74, 0xd9, 0x35,
-	0x85, 0xb9, 0xf5, 0x80, 0x3c, 0xf9, 0x4c, 0x1d, 0xf5, 0xa6, 0x8d, 0x3c,
-	0xf0, 0x90, 0xfe, 0x45, 0xe8, 0x0e, 0xd6, 0x45, 0xfa, 0xb1, 0x0c, 0xe6,
-	0xf0, 0x24, 0xfc, 0x9f, 0x46, 0x7c, 0x37, 0xe3, 0x7b, 0x42, 0x7e, 0x75,
-	0x30, 0xaa, 0xc7, 0x3d, 0x82, 0x71, 0x1c, 0x38, 0x82, 0x31, 0x39, 0xc6,
-	0x76, 0x76, 0xcf, 0xb8, 0x52, 0x73, 0x86, 0x7c, 0xc7, 0x33, 0x86, 0x41,
-	0xb0, 0xb7, 0x8b, 0x74, 0x9b, 0xf4, 0xfa, 0xf5, 0xf9, 0xb7, 0xcd, 0xf1,
-	0x08, 0x70, 0x72, 0x00, 0xf3, 0x31, 0x52, 0xf4, 0xbd, 0xac, 0xe3, 0xc7,
-	0x31, 0x4e, 0xd8, 0x80, 0xed, 0xb0, 0x05, 0xdb, 0x61, 0x07, 0xb6, 0xc3,
-	0x0e, 0x5c, 0x2d, 0xa7, 0xb6, 0x72, 0x7f, 0x49, 0xfe, 0x9d, 0xbc, 0x77,
-	0xf9, 0x1b, 0x3a, 0x36, 0x5f, 0x7b, 0x4b, 0x1f, 0x7c, 0x76, 0xf1, 0x92,
-	0x03, 0xdc, 0x63, 0x3f, 0xeb, 0xd5, 0xde, 0xd2, 0x2f, 0xed, 0x3d, 0xc8,
-	0xef, 0xb9, 0x24, 0x1d, 0xb7, 0x7c, 0xd8, 0xa9, 0x1d, 0xe8, 0x03, 0x1e,
-	0x33, 0x4e, 0x32, 0x3e, 0xe4, 0x30, 0x4e, 0x91, 0xdd, 0x1c, 0xd1, 0x67,
-	0xc4, 0xa6, 0x19, 0x8b, 0xb8, 0xa5, 0x3d, 0xb2, 0x25, 0xb1, 0xdb, 0x49,
-	0x0e, 0xa8, 0x48, 0x72, 0xa0, 0xcf, 0x09, 0xcb, 0xf1, 0x0e, 0x6a, 0xc8,
-	0x19, 0xc0, 0x7a, 0xa0, 0xf4, 0x75, 0xd0, 0xd3, 0x79, 0x29, 0x1c, 0x6f,
-	0x90, 0xa9, 0x62, 0xbb, 0x97, 0x55, 0x31, 0xe1, 0xbe, 0x12, 0x75, 0x0a,
-	0x44, 0x7f, 0x26, 0x2a, 0x13, 0xa3, 0x1b, 0x45, 0x69, 0xdb, 0xbd, 0x45,
-	0xb2, 0x63, 0xa3, 0x72, 0xbe, 0x5b, 0x9a, 0x14, 0xda, 0xe7, 0xdd, 0xde,
-	0xea, 0x14, 0xd7, 0x11, 0x43, 0x5e, 0x58, 0x4f, 0x3e, 0x19, 0x05, 0x0e,
-	0x41, 0xb7, 0x8c, 0xeb, 0xd6, 0x09, 0xe5, 0xde, 0xed, 0x3a, 0x66, 0xca,
-	0x38, 0x6d, 0xf5, 0x7a, 0x03, 0xf9, 0x23, 0xba, 0x2c, 0x7f, 0x4c, 0x96,
-	0xb8, 0x36, 0x23, 0x79, 0x97, 0x71, 0x61, 0x1f, 0xbf, 0xc7, 0x59, 0xb6,
-	0x4e, 0x46, 0xba, 0xf3, 0x76, 0x8f, 0xc7, 0x37, 0xc1, 0x07, 0x1c, 0x9f,
-	0x5e, 0x27, 0x01, 0xaf, 0x2f, 0x5e, 0xcf, 0x88, 0x56, 0xc9, 0x03, 0x47,
-	0x66, 0x46, 0xc3, 0xf5, 0x0f, 0xb6, 0x87, 0xef, 0x71, 0x23, 0x6f, 0xb3,
-	0x4b, 0xea, 0x11, 0x2e, 0xae, 0x55, 0x2e, 0x94, 0xb1, 0x4a, 0x9f, 0x13,
-	0xf6, 0xb4, 0x7c, 0x3d, 0x5d, 0x31, 0xb2, 0x75, 0xbc, 0x12, 0xea, 0x96,
-	0xa8, 0xd1, 0xa5, 0x4b, 0xf4, 0x89, 0x89, 0x60, 0xce, 0xeb, 0x93, 0x4b,
-	0x3a, 0x46, 0xf7, 0x6b, 0x53, 0x2d, 0xe2, 0x1e, 0x93, 0xd9, 0x11, 0xff,
-	0x54, 0x2b, 0xf7, 0x69, 0x8c, 0xa4, 0xde, 0x8c, 0x7e, 0x8c, 0xb5, 0x50,
-	0x1f, 0x0e, 0xa9, 0xb5, 0x78, 0xaf, 0xd1, 0xf4, 0x07, 0x9e, 0xc2, 0xb7,
-	0xf1, 0x13, 0xbe, 0x0c, 0x3f, 0xe1, 0x09, 0xe8, 0xba, 0x73, 0xf0, 0x13,
-	0x1e, 0x87, 0x9f, 0xf0, 0x18, 0xfc, 0x84, 0x47, 0xa1, 0x27, 0xab, 0xfd,
-	0x83, 0xe1, 0x05, 0xfe, 0x41, 0xa0, 0xf9, 0x9f, 0x31, 0xc0, 0xc7, 0xab,
-	0x7c, 0x83, 0xbd, 0x46, 0x5f, 0xc1, 0xef, 0x37, 0x7c, 0xd4, 0xa6, 0x6e,
-	0xd6, 0xfa, 0xd1, 0xec, 0xd9, 0x1d, 0x98, 0xd3, 0x57, 0x6d, 0xca, 0xe8,
-	0xab, 0x89, 0x79, 0x7d, 0x65, 0xf8, 0xe8, 0xd8, 0xa8, 0x44, 0xfc, 0xd1,
-	0xe9, 0x6c, 0x6a, 0xbb, 0xe6, 0xa1, 0x26, 0x7f, 0xa3, 0x44, 0x1e, 0x50,
-	0xcd, 0x35, 0x92, 0xb5, 0xdf, 0xa0, 0xaf, 0xa3, 0x5f, 0x47, 0x5b, 0xef,
-	0x94, 0x9c, 0xb6, 0xcf, 0xae, 0x8c, 0xef, 0x47, 0x17, 0xe1, 0xbb, 0x50,
-	0x7a, 0x56, 0xe3, 0xfc, 0x7e, 0x7d, 0x26, 0xbf, 0x41, 0x86, 0xcb, 0x21,
-	0xce, 0x79, 0x06, 0x8e, 0xfb, 0x30, 0x5a, 0x25, 0x72, 0xac, 0x45, 0xfa,
-	0x53, 0xa2, 0x72, 0xa9, 0x95, 0x7a, 0xff, 0xca, 0xa9, 0x6e, 0x89, 0xe7,
-	0xba, 0x49, 0xab, 0xf7, 0xc9, 0x84, 0x9e, 0x8b, 0x16, 0xa9, 0x39, 0x46,
-	0x1b, 0x25, 0x5c, 0xc3, 0xbb, 0xbd, 0xc5, 0xde, 0x41, 0x1d, 0x35, 0xe5,
-	0x44, 0x0e, 0xea, 0xf9, 0x9a, 0xd5, 0x7b, 0x0c, 0x6f, 0x9e, 0x62, 0x2c,
-	0x9e, 0xf7, 0xfd, 0x31, 0x0e, 0xff, 0xaf, 0x99, 0xbf, 0x42, 0x8b, 0xb1,
-	0x67, 0xd6, 0x58, 0x3b, 0xc6, 0xc4, 0xa9, 0x96, 0xb7, 0x61, 0xd8, 0x4e,
-	0xf5, 0x1d, 0xb5, 0xab, 0xe0, 0x03, 0x37, 0xa0, 0x4d, 0xae, 0x63, 0xdb,
-	0xbf, 0x17, 0xe4, 0xfd, 0xb3, 0x73, 0xc0, 0x5f, 0x85, 0xb4, 0x06, 0xe4,
-	0x31, 0x66, 0xf3, 0x85, 0x16, 0xc6, 0x65, 0xb3, 0x7e, 0xa3, 0x4d, 0x5b,
-	0xe5, 0x8c, 0x8c, 0xb6, 0xc3, 0x37, 0xe7, 0x39, 0x76, 0xe6, 0xf7, 0x73,
-	0xee, 0x84, 0x7f, 0xab, 0x69, 0x12, 0xf2, 0x67, 0x8f, 0x5c, 0x6b, 0xe3,
-	0xce, 0xd4, 0xc3, 0xbf, 0xb8, 0x60, 0xbd, 0xf6, 0x10, 0xf4, 0xd8, 0xad,
-	0x90, 0x47, 0xd4, 0xc3, 0x87, 0xe4, 0x17, 0x2c, 0x3d, 0x2f, 0xd4, 0xc3,
-	0x17, 0x85, 0xb1, 0xe1, 0x2e, 0xe4, 0xe5, 0x83, 0x28, 0xe8, 0xe1, 0x70,
-	0x95, 0xaf, 0x46, 0xbf, 0xaf, 0x2e, 0x6d, 0xd6, 0xc0, 0x16, 0xfa, 0x7d,
-	0x90, 0x03, 0xb1, 0xd0, 0xcf, 0xab, 0x9d, 0x5b, 0xa3, 0xdd, 0x69, 0xeb,
-	0x8e, 0xa4, 0x5e, 0x22, 0x8e, 0x12, 0x87, 0xe4, 0xf6, 0xf5, 0xbc, 0x26,
-	0xcf, 0xf5, 0xbf, 0xa5, 0x71, 0x26, 0x8a, 0xb4, 0xb7, 0x46, 0xc3, 0x68,
-	0xe5, 0x7c, 0x22, 0xdc, 0xbf, 0x51, 0xb0, 0x75, 0xf7, 0xd8, 0xf5, 0xf8,
-	0x82, 0x7c, 0x9b, 0x71, 0xce, 0x44, 0x5f, 0x64, 0x25, 0xcf, 0x64, 0xa3,
-	0xee, 0xed, 0xda, 0x6f, 0xcf, 0x48, 0xd8, 0x16, 0xbf, 0x6b, 0xaa, 0xda,
-	0xa6, 0x1d, 0xc5, 0xf7, 0xe2, 0xfb, 0x1b, 0x9e, 0xd7, 0x6b, 0x8b, 0xe6,
-	0x6e, 0x9a, 0x90, 0x4f, 0xc8, 0x3b, 0x09, 0x7d, 0x8e, 0xc9, 0x3f, 0x46,
-	0xbb, 0x87, 0xeb, 0xae, 0xde, 0xf4, 0x70, 0xea, 0x23, 0xfa, 0x0e, 0xd5,
-	0x71, 0x11, 0xa7, 0x90, 0xda, 0xab, 0xf7, 0x9d, 0x14, 0x74, 0x7c, 0x39,
-	0x8f, 0xf7, 0xbc, 0x8f, 0xda, 0x76, 0x8c, 0x7f, 0x0b, 0x88, 0x69, 0x1f,
-	0x04, 0x6c, 0xd4, 0x21, 0x94, 0xbd, 0x31, 0x69, 0x3b, 0xfa, 0x7e, 0xcd,
-	0x0b, 0x6b, 0xe1, 0x0b, 0xf4, 0x1e, 0x85, 0xae, 0x3e, 0x1a, 0x97, 0xfe,
-	0xa3, 0x5a, 0x37, 0x66, 0x96, 0xc6, 0x0a, 0xb6, 0x78, 0x2e, 0xfd, 0x89,
-	0x98, 0x27, 0xd7, 0x1c, 0x8d, 0xc8, 0xe1, 0xd8, 0x16, 0xaf, 0xc3, 0xb9,
-	0xd1, 0xea, 0x42, 0x43, 0x7f, 0xa0, 0x15, 0xd4, 0x37, 0xeb, 0x90, 0xbd,
-	0xf3, 0xb1, 0x6b, 0xd4, 0x7f, 0x49, 0x46, 0xc8, 0x4b, 0x95, 0x88, 0x8c,
-	0x0f, 0xb6, 0x02, 0x9e, 0xb7, 0xae, 0x07, 0x0e, 0x40, 0x53, 0x98, 0x1f,
-	0xfd, 0xf7, 0x3c, 0xdc, 0x38, 0xe5, 0x57, 0x1b, 0xfa, 0xef, 0x3b, 0x4a,
-	0x1d, 0xe6, 0x6b, 0xbe, 0x46, 0xbf, 0x5e, 0x8d, 0xf6, 0x3d, 0xc8, 0x8b,
-	0x6f, 0x11, 0xff, 0x01, 0xc8, 0xb5, 0xa3, 0x51, 0xe9, 0x38, 0xda, 0x20,
-	0x9b, 0x8e, 0xd2, 0xf7, 0xa8, 0xf6, 0x45, 0x69, 0x8b, 0x5e, 0xc2, 0xb8,
-	0x6e, 0x34, 0xf7, 0x0d, 0x4e, 0x45, 0x65, 0x1f, 0xf9, 0x15, 0x65, 0x73,
-	0xb0, 0x93, 0xb3, 0x47, 0x3d, 0xbd, 0x16, 0x9a, 0xc5, 0x38, 0xf9, 0x37,
-	0x2c, 0xfa, 0x8e, 0x1a, 0x39, 0x53, 0xa0, 0x6f, 0x32, 0xd0, 0x02, 0xbc,
-	0x3e, 0x60, 0xf9, 0xe5, 0x3d, 0xeb, 0x2d, 0x5f, 0xfe, 0x9c, 0xfc, 0x96,
-	0x5b, 0x6f, 0xe4, 0xe5, 0x87, 0xd6, 0x73, 0x2f, 0xd2, 0x5a, 0x9f, 0xef,
-	0x3a, 0x6d, 0x43, 0x18, 0xb9, 0xf9, 0x7a, 0xfc, 0x27, 0xc0, 0x51, 0xb8,
-	0xfe, 0x44, 0x3e, 0xe4, 0x1a, 0xb2, 0x3e, 0xb3, 0x92, 0x9a, 0xd1, 0x7f,
-	0x53, 0x89, 0x6b, 0x61, 0xf3, 0xf7, 0x59, 0x6d, 0xaf, 0x30, 0x36, 0xfe,
-	0x4c, 0xf8, 0x37, 0x9c, 0xaa, 0xf6, 0x19, 0x56, 0xaf, 0x75, 0x31, 0xbe,
-	0x34, 0xb7, 0x17, 0x28, 0x18, 0xd5, 0x77, 0xc2, 0xc5, 0x9c, 0x8b, 0xc5,
-	0x5a, 0xe7, 0x9b, 0x63, 0x12, 0xb8, 0x7e, 0xdc, 0xf9, 0x96, 0xcf, 0xb5,
-	0x71, 0xcf, 0x79, 0xb9, 0xe8, 0x83, 0xf7, 0xfe, 0x02, 0xe3, 0x68, 0x75,
-	0x5e, 0xc1, 0x9c, 0x1e, 0x2c, 0x65, 0x92, 0x9e, 0x8d, 0x83, 0x3f, 0x5b,
-	0x6c, 0x75, 0x9e, 0x9b, 0x8f, 0x21, 0xf5, 0x84, 0x74, 0x71, 0x88, 0x79,
-	0x65, 0xe4, 0x95, 0x19, 0xeb, 0xad, 0x77, 0x26, 0xc7, 0xec, 0x7e, 0x12,
-	0xa3, 0x8b, 0xe6, 0xd6, 0x5f, 0x06, 0xf4, 0xfa, 0x84, 0xeb, 0x4c, 0x4e,
-	0x4d, 0xaf, 0x37, 0xfb, 0x8a, 0x6a, 0x91, 0x67, 0xf6, 0x58, 0x4e, 0x4c,
-	0xd5, 0xa2, 0x4c, 0xbd, 0x33, 0xa1, 0x63, 0x5e, 0xda, 0xf6, 0x70, 0xc6,
-	0xa7, 0xea, 0x9d, 0x29, 0xbd, 0xd6, 0x1c, 0x75, 0x4e, 0x8e, 0xb1, 0xed,
-	0x28, 0xca, 0x88, 0x73, 0x0a, 0xed, 0x4d, 0x8d, 0xb5, 0xc7, 0xf7, 0x49,
-	0x3b, 0x6c, 0x01, 0xfe, 0x8d, 0x34, 0xde, 0x17, 0xe0, 0x3a, 0x53, 0x73,
-	0xed, 0x2a, 0xb4, 0xc3, 0xb2, 0xa4, 0x41, 0xf6, 0xeb, 0xa2, 0xfd, 0xa5,
-	0x6b, 0x52, 0x4b, 0x71, 0x32, 0x06, 0x9c, 0x1c, 0xb4, 0x38, 0x39, 0x61,
-	0x71, 0x32, 0x5a, 0x85, 0x93, 0x87, 0x17, 0xe1, 0xe4, 0x04, 0x70, 0xf2,
-	0xf0, 0x15, 0x70, 0x82, 0xbc, 0xf2, 0xc3, 0x16, 0x27, 0xf7, 0x2d, 0xc2,
-	0x49, 0x7e, 0x2e, 0x16, 0x6f, 0x70, 0x32, 0x02, 0x9c, 0xd4, 0xb4, 0x1a,
-	0xd8, 0x0f, 0x5a, 0x9c, 0xe0, 0x3d, 0x75, 0x10, 0x65, 0xee, 0xab, 0xc2,
-	0xc9, 0x41, 0xe0, 0xe4, 0x3e, 0x8b, 0x93, 0xc3, 0x16, 0x27, 0x87, 0x51,
-	0x26, 0x0f, 0x9c, 0x14, 0x96, 0xc1, 0xc9, 0x08, 0x70, 0x12, 0xb6, 0x5b,
-	0x40, 0x3b, 0x87, 0xab, 0x70, 0x32, 0xb2, 0x0c, 0x4e, 0xb8, 0xe6, 0x1a,
-	0xee, 0xe1, 0xbe, 0xfc, 0x06, 0x7b, 0xb8, 0x53, 0x9f, 0x7d, 0xe3, 0x3d,
-	0xdc, 0x2c, 0x73, 0xb9, 0xea, 0xcc, 0xfb, 0xb3, 0x76, 0x4f, 0x9a, 0xd9,
-	0xfb, 0x37, 0x7f, 0x0f, 0x5e, 0x3b, 0xf8, 0xbc, 0x90, 0xf7, 0xc4, 0xec,
-	0x21, 0x75, 0xb7, 0x4d, 0x81, 0xd7, 0x8e, 0xca, 0x81, 0xe3, 0xb5, 0x87,
-	0x73, 0x36, 0xcd, 0xdf, 0xd6, 0x9e, 0x57, 0x8a, 0x79, 0xe1, 0xde, 0x83,
-	0x17, 0xcd, 0x5d, 0x50, 0x31, 0x9e, 0xc7, 0xa8, 0x5e, 0x7b, 0x7e, 0xd1,
-	0xde, 0x55, 0xe4, 0xdd, 0x9b, 0xf5, 0xa7, 0x13, 0xdc, 0x57, 0x55, 0xd0,
-	0xf0, 0x72, 0x2d, 0xad, 0x47, 0xef, 0xa5, 0xca, 0x16, 0x69, 0x67, 0x27,
-	0xb8, 0x27, 0x0d, 0xf6, 0x31, 0xf7, 0xed, 0x9a, 0x7d, 0xba, 0xbd, 0x0b,
-	0xf6, 0xe9, 0x56, 0x9f, 0xef, 0x26, 0xdf, 0xcd, 0xd3, 0xcd, 0xc1, 0xb9,
-	0xbb, 0x57, 0x8f, 0x3b, 0xcf, 0xe8, 0xf8, 0x70, 0x3d, 0xe6, 0x27, 0x08,
-	0x4e, 0xa7, 0x4c, 0x5c, 0x76, 0x46, 0xc7, 0x65, 0x05, 0x1e, 0xf8, 0xb0,
-	0x8d, 0xcd, 0x76, 0xf4, 0x5c, 0x9e, 0x8b, 0xcb, 0x2e, 0xd8, 0xa3, 0xa3,
-	0xef, 0xff, 0xc8, 0x8e, 0x5e, 0xd2, 0x7b, 0x71, 0xfa, 0x52, 0x8e, 0x14,
-	0x20, 0x23, 0xf6, 0x8c, 0xbf, 0x2a, 0xc3, 0x0f, 0xf2, 0x9b, 0x3a, 0x2d,
-	0x02, 0xbd, 0x45, 0xb9, 0x9d, 0x97, 0x6c, 0x0f, 0xd3, 0x4c, 0x9d, 0x3e,
-	0xed, 0x23, 0x1f, 0x77, 0x7a, 0xe7, 0xfa, 0x27, 0x7e, 0xc3, 0x35, 0x70,
-	0xfe, 0xa6, 0x9d, 0x93, 0x71, 0xb2, 0x15, 0xe6, 0x87, 0x6b, 0xe1, 0x77,
-	0xdb, 0xfb, 0x08, 0x99, 0x5f, 0x7d, 0xff, 0xb5, 0xe1, 0xd3, 0xac, 0xfe,
-	0x3b, 0x22, 0x23, 0x4e, 0x1f, 0xea, 0x4c, 0x7b, 0x0d, 0x03, 0x2a, 0x7d,
-	0xd3, 0x00, 0xcf, 0xca, 0x4d, 0x2c, 0xf9, 0xfb, 0x01, 0xf3, 0xba, 0xb0,
-	0xa0, 0xe7, 0x94, 0xfb, 0xb0, 0xa6, 0x41, 0x8b, 0x9a, 0xb6, 0x34, 0xfd,
-	0x1f, 0x98, 0xd3, 0x91, 0xd4, 0xad, 0xd4, 0x93, 0xa1, 0x8e, 0x4c, 0xc6,
-	0xfb, 0x78, 0x7f, 0x84, 0xa6, 0x71, 0x7b, 0x97, 0xc4, 0xd4, 0x39, 0xad,
-	0xdf, 0x47, 0x52, 0xbc, 0x5f, 0x66, 0x99, 0xb2, 0xa3, 0x55, 0x65, 0xf5,
-	0xb8, 0x3d, 0xf9, 0x43, 0xcc, 0xcd, 0x17, 0x61, 0x6f, 0xf6, 0x8e, 0xbd,
-	0x0a, 0x9f, 0x31, 0x2e, 0x5f, 0x2a, 0xbd, 0x04, 0x7a, 0xcd, 0xaf, 0xb5,
-	0x77, 0xe1, 0x65, 0x01, 0x37, 0xcf, 0x38, 0xeb, 0xfd, 0xc3, 0x91, 0x3f,
-	0x02, 0x5d, 0xfc, 0xc1, 0x4b, 0xec, 0x03, 0xb0, 0x44, 0x60, 0xcf, 0xc3,
-	0x36, 0x18, 0x7f, 0x49, 0xef, 0x95, 0xbb, 0xbe, 0xfc, 0x92, 0x8e, 0x53,
-	0xf4, 0x97, 0x5b, 0x65, 0x7b, 0xb9, 0x41, 0x76, 0x40, 0x2f, 0xec, 0x28,
-	0xfb, 0x78, 0xa2, 0x72, 0x63, 0xd9, 0xcc, 0xd3, 0x47, 0xca, 0x9c, 0xef,
-	0x6d, 0x32, 0x71, 0xbc, 0x9a, 0x66, 0xa7, 0xed, 0xde, 0x31, 0xd2, 0x0f,
-	0x9e, 0x52, 0x32, 0x3f, 0xad, 0xc7, 0xce, 0x5d, 0xac, 0xc9, 0xc3, 0xb3,
-	0xc2, 0xbd, 0xf8, 0xfc, 0x1b, 0x74, 0xdf, 0x68, 0xe5, 0x19, 0x77, 0xde,
-	0x8f, 0xd8, 0x5f, 0x09, 0xf7, 0x86, 0xbf, 0xfe, 0x19, 0x10, 0xfd, 0x77,
-	0x5d, 0xf4, 0xde, 0x70, 0x4d, 0x7b, 0xd2, 0x76, 0x26, 0xa6, 0x75, 0x84,
-	0xa1, 0xf1, 0xf9, 0xbf, 0xe7, 0x22, 0xf2, 0x7f, 0x01, 0x95, 0xf6, 0x2d,
-	0x58, 0xd0, 0x73, 0x00, 0x00, 0x00 };
-static u32 bnx2_CP_b09FwData[(0x50/4) + 1] = {
-	0x00010030, 0x00000030, 0x00000000, 0x00000001, 0x00010fd0, 0x00000fd0,
-	0x00001430, 0x0000007f, 0x00030400, 0x00001000, 0x00000030, 0x00000020,
-	0x00050200, 0x00001000, 0x00000030, 0x00000010, 0x00010400, 0x00000400,
-	0x00001030, 0x00000020, 0x00000000 };
-static u32 bnx2_CP_b09FwRodata[(0x118/4) + 1] = {
-	0x080005d8, 0x080007f8, 0x0800073c, 0x08000764, 0x0800078c, 0x080007b4,
-	0x08000610, 0x080005fc, 0x08000820, 0x08000820, 0x0800062c, 0x08000648,
-	0x08000648, 0x08000820, 0x08000660, 0x08000674, 0x08000820, 0x08000688,
-	0x08000820, 0x08000820, 0x0800069c, 0x08000820, 0x08000820, 0x08000820,
-	0x08000820, 0x08000820, 0x08000820, 0x08000820, 0x08000820, 0x08000820,
-	0x08000820, 0x080006b0, 0x08000820, 0x080006c4, 0x080006d8, 0x080006ec,
-	0x08000820, 0x08000700, 0x08000714, 0x08000728, 0x08003740, 0x08003758,
-	0x08003768, 0x08003778, 0x08003790, 0x080037a8, 0x080037b8, 0x080037c8,
-	0x080037e8, 0x080037f8, 0x08003808, 0x08003898, 0x080037d8, 0x08003818,
-	0x08003828, 0x08003840, 0x08003860, 0x08003898, 0x08003878, 0x08003878,
-	0x080055f0, 0x080055f0, 0x080055f0, 0x080055f0, 0x080055f0, 0x08005618,
-	0x08005618, 0x08005640, 0x08005690, 0x08005660, 0x00000000 };
-static u32 bnx2_CP_b09FwBss[(0x870/4) + 1] = { 0x0 };
-static u32 bnx2_CP_b09FwSbss[(0xe9/4) + 1] = { 0x0 };
+	0x1f, 0x8b, 0x08, 0x00, 0x0f, 0x34, 0xe7, 0x45, 0x00, 0x03, 0xbd, 0x7d,
+	0x0d, 0x74, 0x5c, 0x57, 0x7d, 0xe7, 0xff, 0xdd, 0x19, 0x49, 0x63, 0x59,
+	0x96, 0x9f, 0xe5, 0x89, 0x32, 0x51, 0x84, 0x3d, 0x23, 0x3d, 0xd9, 0x22,
+	0x12, 0xe1, 0xc5, 0x11, 0xac, 0xda, 0x2a, 0xe9, 0x30, 0x92, 0x3f, 0x12,
+	0x02, 0xab, 0x10, 0x43, 0xb3, 0x1c, 0x4a, 0xc5, 0x48, 0x4e, 0x02, 0x04,
+	0xea, 0x40, 0xe8, 0x86, 0xdd, 0xec, 0x66, 0x32, 0x92, 0x3f, 0x9a, 0x8e,
+	0x3d, 0x93, 0x44, 0x89, 0xbd, 0xdd, 0x9c, 0xad, 0x90, 0x14, 0x3b, 0x74,
+	0x07, 0x4f, 0xe2, 0x98, 0x96, 0x73, 0x0a, 0x8d, 0x50, 0x8c, 0x9b, 0xe6,
+	0xb0, 0xdd, 0xd0, 0xa6, 0x34, 0xdb, 0x86, 0x22, 0x8c, 0x81, 0xf4, 0x2c,
+	0xdd, 0x86, 0x42, 0x77, 0xd3, 0x36, 0xe5, 0xed, 0xef, 0x77, 0xef, 0x7d,
+	0x9a, 0x91, 0x34, 0xce, 0x07, 0xdd, 0xad, 0xcf, 0x79, 0x7e, 0xf3, 0xee,
+	0xbb, 0x1f, 0xff, 0xfb, 0xbf, 0xff, 0xef, 0xfb, 0xbf, 0x4f, 0x97, 0x8b,
+	0x34, 0x8b, 0xfd, 0xb7, 0x01, 0xd7, 0xd5, 0xc9, 0xfd, 0xe3, 0x57, 0x5f,
+	0x39, 0x70, 0x25, 0x9f, 0xa3, 0x91, 0x68, 0x44, 0xde, 0xc4, 0xbf, 0xe4,
+	0x1b, 0xa8, 0x83, 0x0e, 0xdd, 0x70, 0x2c, 0x5e, 0x12, 0x53, 0x43, 0xde,
+	0xfe, 0x8c, 0x27, 0xb1, 0xc8, 0x50, 0xee, 0xce, 0x71, 0x4f, 0x24, 0x5d,
+	0xee, 0x4b, 0x0e, 0xcb, 0x3f, 0x05, 0xb9, 0x78, 0x54, 0x58, 0xfe, 0x96,
+	0xa1, 0x57, 0x7f, 0xeb, 0x2b, 0xff, 0x2a, 0xf5, 0xf2, 0x4c, 0x44, 0x62,
+	0xee, 0xd0, 0xed, 0xe2, 0x6e, 0x93, 0x58, 0xe7, 0x50, 0x72, 0xff, 0x23,
+	0xdb, 0x97, 0x44, 0x5a, 0xc3, 0xbe, 0x5e, 0x0a, 0xbe, 0xb2, 0x5d, 0x72,
+	0x1d, 0x43, 0x89, 0xb1, 0x86, 0x21, 0x57, 0x9e, 0xaa, 0xc8, 0xe8, 0x89,
+	0xc2, 0xcb, 0x41, 0x74, 0x28, 0x88, 0x4c, 0x0d, 0x38, 0x12, 0x19, 0x92,
+	0xb3, 0xe3, 0x03, 0xf7, 0x04, 0xca, 0xf3, 0xfc, 0x45, 0x69, 0x19, 0x3c,
+	0x37, 0x80, 0xf7, 0x65, 0x41, 0xdd, 0xbd, 0xd7, 0x9c, 0x28, 0xc4, 0x44,
+	0x0d, 0xf5, 0xbc, 0x90, 0x89, 0x5c, 0x25, 0x7c, 0x7f, 0x56, 0x7a, 0xfc,
+	0xa7, 0x05, 0xe5, 0xe5, 0x98, 0x64, 0x2a, 0xd2, 0x82, 0x32, 0xdc, 0x9b,
+	0x51, 0x27, 0xe5, 0x66, 0x22, 0xae, 0xe4, 0x2b, 0x3f, 0x5e, 0x67, 0xc6,
+	0x9d, 0xb3, 0xf7, 0xbf, 0x8e, 0x99, 0x3b, 0xc6, 0x2d, 0xc6, 0x64, 0x29,
+	0x92, 0x10, 0xc0, 0x82, 0x79, 0x25, 0x64, 0xb2, 0x98, 0x94, 0x4c, 0x81,
+	0xb0, 0x45, 0x25, 0xeb, 0x12, 0xae, 0x04, 0xda, 0xb7, 0x39, 0xf5, 0xeb,
+	0xb3, 0xee, 0x0b, 0xa8, 0x9b, 0x44, 0xbd, 0x4e, 0x79, 0x12, 0x75, 0x4f,
+	0x57, 0xe2, 0xf2, 0x44, 0xe5, 0x57, 0x25, 0x8d, 0xb6, 0x8f, 0x57, 0x30,
+	0x76, 0xb1, 0x51, 0x86, 0xa7, 0x9b, 0x25, 0x33, 0xdd, 0x9d, 0xc8, 0x4a,
+	0x10, 0x7c, 0xda, 0xff, 0xa8, 0x8c, 0xb5, 0xa1, 0x7e, 0x91, 0xef, 0x12,
+	0x2b, 0xde, 0x65, 0xfd, 0x3e, 0x37, 0xab, 0x1c, 0x49, 0xef, 0x4d, 0x25,
+	0xc6, 0x14, 0x9f, 0x1b, 0x24, 0xd3, 0x8f, 0xe7, 0xd1, 0xa8, 0x44, 0xbc,
+	0x20, 0xb8, 0xc3, 0xbf, 0x0c, 0x70, 0xa4, 0x92, 0x49, 0xc5, 0xb6, 0x6c,
+	0x97, 0xca, 0x25, 0x55, 0x5c, 0x72, 0x95, 0x2b, 0x25, 0xd9, 0x16, 0x04,
+	0xef, 0xf3, 0x3b, 0x51, 0x2e, 0x32, 0x5c, 0x90, 0xfd, 0x58, 0x23, 0xf4,
+	0x29, 0xbe, 0x1a, 0xda, 0x8c, 0x79, 0xf4, 0xb9, 0xc3, 0xd2, 0x28, 0xe9,
+	0xb8, 0xa4, 0xd5, 0x90, 0x24, 0xd5, 0xd0, 0x3a, 0x94, 0x39, 0xd2, 0xe0,
+	0x7d, 0xc1, 0xd2, 0xd2, 0x46, 0x3c, 0xcb, 0xa8, 0x1a, 0x6a, 0x5b, 0x55,
+	0x9e, 0x4a, 0x8a, 0x5a, 0x07, 0x5c, 0xa5, 0x7a, 0xd3, 0x8a, 0x65, 0xb8,
+	0xeb, 0xb2, 0x0f, 0x36, 0xad, 0x2d, 0xdb, 0xef, 0xac, 0x2c, 0xbb, 0xbd,
+	0x85, 0xb0, 0x8a, 0xe2, 0xef, 0xb8, 0x9e, 0x6b, 0x3a, 0xde, 0xed, 0x36,
+	0x60, 0x5e, 0xa3, 0x7e, 0xca, 0xdd, 0xa9, 0x9e, 0x0f, 0xa4, 0x9d, 0x30,
+	0xf3, 0x9d, 0xc2, 0x3b, 0x54, 0x1d, 0xf2, 0xb1, 0x6e, 0xae, 0x1c, 0xc2,
+	0xdc, 0xce, 0x4f, 0xa7, 0xdc, 0x2e, 0x85, 0xfb, 0x3c, 0x7f, 0x07, 0x41,
+	0xc6, 0xcf, 0xe9, 0x35, 0xfd, 0xee, 0x74, 0x02, 0xcf, 0x80, 0x3f, 0x9e,
+	0x4e, 0x6d, 0x92, 0xab, 0xed, 0xba, 0x7c, 0x13, 0x63, 0x76, 0xbb, 0x77,
+	0xa8, 0x6e, 0xd7, 0x57, 0x29, 0x77, 0x56, 0xce, 0xe0, 0x39, 0x08, 0x6e,
+	0xf4, 0x53, 0x89, 0x1c, 0xd6, 0xec, 0x42, 0x21, 0x2e, 0xdf, 0x2b, 0xa4,
+	0x40, 0xc5, 0xa9, 0xde, 0x39, 0xe9, 0xf3, 0xe7, 0x00, 0x6f, 0x1e, 0xd7,
+	0x41, 0xbe, 0x2b, 0xe3, 0x5d, 0x99, 0x6d, 0x83, 0xe0, 0x26, 0xff, 0x37,
+	0x83, 0xb1, 0x76, 0xc3, 0x17, 0x4f, 0x15, 0xb1, 0x9e, 0x80, 0xf9, 0x74,
+	0x11, 0xeb, 0x89, 0xb5, 0x7a, 0x5c, 0xaf, 0x7b, 0x2f, 0xd6, 0x9d, 0xb4,
+	0x41, 0xba, 0xd8, 0x61, 0x69, 0xf9, 0x03, 0xf6, 0x2e, 0x92, 0x29, 0x3a,
+	0x92, 0xf1, 0xff, 0x31, 0x48, 0x6b, 0x7e, 0x11, 0x67, 0xb8, 0x48, 0x5a,
+	0x6c, 0x00, 0xac, 0x7c, 0xcc, 0xda, 0x7a, 0x1b, 0x1d, 0xe0, 0x96, 0xeb,
+	0xc0, 0xf7, 0x31, 0xe5, 0x35, 0xd9, 0xf7, 0x21, 0x5f, 0xf0, 0xdf, 0x26,
+	0x47, 0xbc, 0x6a, 0xbd, 0x0c, 0x69, 0xb2, 0x92, 0x93, 0xec, 0x83, 0x81,
+	0x0c, 0xfb, 0xc0, 0x13, 0xfb, 0x74, 0x7d, 0xd1, 0x6d, 0x5d, 0xd6, 0xd1,
+	0x75, 0xf1, 0x6f, 0x7d, 0x23, 0xc6, 0x70, 0x46, 0x8a, 0xd5, 0xb6, 0x23,
+	0xc5, 0xfc, 0x66, 0x0b, 0x1f, 0x9e, 0x07, 0x9d, 0x4c, 0xe5, 0x82, 0x5d,
+	0xdb, 0x70, 0x1e, 0x57, 0xd7, 0xa1, 0x6d, 0x17, 0x7c, 0xe0, 0x4a, 0xb6,
+	0x30, 0x88, 0x71, 0xe3, 0xb8, 0x07, 0xc1, 0x94, 0x9f, 0x4e, 0x45, 0x65,
+	0x08, 0xcf, 0xa3, 0xe4, 0x3d, 0xe0, 0x4f, 0xa2, 0x99, 0xed, 0xbe, 0x8c,
+	0x80, 0xee, 0xf3, 0x95, 0xd7, 0x97, 0x22, 0x7a, 0x0e, 0xfe, 0x3f, 0x59,
+	0xdc, 0x70, 0x1c, 0x33, 0xe6, 0x54, 0xb1, 0x43, 0xf2, 0xd3, 0x9e, 0x4c,
+	0x16, 0x16, 0x7a, 0x95, 0xbc, 0x4c, 0x7e, 0xc7, 0xfa, 0xa5, 0x40, 0xbb,
+	0x43, 0x32, 0x5c, 0xf1, 0x24, 0x5f, 0xc0, 0xbd, 0xd8, 0x0d, 0xfa, 0x8d,
+	0x4a, 0x3a, 0x61, 0xd6, 0x26, 0x5f, 0x18, 0xc1, 0xfc, 0x80, 0x6b, 0x8f,
+	0xbf, 0x07, 0x2d, 0x4c, 0xae, 0x64, 0x06, 0x48, 0x3f, 0x6f, 0x06, 0x96,
+	0x98, 0xcc, 0xfa, 0xe0, 0x0b, 0xd7, 0xc0, 0x92, 0x2f, 0xc6, 0xa2, 0xc3,
+	0x98, 0xf7, 0x70, 0xf9, 0x57, 0xd0, 0x7f, 0x8b, 0xfe, 0x0d, 0x7e, 0xb2,
+	0x65, 0x51, 0xdc, 0xe3, 0xb8, 0x13, 0xe6, 0x90, 0x56, 0x21, 0x1b, 0xa6,
+	0x3b, 0x65, 0x12, 0xb4, 0x3a, 0x2c, 0xf8, 0x3d, 0xcf, 0xb9, 0x10, 0xae,
+	0x0e, 0xfd, 0x7b, 0x72, 0x7a, 0x8b, 0x7e, 0xce, 0x8e, 0x76, 0x48, 0x6e,
+	0x3e, 0x9c, 0x33, 0xe5, 0x05, 0x65, 0x44, 0xea, 0xb0, 0x08, 0x65, 0x46,
+	0x10, 0x3c, 0xe8, 0x53, 0x6e, 0x04, 0xc1, 0x69, 0x9f, 0x72, 0xe4, 0x0c,
+	0xe4, 0x03, 0x65, 0x07, 0x79, 0xd9, 0x53, 0x5c, 0xab, 0x4c, 0xa1, 0x17,
+	0xeb, 0xd1, 0x28, 0xd9, 0xfe, 0xe3, 0x84, 0x15, 0x72, 0xe7, 0xa5, 0x4f,
+	0x66, 0xbc, 0x5c, 0x22, 0xa2, 0xf1, 0x04, 0xca, 0x82, 0x3c, 0x4c, 0xeb,
+	0x99, 0x75, 0x49, 0xbe, 0xbf, 0x64, 0xeb, 0xc8, 0xaf, 0xb2, 0x4e, 0x74,
+	0x4d, 0x9d, 0x7f, 0xa7, 0x0c, 0x5f, 0xf6, 0x62, 0xdd, 0x3a, 0x14, 0xf1,
+	0xd8, 0xb5, 0x8d, 0xcf, 0x12, 0x6b, 0x18, 0xfa, 0x3d, 0xbc, 0x7b, 0xee,
+	0x53, 0x8f, 0x7a, 0xf5, 0xde, 0xfd, 0x28, 0xba, 0xf6, 0xdd, 0x94, 0x44,
+	0xbd, 0x54, 0xef, 0x8d, 0xea, 0x4f, 0x1a, 0xa4, 0x35, 0x08, 0x1e, 0xf5,
+	0xc3, 0xf2, 0xc6, 0x86, 0xb5, 0x63, 0x5c, 0x55, 0xa7, 0xec, 0x68, 0x9d,
+	0xb2, 0xcf, 0xd7, 0x29, 0x7b, 0x7b, 0xe3, 0xda, 0xb2, 0xdb, 0xeb, 0x94,
+	0xcd, 0xd6, 0x29, 0xfb, 0x69, 0x9d, 0x32, 0x69, 0x5a, 0x5b, 0x16, 0xa9,
+	0x53, 0xd6, 0x57, 0xa7, 0x2c, 0x0a, 0xbe, 0xdb, 0x26, 0xf9, 0xf8, 0xbd,
+	0x9c, 0xbb, 0xc5, 0x4d, 0x29, 0xb2, 0x16, 0x37, 0x0d, 0xa8, 0xd7, 0xb9,
+	0xaa, 0xde, 0x17, 0xeb, 0xd4, 0x6b, 0x44, 0xbd, 0xb6, 0x55, 0xf5, 0x76,
+	0xd4, 0xc1, 0x75, 0x13, 0xea, 0xc5, 0x56, 0xd5, 0x7b, 0xb0, 0x4e, 0x3d,
+	0x96, 0x7f, 0xc6, 0x8e, 0xd3, 0x07, 0x2d, 0xf4, 0x5a, 0xeb, 0xd5, 0x28,
+	0xd2, 0xce, 0xf2, 0x5e, 0xe8, 0x90, 0x0e, 0x65, 0xe4, 0x02, 0x65, 0x10,
+	0xcb, 0x3a, 0x41, 0xe7, 0x71, 0xd0, 0x1d, 0xe5, 0x28, 0xf8, 0x8c, 0x73,
+	0xa9, 0x6c, 0x90, 0xb1, 0x78, 0x9f, 0x7b, 0xb5, 0x6a, 0x01, 0x8d, 0xa5,
+	0xdc, 0xa4, 0x22, 0xff, 0x49, 0x2e, 0x32, 0xe4, 0xe5, 0x86, 0x45, 0xc5,
+	0x95, 0x04, 0x32, 0xe2, 0xab, 0x36, 0x25, 0xf7, 0x80, 0xbf, 0xd2, 0xd0,
+	0x59, 0x37, 0x06, 0xc3, 0x9a, 0xb7, 0x4c, 0xdd, 0x8b, 0xcb, 0x54, 0x5f,
+	0x0e, 0x52, 0x16, 0x0e, 0x8d, 0x7e, 0x2a, 0xe3, 0x2d, 0x0c, 0x36, 0x82,
+	0x66, 0xcf, 0xa3, 0xcd, 0x6e, 0xb4, 0xdc, 0x57, 0x8e, 0xca, 0x48, 0x79,
+	0x00, 0xbc, 0xe0, 0xc8, 0x39, 0x6f, 0xa3, 0x9c, 0xf3, 0x51, 0xb7, 0x12,
+	0x91, 0xc5, 0xb8, 0x23, 0x8b, 0x78, 0xce, 0xf8, 0x78, 0x57, 0x09, 0x79,
+	0x6b, 0x40, 0x0e, 0x14, 0x7d, 0x39, 0x5c, 0xbc, 0x41, 0x85, 0x7a, 0x6d,
+	0xa7, 0xbf, 0x5e, 0x1e, 0x73, 0x4d, 0xdf, 0xbb, 0xbd, 0x05, 0x68, 0xd4,
+	0xa8, 0x9c, 0xf7, 0x52, 0x89, 0x45, 0xcd, 0x13, 0xff, 0x27, 0x18, 0x41,
+	0x3f, 0xb3, 0x5e, 0xca, 0xfd, 0x03, 0x3c, 0x8f, 0x95, 0x69, 0xcb, 0x54,
+	0xfb, 0x9a, 0x44, 0x5f, 0x87, 0x8a, 0x1b, 0xe4, 0x56, 0xdb, 0x7e, 0x97,
+	0xb7, 0xd0, 0x0b, 0x9e, 0x73, 0x4f, 0x50, 0x86, 0x14, 0x00, 0xd7, 0x5e,
+	0xf0, 0x36, 0xda, 0x7e, 0x4d, 0xcb, 0x33, 0xd8, 0x3e, 0x85, 0x8d, 0x90,
+	0xcf, 0x7f, 0x17, 0xdc, 0x1a, 0x67, 0x7d, 0x96, 0x51, 0xe7, 0x48, 0x49,
+	0x0d, 0x41, 0x26, 0x0c, 0x50, 0x66, 0x26, 0x21, 0x2f, 0x21, 0x7b, 0x8a,
+	0x3f, 0x0d, 0xd2, 0xd1, 0x5a, 0x39, 0x28, 0xb9, 0x6a, 0x1d, 0x96, 0x25,
+	0x8d, 0x5c, 0x2d, 0x2e, 0x2d, 0xcb, 0x8a, 0x1c, 0xe4, 0xcb, 0x53, 0x15,
+	0xca, 0x85, 0x0f, 0x82, 0x47, 0x3b, 0x65, 0xa4, 0x90, 0xca, 0xa5, 0x65,
+	0x1b, 0xd6, 0xef, 0xd7, 0xb1, 0xa6, 0x51, 0x5c, 0x0f, 0xad, 0x97, 0x56,
+	0x1f, 0xba, 0x9b, 0xe5, 0xe8, 0xb4, 0x9d, 0x36, 0xd2, 0x6f, 0x03, 0x0f,
+	0x93, 0x5c, 0xf3, 0x44, 0x26, 0xe2, 0x8c, 0xd2, 0x5e, 0x19, 0x85, 0x7c,
+	0xcc, 0x96, 0xd9, 0x37, 0xe1, 0x4d, 0xd8, 0xdf, 0xb0, 0x9b, 0x0a, 0x9d,
+	0xf6, 0x77, 0x0b, 0x7e, 0x27, 0xed, 0x6f, 0xc8, 0xd4, 0x82, 0x67, 0x7f,
+	0xc7, 0xb5, 0x1c, 0x32, 0xbf, 0x13, 0xf8, 0xdd, 0xaf, 0x7f, 0x4f, 0x15,
+	0x77, 0xed, 0x52, 0xde, 0x95, 0x92, 0x9d, 0xef, 0x94, 0x03, 0x85, 0x77,
+	0x58, 0xd9, 0x82, 0x4b, 0xbe, 0xe4, 0x98, 0x79, 0x26, 0xf4, 0xba, 0xe7,
+	0x8b, 0x39, 0x67, 0x94, 0xf0, 0xe3, 0xf7, 0x70, 0xa1, 0xcf, 0xdd, 0x24,
+	0xa4, 0x81, 0x29, 0x67, 0xb8, 0xe2, 0xa4, 0x23, 0x43, 0x3d, 0x89, 0x49,
+	0x39, 0x8c, 0xdf, 0xe2, 0x46, 0x86, 0xbe, 0x84, 0xbb, 0xc1, 0xc1, 0x57,
+	0xb6, 0x43, 0xb6, 0x16, 0x29, 0x2f, 0x3d, 0xcc, 0x3d, 0x29, 0x67, 0x56,
+	0xd8, 0x58, 0xc4, 0x85, 0x92, 0xec, 0x74, 0xea, 0x78, 0x4e, 0x52, 0xb9,
+	0x19, 0x30, 0xc4, 0x8d, 0x7e, 0x54, 0xde, 0xe7, 0x83, 0x76, 0xaf, 0x74,
+	0x64, 0xd7, 0x95, 0x51, 0xd8, 0x44, 0xde, 0xcc, 0x2e, 0xc8, 0x58, 0xc8,
+	0xbe, 0x08, 0xe9, 0x41, 0x9d, 0x92, 0xb1, 0xe8, 0x10, 0xb0, 0x7d, 0xaa,
+	0x7f, 0x64, 0xb2, 0x90, 0xbd, 0x5d, 0x0d, 0xed, 0xff, 0x6c, 0x66, 0xe0,
+	0xad, 0x92, 0xdd, 0xab, 0x80, 0xa3, 0xf6, 0x31, 0xc8, 0x4c, 0xcc, 0x2b,
+	0x08, 0x40, 0xcf, 0x90, 0xe7, 0x37, 0xdd, 0x14, 0x19, 0x6a, 0x90, 0xe1,
+	0xbd, 0xed, 0x68, 0xc3, 0x77, 0xc4, 0xd7, 0x79, 0xe0, 0x33, 0x95, 0x1c,
+	0x11, 0xb9, 0x7b, 0x6a, 0x60, 0xc9, 0x99, 0x2c, 0x7d, 0x10, 0x3c, 0x79,
+	0x15, 0xda, 0x3f, 0x80, 0xf6, 0x2f, 0x3b, 0xf9, 0xe9, 0x57, 0x9c, 0xc9,
+	0xe9, 0xbf, 0x75, 0xa6, 0xa6, 0xb7, 0x6c, 0xd9, 0x39, 0xb8, 0x65, 0xcb,
+	0xf8, 0x60, 0xd4, 0xea, 0x97, 0x2d, 0x5b, 0xa6, 0x06, 0x07, 0x81, 0x83,
+	0x3e, 0x77, 0x44, 0x3c, 0x77, 0x97, 0x80, 0x7f, 0xe2, 0x1c, 0x93, 0xfa,
+	0x27, 0x85, 0xf7, 0x6c, 0xef, 0xe9, 0xf7, 0xc3, 0xd2, 0x97, 0x68, 0x13,
+	0x8e, 0x1f, 0xb1, 0x75, 0xda, 0x01, 0xfb, 0x03, 0x76, 0x7d, 0x0b, 0xaa,
+	0xc1, 0x63, 0x39, 0xe7, 0xc2, 0x72, 0xae, 0xed, 0x8f, 0xac, 0x2d, 0xbb,
+	0x11, 0xe5, 0x7c, 0x26, 0xce, 0x88, 0x17, 0xda, 0x22, 0x0d, 0xda, 0x76,
+	0xcc, 0x16, 0x48, 0x33, 0x51, 0x99, 0x28, 0xb4, 0xa1, 0x0d, 0xe8, 0xe2,
+	0x94, 0xbd, 0x8e, 0x02, 0xb6, 0xbd, 0xe8, 0xeb, 0xe8, 0x21, 0xb4, 0xa3,
+	0xcc, 0x48, 0xf5, 0x8a, 0xfa, 0x04, 0xea, 0xf4, 0xb9, 0x9b, 0x85, 0x36,
+	0xc7, 0x71, 0xc9, 0x16, 0xc9, 0xdf, 0x3d, 0x80, 0x27, 0x26, 0xc9, 0x76,
+	0x3c, 0x57, 0x0e, 0xc0, 0x0e, 0x69, 0xb0, 0x3a, 0x33, 0x94, 0x17, 0xfc,
+	0x77, 0x87, 0x12, 0xef, 0x80, 0x8c, 0xcd, 0x5d, 0x8e, 0x7a, 0x0e, 0xf0,
+	0x42, 0x3b, 0x05, 0x36, 0xcb, 0x5c, 0x5a, 0x32, 0xdb, 0xee, 0xc5, 0xdd,
+	0xc5, 0x73, 0x1e, 0xf7, 0xb7, 0xe0, 0x3e, 0x89, 0x7b, 0x08, 0x27, 0xf0,
+	0xea, 0x47, 0xac, 0xce, 0xba, 0x06, 0x63, 0xff, 0x6b, 0xc9, 0x94, 0x12,
+	0xb4, 0x39, 0x36, 0x66, 0xbc, 0xb4, 0xab, 0x44, 0x6d, 0x56, 0x32, 0x85,
+	0xfa, 0xf0, 0x09, 0xbc, 0x83, 0x32, 0x7e, 0x12, 0xbf, 0x1f, 0xa4, 0x4d,
+	0x3c, 0x25, 0xe3, 0x73, 0x1c, 0xa7, 0x00, 0x98, 0x4a, 0x92, 0x3d, 0xf9,
+	0x00, 0xae, 0x69, 0x5c, 0x0f, 0xe3, 0xe2, 0xdc, 0xd8, 0xff, 0xe2, 0x26,
+	0x05, 0x5c, 0xf3, 0x39, 0x4b, 0x3a, 0xae, 0xe0, 0x37, 0x69, 0xb8, 0x42,
+	0xdb, 0x06, 0xf4, 0x5b, 0x09, 0xe9, 0xda, 0xb7, 0xbf, 0x13, 0x9a, 0xaf,
+	0x73, 0x6d, 0xa0, 0x99, 0xca, 0xa0, 0x96, 0x39, 0x19, 0x0f, 0xf7, 0x0a,
+	0x6c, 0x8f, 0x36, 0xce, 0xd1, 0xb3, 0x65, 0x9e, 0x2e, 0x4b, 0xea, 0xb2,
+	0x7e, 0x5b, 0x86, 0x7b, 0xa5, 0x41, 0xc6, 0xda, 0x01, 0x31, 0xe5, 0xb3,
+	0x84, 0xf8, 0xa4, 0x0c, 0x00, 0xfd, 0xc2, 0x66, 0x38, 0x73, 0x51, 0xf9,
+	0xb7, 0xa4, 0x6d, 0xb1, 0xc7, 0x2b, 0xa4, 0x63, 0xd2, 0x76, 0x10, 0xdc,
+	0xef, 0x37, 0xa1, 0x7f, 0xf2, 0xbc, 0x48, 0xc3, 0xd1, 0xa8, 0xcc, 0xb8,
+	0xa4, 0x85, 0x77, 0xb4, 0x90, 0x06, 0x1a, 0x3d, 0xd2, 0x70, 0x2d, 0x7f,
+	0x71, 0x0d, 0xd9, 0x5f, 0x0e, 0xf6, 0x1d, 0xed, 0xbc, 0x1e, 0xd8, 0xce,
+	0x1c, 0xe3, 0x30, 0x9f, 0x5d, 0x05, 0x9e, 0xca, 0x2c, 0xf3, 0x94, 0xc8,
+	0x6c, 0x81, 0xb8, 0x09, 0xed, 0x3f, 0xae, 0x33, 0xf1, 0xf3, 0x38, 0xe6,
+	0xcc, 0xfb, 0x19, 0x8b, 0xa7, 0x2f, 0x59, 0x3c, 0x7d, 0xd9, 0xde, 0x5d,
+	0x27, 0xab, 0x6d, 0xc1, 0x05, 0x3c, 0x73, 0x7d, 0xa2, 0x1a, 0x67, 0xd9,
+	0xc2, 0x0c, 0xee, 0xa8, 0x5b, 0x7c, 0x5c, 0xc6, 0xb5, 0x9d, 0x16, 0x91,
+	0x77, 0x69, 0xd9, 0x06, 0x21, 0xdd, 0x5c, 0x00, 0xcc, 0x0d, 0x92, 0x8b,
+	0x47, 0xf4, 0xda, 0x47, 0xbd, 0x03, 0x51, 0x43, 0xab, 0xc4, 0xc9, 0x0a,
+	0x5f, 0xaa, 0x06, 0xa6, 0xb8, 0x95, 0x73, 0x84, 0x8b, 0xb4, 0xfb, 0x88,
+	0x86, 0xeb, 0x16, 0xc8, 0xbb, 0x9c, 0xa8, 0xf6, 0x46, 0xb9, 0x0c, 0xb4,
+	0xa0, 0xe2, 0xd0, 0x5c, 0xc1, 0xd3, 0xb0, 0x9b, 0xb2, 0x73, 0xb4, 0xa1,
+	0xbb, 0xe8, 0xb7, 0xc4, 0xb2, 0xfd, 0xad, 0xa4, 0x23, 0xa5, 0x60, 0x7f,
+	0xe1, 0x59, 0x65, 0xfb, 0x35, 0x9d, 0x3a, 0xca, 0x8b, 0x6b, 0x3b, 0x19,
+	0xbc, 0x12, 0xb1, 0xbe, 0x73, 0x54, 0x79, 0x9b, 0x57, 0x97, 0x25, 0xa9,
+	0x87, 0xd1, 0x2e, 0x99, 0xed, 0x6f, 0x27, 0x8f, 0xb9, 0xca, 0x03, 0x2e,
+	0x3d, 0xed, 0x1b, 0xe5, 0xd4, 0xc0, 0xc6, 0x55, 0xf5, 0xf5, 0xdd, 0xb1,
+	0xcf, 0x51, 0x7b, 0x77, 0xed, 0x3d, 0x69, 0xef, 0xb9, 0xe8, 0x00, 0xef,
+	0x8e, 0x44, 0x87, 0x78, 0xc7, 0x1a, 0x0e, 0xb1, 0x0f, 0xcd, 0x57, 0x56,
+	0xce, 0xf4, 0xb8, 0x79, 0x21, 0x5f, 0xfd, 0xa9, 0xdc, 0x32, 0x67, 0xe4,
+	0xef, 0x2e, 0xc8, 0x20, 0xf8, 0x6f, 0xee, 0xa2, 0x00, 0xfe, 0xbd, 0x65,
+	0xb9, 0xa5, 0x42, 0xbc, 0xfd, 0x06, 0xf0, 0xb7, 0x35, 0x4a, 0xde, 0x74,
+	0x85, 0x72, 0xf7, 0x4e, 0xd1, 0xf6, 0x69, 0x81, 0x38, 0x3f, 0x2b, 0x5c,
+	0x9b, 0x7c, 0xe1, 0x19, 0xbd, 0x36, 0x07, 0x0b, 0x8b, 0xc0, 0xcf, 0xd7,
+	0x41, 0xf7, 0x41, 0xb0, 0xe8, 0xe7, 0x41, 0x39, 0x7f, 0x84, 0xdf, 0xe8,
+	0xbb, 0xf0, 0x1c, 0xde, 0xb7, 0x4a, 0xbe, 0x44, 0x9e, 0x8b, 0x5a, 0x1e,
+	0x3e, 0x05, 0x7e, 0xba, 0x0c, 0xfd, 0xa2, 0x6c, 0x80, 0xbf, 0xff, 0x11,
+	0xef, 0x70, 0x9f, 0xc3, 0x22, 0xb6, 0xd3, 0xd6, 0xe1, 0xd8, 0x5c, 0x3b,
+	0xae, 0x59, 0x5c, 0xfb, 0xad, 0x8f, 0x2f, 0xaf, 0x1b, 0xd7, 0x2b, 0xd5,
+	0x9b, 0x93, 0x70, 0xcd, 0x44, 0x1e, 0x2f, 0xb0, 0x3e, 0xe9, 0xff, 0x1f,
+	0x62, 0x46, 0x17, 0xfc, 0xc9, 0x3a, 0x73, 0x5f, 0xdd, 0x96, 0x6b, 0x5e,
+	0x4b, 0x83, 0xf4, 0x6f, 0x52, 0x83, 0x39, 0xc8, 0x9d, 0xa8, 0xd7, 0x2a,
+	0x23, 0xda, 0x27, 0x22, 0x4d, 0x90, 0x06, 0x6e, 0x56, 0x86, 0x36, 0x3f,
+	0xa4, 0x0c, 0x6d, 0x3e, 0x03, 0x5a, 0xc4, 0x55, 0x5c, 0x72, 0x0c, 0x6d,
+	0x7e, 0x1d, 0x77, 0x5c, 0xc5, 0x0b, 0x4e, 0xc8, 0xc7, 0xc3, 0xf0, 0xf9,
+	0x76, 0x15, 0xa2, 0xce, 0x78, 0x05, 0xf4, 0x5b, 0x8c, 0xa1, 0x7c, 0x81,
+	0x38, 0xc7, 0xfc, 0x39, 0xce, 0x56, 0xdb, 0xff, 0xe3, 0x32, 0x51, 0x0c,
+	0xb4, 0x5d, 0x95, 0x9d, 0xbb, 0x17, 0xf7, 0xf5, 0x5a, 0xce, 0x28, 0x2f,
+	0xad, 0x8c, 0xbc, 0x7a, 0x17, 0xee, 0xdd, 0x89, 0x83, 0xd2, 0xed, 0x46,
+	0xe4, 0x39, 0xf4, 0xf5, 0x43, 0x67, 0xa2, 0xf2, 0x32, 0xae, 0x9f, 0xe0,
+	0x7a, 0x15, 0xd7, 0x2b, 0xe8, 0xf7, 0x45, 0x94, 0xaf, 0x97, 0x05, 0xb7,
+	0x19, 0xf5, 0x45, 0x8d, 0x57, 0x5e, 0x70, 0xc6, 0x4e, 0xbe, 0x84, 0x2b,
+	0xaa, 0x26, 0x2a, 0xcf, 0x3b, 0xd9, 0xb9, 0x60, 0xe3, 0xa2, 0x47, 0x19,
+	0xf6, 0xa7, 0x8e, 0xe9, 0x7b, 0x08, 0x73, 0x00, 0x4d, 0x17, 0x17, 0x30,
+	0xf6, 0x33, 0x9a, 0x67, 0x46, 0x20, 0xf3, 0xb3, 0xb0, 0x4b, 0xc6, 0x34,
+	0x4c, 0x97, 0x03, 0x3e, 0xf8, 0xba, 0x03, 0xb8, 0xcf, 0x35, 0xca, 0x52,
+	0x9c, 0x76, 0xe4, 0x97, 0x75, 0xfd, 0x6c, 0xb1, 0x5b, 0xe3, 0x76, 0x66,
+	0x0d, 0xff, 0xd0, 0x3f, 0x0b, 0xe5, 0x81, 0x91, 0xc6, 0xb3, 0x05, 0xca,
+	0x02, 0xe8, 0x9f, 0xc2, 0x14, 0xee, 0x8d, 0x5a, 0x26, 0xe4, 0x25, 0x94,
+	0x07, 0x6c, 0x47, 0x99, 0x50, 0x2b, 0x77, 0x28, 0x6b, 0x28, 0x7b, 0x28,
+	0x4b, 0xcc, 0x7a, 0x8c, 0x3f, 0x48, 0x19, 0x7e, 0x2d, 0xfc, 0x53, 0xda,
+	0x1f, 0x9d, 0xc6, 0x07, 0x99, 0xce, 0x28, 0x23, 0x4f, 0xf7, 0xe8, 0xb5,
+	0x98, 0x28, 0xa8, 0x38, 0x20, 0x47, 0x19, 0xae, 0x63, 0x7b, 0x71, 0xcf,
+	0xaa, 0x09, 0x5c, 0xd9, 0x63, 0x1f, 0xc0, 0x6f, 0xae, 0xcd, 0x04, 0xea,
+	0xe1, 0x2a, 0x8e, 0xe2, 0x8e, 0x0b, 0xb6, 0x99, 0x91, 0x23, 0x5c, 0xd3,
+	0x84, 0x5d, 0xd3, 0x2f, 0x03, 0x0f, 0x9c, 0x9f, 0xd2, 0xf1, 0x07, 0xe5,
+	0xed, 0x00, 0xde, 0x2b, 0xd6, 0xdf, 0x6d, 0x15, 0xc3, 0x83, 0xb8, 0x7a,
+	0xc9, 0xcf, 0x2d, 0x66, 0xbd, 0x34, 0xed, 0x7e, 0x37, 0x6a, 0x78, 0x31,
+	0x8e, 0xb2, 0x08, 0xca, 0xda, 0x45, 0xf3, 0xfe, 0x32, 0x1e, 0xd3, 0x16,
+	0x8f, 0xfc, 0xad, 0xec, 0x6f, 0xd0, 0x13, 0x6c, 0xda, 0x8c, 0x37, 0x80,
+	0x71, 0x31, 0x97, 0x63, 0x7b, 0xd4, 0x38, 0xe4, 0xf7, 0xb8, 0x47, 0x19,
+	0xce, 0x38, 0x03, 0xe7, 0xc7, 0x7e, 0x51, 0xae, 0x71, 0xe0, 0x4b, 0xd5,
+	0x87, 0xff, 0x32, 0xd6, 0xec, 0x71, 0xd9, 0x57, 0xbc, 0x5a, 0xfb, 0xd4,
+	0x8d, 0x47, 0xcd, 0x7a, 0x88, 0x0a, 0xeb, 0xa1, 0xef, 0x38, 0x6d, 0x9b,
+	0x31, 0xfd, 0x3e, 0x7a, 0x94, 0xbf, 0x29, 0x9f, 0x6b, 0xe5, 0xbd, 0xb1,
+	0x6b, 0xf2, 0x2b, 0x64, 0x1d, 0x6d, 0x0b, 0xac, 0x59, 0xb9, 0x16, 0xef,
+	0xf4, 0xf1, 0x29, 0xf3, 0xc8, 0x4f, 0x07, 0xc1, 0x13, 0xaa, 0xc1, 0xf0,
+	0x3e, 0x7d, 0x8d, 0x7a, 0xfc, 0x04, 0xfb, 0x0b, 0xbc, 0x72, 0x02, 0xb6,
+	0xdb, 0xae, 0xe5, 0x3e, 0x20, 0x2b, 0xe3, 0x31, 0x39, 0x59, 0x68, 0x91,
+	0xb9, 0x82, 0x82, 0xc1, 0x60, 0x64, 0x67, 0x44, 0x12, 0x5a, 0xff, 0xd2,
+	0xbe, 0x1b, 0x9e, 0x8e, 0x58, 0xba, 0x83, 0xc3, 0xd2, 0xfc, 0x1b, 0xd0,
+	0xb1, 0x65, 0xe8, 0xd8, 0x56, 0xe8, 0xe0, 0xd5, 0x32, 0xa2, 0xab, 0x61,
+	0xad, 0x8c, 0x60, 0x9b, 0x14, 0xbc, 0xf2, 0x83, 0x68, 0x17, 0xd2, 0x5f,
+	0x4c, 0xd3, 0x5a, 0x56, 0x72, 0xce, 0xae, 0xca, 0x94, 0xb3, 0xbb, 0xb2,
+	0x5a, 0x07, 0xf5, 0xb9, 0x51, 0x31, 0xb0, 0x9e, 0xd4, 0x71, 0xbc, 0x94,
+	0x9f, 0x01, 0x4e, 0x76, 0x83, 0xee, 0x9e, 0x2e, 0xc1, 0x8f, 0xa7, 0x5c,
+	0x06, 0xcc, 0x8f, 0x01, 0xe6, 0xd9, 0x92, 0x13, 0xda, 0x06, 0xc2, 0xe0,
+	0xc9, 0xec, 0x74, 0xbf, 0x2c, 0xce, 0x93, 0x0e, 0x21, 0x03, 0x4a, 0x58,
+	0x4f, 0x7f, 0x1d, 0xec, 0x00, 0x8e, 0x0f, 0xb9, 0x3d, 0xdd, 0xa1, 0xdf,
+	0x19, 0x7d, 0xde, 0x29, 0x8b, 0xe5, 0xf7, 0x58, 0xd8, 0x0e, 0xd7, 0xc0,
+	0xb6, 0x6e, 0x19, 0xb6, 0xdd, 0x80, 0x6d, 0x4f, 0x5d, 0xd8, 0xea, 0xe9,
+	0xe2, 0x2e, 0xd8, 0x34, 0xe4, 0x8f, 0x10, 0xaf, 0xed, 0x96, 0x1e, 0x6e,
+	0xb7, 0xf6, 0x2e, 0x6d, 0xa2, 0x9f, 0x02, 0x1e, 0xd2, 0x18, 0x7e, 0xcf,
+	0x3d, 0x4a, 0x59, 0x86, 0x72, 0x3e, 0x7f, 0x06, 0x75, 0xf0, 0x3c, 0xf7,
+	0xe7, 0x56, 0x0e, 0xde, 0x65, 0x61, 0xa1, 0x9d, 0x90, 0x86, 0x4d, 0x3c,
+	0xe2, 0x64, 0xe6, 0x08, 0x43, 0x0e, 0xf0, 0xe2, 0x5d, 0xa5, 0xb6, 0x4f,
+	0xde, 0xd9, 0xef, 0x15, 0xb6, 0x1f, 0xf6, 0x1d, 0xce, 0x65, 0xbd, 0xd5,
+	0xf3, 0x21, 0x7d, 0x85, 0xf6, 0xf5, 0x94, 0x93, 0x5e, 0x33, 0xaf, 0x5a,
+	0x9a, 0xa3, 0xbc, 0x8d, 0xca, 0x4e, 0xd0, 0xc9, 0xce, 0x15, 0xb4, 0xa6,
+	0xdd, 0x10, 0x4b, 0xc7, 0xeb, 0xec, 0xfc, 0x0e, 0x18, 0xbe, 0xf1, 0x63,
+	0xd0, 0x87, 0x94, 0x37, 0x37, 0x1b, 0xdf, 0x5c, 0x4e, 0x00, 0xd6, 0xf0,
+	0x99, 0xb4, 0xc9, 0xdf, 0x94, 0x49, 0x55, 0x5a, 0x34, 0xbe, 0x4b, 0xa7,
+	0x8e, 0x9f, 0x56, 0xed, 0xf5, 0xa8, 0x8c, 0x9a, 0x35, 0x3f, 0xcc, 0x35,
+	0xa7, 0x2f, 0xd2, 0xfd, 0xc0, 0xa8, 0xe5, 0xaf, 0x54, 0x29, 0x27, 0xbb,
+	0xed, 0xdc, 0xbf, 0x5c, 0x67, 0xed, 0x5a, 0x97, 0xd7, 0x6e, 0xb4, 0xb2,
+	0x7a, 0x8e, 0x22, 0x5d, 0x0f, 0x44, 0xb5, 0x6f, 0x2b, 0xca, 0x97, 0x46,
+	0x8f, 0xf2, 0x93, 0xb6, 0x12, 0xca, 0x67, 0xfb, 0xdc, 0x36, 0xd0, 0xdb,
+	0x53, 0x6b, 0xec, 0xae, 0xa4, 0x95, 0x9b, 0xf4, 0x83, 0xc3, 0x31, 0x72,
+	0x56, 0x4e, 0xe6, 0xd0, 0xff, 0x94, 0xb3, 0xb3, 0x52, 0x4f, 0x5e, 0x86,
+	0x72, 0x92, 0xf3, 0xb9, 0x57, 0xee, 0x78, 0x90, 0x3c, 0x7a, 0xbb, 0xb6,
+	0xaf, 0xaf, 0xda, 0x71, 0x00, 0xf8, 0x23, 0xfc, 0x8b, 0x9b, 0x60, 0x32,
+	0x40, 0xe7, 0xa6, 0x65, 0xdc, 0xae, 0xdb, 0xf8, 0xf2, 0xfa, 0xf3, 0x6a,
+	0xc7, 0x6f, 0xc6, 0x59, 0x95, 0x85, 0x59, 0xdb, 0xb1, 0xb0, 0xeb, 0x56,
+	0xdb, 0xb2, 0x9c, 0x03, 0xed, 0xd9, 0x46, 0x63, 0x0b, 0x16, 0x69, 0x7f,
+	0x52, 0x76, 0xd1, 0xfe, 0x8c, 0x35, 0x4a, 0x33, 0xe7, 0x33, 0x68, 0xcb,
+	0x68, 0xa7, 0xae, 0x9e, 0xdf, 0x6a, 0xff, 0x91, 0x70, 0x12, 0x6e, 0x43,
+	0x5b, 0x49, 0x45, 0xd8, 0x02, 0x19, 0xf5, 0xaf, 0xd5, 0x6b, 0xa0, 0x68,
+	0xbb, 0xee, 0xf8, 0x76, 0x83, 0x89, 0x31, 0x27, 0xd1, 0x3f, 0xc7, 0x24,
+	0xff, 0xf1, 0x4e, 0x3b, 0xbf, 0x9e, 0x2c, 0xab, 0xd5, 0x3d, 0x97, 0x2d,
+	0xe3, 0x6f, 0xe7, 0x8a, 0x35, 0x0a, 0xf1, 0x17, 0xd2, 0x45, 0x2d, 0x0e,
+	0x49, 0x13, 0xa4, 0x85, 0x90, 0x16, 0xb7, 0x5a, 0x7d, 0x13, 0xd2, 0xde,
+	0xa5, 0xa0, 0xbd, 0xfb, 0x80, 0x27, 0xca, 0x70, 0xc6, 0xed, 0x36, 0xe3,
+	0xf9, 0x08, 0x9e, 0x43, 0x3e, 0xb9, 0x98, 0x0c, 0xa7, 0xfc, 0x66, 0x9b,
+	0x8c, 0x95, 0xfb, 0xa1, 0x9f, 0xcb, 0x36, 0x9c, 0x37, 0xe5, 0xff, 0x57,
+	0xe9, 0x77, 0x35, 0x1a, 0x3b, 0xfd, 0x43, 0x8d, 0x94, 0xaf, 0x9b, 0xe4,
+	0x60, 0x4d, 0xd9, 0xc5, 0xe4, 0x77, 0xed, 0x9c, 0x2f, 0xff, 0x7f, 0x30,
+	0xe7, 0xc4, 0xaa, 0x39, 0xbb, 0x76, 0xce, 0x15, 0xbc, 0x6f, 0xc3, 0xfb,
+	0x16, 0xea, 0x82, 0x64, 0x55, 0xde, 0x58, 0x5c, 0xe8, 0x79, 0xd5, 0xca,
+	0x89, 0x50, 0x46, 0x70, 0x5e, 0x1f, 0xb1, 0x73, 0x78, 0xa0, 0x66, 0x5e,
+	0x1f, 0x79, 0x13, 0xf3, 0xea, 0x5c, 0x31, 0xaf, 0x5d, 0x17, 0x9d, 0x57,
+	0x3d, 0x1e, 0x27, 0x2f, 0x87, 0xf3, 0x8b, 0xc9, 0x8d, 0x05, 0xce, 0x71,
+	0x27, 0xe6, 0x48, 0x18, 0xc2, 0x39, 0x0e, 0xd9, 0x39, 0x8a, 0xea, 0xda,
+	0xf1, 0x73, 0xf8, 0x5d, 0x3b, 0x3f, 0xea, 0xfe, 0x1f, 0x83, 0xa6, 0x9b,
+	0x24, 0xd3, 0xdf, 0x64, 0xe5, 0xff, 0x97, 0xe5, 0xd6, 0x22, 0xd7, 0x3a,
+	0x95, 0x16, 0xd9, 0xa3, 0xf6, 0x15, 0x9f, 0x6d, 0x64, 0x8c, 0x7f, 0x97,
+	0x6f, 0xf5, 0x18, 0xf4, 0xc5, 0x6e, 0xd8, 0x7c, 0x3b, 0x0b, 0x6a, 0x20,
+	0x22, 0x41, 0x70, 0x9b, 0xdf, 0x8c, 0xb1, 0x37, 0x6a, 0x5f, 0x75, 0x6d,
+	0x7c, 0xfd, 0x99, 0x46, 0xf1, 0x68, 0x6f, 0x50, 0x9f, 0x43, 0xdf, 0x1d,
+	0xa3, 0x0d, 0x96, 0x81, 0x9d, 0x9c, 0x4e, 0x44, 0xb4, 0x2d, 0x46, 0x9d,
+	0x98, 0x4a, 0xa4, 0xa5, 0x2c, 0xd9, 0x63, 0xe9, 0x84, 0x12, 0x8e, 0x01,
+	0x5b, 0x0d, 0x36, 0xe4, 0xad, 0x90, 0x35, 0xb7, 0x56, 0xf6, 0xaa, 0x5b,
+	0x60, 0xef, 0xdc, 0x72, 0xf2, 0x03, 0xea, 0x36, 0xd8, 0x3a, 0xb7, 0x9d,
+	0xbc, 0x41, 0xed, 0x83, 0x6d, 0xb3, 0x0f, 0x76, 0xce, 0xbe, 0x0a, 0x6d,
+	0xcf, 0x9b, 0x41, 0x7b, 0x9d, 0x35, 0xb4, 0x46, 0x1b, 0x87, 0xf3, 0x23,
+	0xee, 0x8f, 0x71, 0x0d, 0xfc, 0xa4, 0x7a, 0x45, 0xaf, 0x4b, 0xdb, 0x8a,
+	0xb2, 0xd7, 0x92, 0x55, 0xa1, 0x7e, 0xda, 0x60, 0xe3, 0x46, 0x94, 0xb7,
+	0xaf, 0x45, 0x5b, 0xa4, 0x11, 0x17, 0x78, 0x26, 0xfe, 0x48, 0x5b, 0xb5,
+	0xf3, 0xdf, 0xd4, 0x24, 0x5e, 0x67, 0x93, 0x34, 0xdf, 0x0b, 0xf9, 0x5a,
+	0x4b, 0x53, 0xbc, 0xbb, 0x56, 0xd7, 0x90, 0xb6, 0x28, 0x83, 0x43, 0x7a,
+	0xd8, 0xfa, 0x1a, 0xf2, 0xf7, 0xa2, 0xf4, 0x74, 0x4f, 0x64, 0x28, 0x08,
+	0xc6, 0x07, 0x64, 0x23, 0xe3, 0x01, 0x99, 0x4a, 0x35, 0x26, 0xa0, 0xbc,
+	0xda, 0x98, 0x00, 0xfd, 0xac, 0x47, 0x80, 0xdf, 0x19, 0x5c, 0x22, 0x63,
+	0x8c, 0x3b, 0x54, 0x42, 0xbb, 0xfc, 0x1b, 0xd6, 0x2e, 0x0f, 0xe1, 0x48,
+	0x02, 0x0e, 0x23, 0x9f, 0xd7, 0xea, 0xb9, 0x95, 0xfa, 0x3b, 0xb7, 0x6c,
+	0xd3, 0x26, 0xe5, 0xc6, 0x22, 0xe7, 0x4d, 0x19, 0x4c, 0xdc, 0xd4, 0xca,
+	0xe0, 0x84, 0xb5, 0xa3, 0x50, 0x47, 0xcb, 0xcf, 0xb5, 0xb2, 0x93, 0x72,
+	0x8f, 0xf1, 0xf9, 0x07, 0x7c, 0xd2, 0xfa, 0x7b, 0x24, 0xbd, 0x1c, 0x9f,
+	0x17, 0xd0, 0x9b, 0xf8, 0x91, 0x21, 0xbd, 0xdf, 0xe6, 0xce, 0xca, 0x6e,
+	0x19, 0x8e, 0x33, 0xd6, 0xc9, 0x78, 0x9e, 0x97, 0x9b, 0x05, 0x0f, 0x4c,
+	0x16, 0x15, 0x2c, 0xf8, 0x46, 0x19, 0x73, 0x03, 0xd9, 0xe5, 0x3b, 0x3a,
+	0x76, 0x6c, 0x74, 0xed, 0x4c, 0x93, 0xb1, 0x5d, 0x1d, 0x1d, 0xff, 0x5d,
+	0x04, 0xf5, 0x2d, 0x6a, 0xfb, 0x56, 0x69, 0xfd, 0xbb, 0xa0, 0xeb, 0x7c,
+	0xae, 0x29, 0x8c, 0x63, 0x2e, 0xba, 0x11, 0x5b, 0xaf, 0xb6, 0xfc, 0x8b,
+	0x36, 0x3e, 0x9d, 0x84, 0xec, 0x0f, 0xcb, 0xfe, 0xb0, 0x4e, 0xd9, 0xb7,
+	0xea, 0x94, 0xfd, 0xcf, 0x3a, 0x65, 0x26, 0x2e, 0xb8, 0xb3, 0xf0, 0xf7,
+	0x78, 0x37, 0xa5, 0x7d, 0x77, 0xb1, 0xfb, 0x61, 0xb9, 0xe5, 0x3a, 0x1b,
+	0xac, 0x5f, 0xc6, 0x18, 0xb1, 0x89, 0x0d, 0x67, 0x75, 0x6c, 0xb8, 0xcf,
+	0xdd, 0xa1, 0xf4, 0x5e, 0xca, 0x7e, 0xc6, 0x19, 0xf7, 0x69, 0xbc, 0x10,
+	0x27, 0x5f, 0x61, 0x0c, 0x38, 0xc7, 0xbd, 0xd8, 0xa4, 0xba, 0x18, 0x6d,
+	0x57, 0x6d, 0x13, 0xb3, 0x6e, 0xb4, 0x8b, 0x5b, 0x64, 0x04, 0xb6, 0xc2,
+	0xce, 0x42, 0x9b, 0xec, 0x9a, 0x1e, 0x58, 0x47, 0xbd, 0xb5, 0x7b, 0xda,
+	0xf8, 0x83, 0xfb, 0xc0, 0x57, 0x69, 0x21, 0x8c, 0x29, 0x5f, 0x84, 0x36,
+	0xf1, 0x5a, 0x5b, 0xf8, 0xb5, 0xfb, 0xfb, 0xa5, 0x8b, 0xf4, 0xe7, 0xc0,
+	0x76, 0x78, 0xa3, 0xfd, 0x35, 0xcb, 0xc8, 0x74, 0x88, 0x2b, 0xf5, 0x33,
+	0xb6, 0x8b, 0x5c, 0xa4, 0x9d, 0xb6, 0x4b, 0xe4, 0xe9, 0x65, 0x59, 0xbc,
+	0x15, 0x36, 0x93, 0x04, 0x99, 0x01, 0xe9, 0x8c, 0x88, 0x8e, 0xf1, 0xf8,
+	0x46, 0x36, 0xf7, 0x70, 0x6f, 0x07, 0xf4, 0x6f, 0x6c, 0x15, 0x13, 0x37,
+	0x0d, 0xed, 0x94, 0x7a, 0xb4, 0x7b, 0x9d, 0xa5, 0x5d, 0xee, 0xb9, 0xee,
+	0xa6, 0xcc, 0xd5, 0x6b, 0x42, 0x3a, 0xde, 0x55, 0x90, 0x64, 0x48, 0xc7,
+	0x8b, 0x92, 0x5e, 0x41, 0xc7, 0x8b, 0x32, 0xa4, 0xe9, 0xb8, 0x71, 0x05,
+	0x1d, 0x77, 0x5a, 0x3a, 0xde, 0x13, 0x33, 0x74, 0xa1, 0xb4, 0x9e, 0x22,
+	0x9d, 0x1a, 0x3a, 0x76, 0x34, 0x1d, 0x2f, 0xe2, 0x1e, 0xf5, 0xae, 0xb3,
+	0x75, 0x22, 0xb6, 0x8c, 0xbf, 0xc3, 0x32, 0xca, 0xc5, 0x4f, 0xc6, 0x8c,
+	0x5e, 0x1a, 0x02, 0x1d, 0x85, 0xe5, 0xfb, 0x6d, 0xfc, 0xa0, 0xb6, 0xcc,
+	0xc4, 0x47, 0x76, 0x16, 0xc6, 0x62, 0x2b, 0xe9, 0x73, 0x08, 0xf4, 0x19,
+	0xd6, 0x79, 0x2d, 0xfa, 0x6c, 0xb6, 0xfb, 0x16, 0x71, 0xbd, 0x2f, 0x9f,
+	0x8e, 0x1b, 0x5a, 0xbd, 0x45, 0xcf, 0x9d, 0xf3, 0x3e, 0xfb, 0x06, 0x68,
+	0xd5, 0xac, 0xcd, 0xb9, 0xaa, 0xbf, 0xcd, 0x58, 0x54, 0xd2, 0xc4, 0xb0,
+	0x19, 0x27, 0xbd, 0x98, 0xed, 0x68, 0xe4, 0x53, 0x83, 0x96, 0x4f, 0xad,
+	0x63, 0xcc, 0x35, 0xa8, 0xca, 0xec, 0x01, 0xe8, 0x0a, 0xda, 0xd8, 0x5a,
+	0x4e, 0xe3, 0x5d, 0x67, 0x32, 0x53, 0x78, 0x35, 0x88, 0x78, 0x8c, 0x0f,
+	0x71, 0x5f, 0x40, 0xc6, 0x1c, 0x94, 0x75, 0x95, 0xcd, 0xbc, 0x94, 0xd7,
+	0x8a, 0xe7, 0x01, 0xe9, 0x2a, 0x2b, 0xf9, 0xe8, 0x74, 0x8b, 0xec, 0x2f,
+	0x44, 0xe5, 0xe3, 0x68, 0xff, 0xb1, 0x82, 0x0b, 0x7f, 0xfc, 0x4c, 0x8c,
+	0x76, 0xe1, 0xbe, 0x02, 0xf7, 0x27, 0x59, 0x37, 0xbe, 0x6a, 0x7f, 0x36,
+	0x22, 0x5d, 0x3d, 0x79, 0x78, 0x2a, 0x12, 0xdd, 0x03, 0x38, 0x9a, 0x86,
+	0x86, 0xe4, 0x07, 0x03, 0x1b, 0x51, 0xf6, 0xb2, 0x1d, 0x6f, 0xd4, 0x31,
+	0xf1, 0xde, 0x41, 0x79, 0x77, 0x65, 0x48, 0xae, 0xaf, 0x98, 0x3d, 0xd5,
+	0xea, 0x9e, 0x69, 0xca, 0x5d, 0x80, 0xfe, 0x49, 0xbb, 0x41, 0x70, 0xce,
+	0xc3, 0xaa, 0x1f, 0x89, 0x4a, 0xac, 0x27, 0x95, 0x58, 0x10, 0xf3, 0x7c,
+	0xbe, 0xfc, 0x0f, 0xc1, 0x58, 0x3c, 0x2a, 0x3f, 0xf0, 0x38, 0xc7, 0x41,
+	0xb9, 0xae, 0x5c, 0x3b, 0x36, 0x97, 0xf3, 0x0f, 0x63, 0xdc, 0xa7, 0xc8,
+	0x54, 0x16, 0x62, 0x8c, 0xa5, 0xd3, 0xe7, 0xe8, 0x7a, 0x1b, 0xfc, 0x38,
+	0x48, 0xee, 0xae, 0xb7, 0x81, 0x6e, 0xe2, 0xd0, 0xf9, 0x57, 0x01, 0xc6,
+	0xab, 0x18, 0xfb, 0x62, 0xcc, 0x8b, 0xcf, 0x5f, 0xc7, 0xb8, 0x6c, 0xfb,
+	0x1b, 0xd6, 0x5e, 0xe6, 0xfa, 0x1b, 0xde, 0xa9, 0xaf, 0x77, 0x5a, 0xc7,
+	0x62, 0x43, 0xe2, 0xc4, 0xde, 0x91, 0x90, 0x75, 0x5e, 0xed, 0xf8, 0xdc,
+	0x27, 0x86, 0xc5, 0x38, 0x20, 0xd1, 0xdd, 0xdb, 0x07, 0x65, 0x04, 0xf3,
+	0xdb, 0xb9, 0x66, 0x7e, 0xf7, 0x08, 0xe3, 0xab, 0xe7, 0x0b, 0x9c, 0x43,
+	0x75, 0x5e, 0xea, 0x0b, 0x66, 0x5e, 0xb1, 0x9e, 0xd5, 0xf3, 0xd1, 0xed,
+	0xd5, 0x09, 0xc0, 0xf2, 0x35, 0x9d, 0x57, 0x10, 0x04, 0x6f, 0xed, 0x39,
+	0x1f, 0x24, 0x2f, 0x49, 0xf5, 0x2e, 0x54, 0xf7, 0x77, 0xc6, 0x22, 0x43,
+	0x69, 0xad, 0xcf, 0xf0, 0x9c, 0xcc, 0x96, 0xd3, 0x58, 0x47, 0x89, 0x66,
+	0xfb, 0xa3, 0x9a, 0x4f, 0xb2, 0x5e, 0xda, 0xee, 0x61, 0x85, 0x3e, 0x54,
+	0x10, 0x28, 0x6f, 0xb5, 0xdc, 0xa0, 0xbe, 0xc2, 0xdc, 0xe5, 0xdf, 0xda,
+	0x1c, 0x96, 0x5e, 0xc6, 0xb3, 0xc6, 0xa2, 0x43, 0xb1, 0x64, 0xbe, 0xec,
+	0xe1, 0x77, 0x0b, 0xee, 0x3b, 0x60, 0xaf, 0xf8, 0xb0, 0x67, 0x24, 0xae,
+	0x8c, 0x6c, 0x00, 0x2d, 0xf7, 0xe4, 0x94, 0x22, 0x6f, 0xba, 0xc9, 0xc9,
+	0x72, 0x3c, 0x59, 0x2a, 0x7f, 0x96, 0xed, 0x51, 0xb7, 0x5e, 0x2c, 0xcf,
+	0xc8, 0x86, 0xa7, 0x2a, 0x1c, 0x83, 0xfe, 0xef, 0x1b, 0x19, 0x23, 0x6a,
+	0xfb, 0x66, 0x9f, 0x21, 0x5e, 0xa2, 0x74, 0xc9, 0xf1, 0x2f, 0x6d, 0x7d,
+	0x13, 0xce, 0xef, 0xb3, 0x16, 0xee, 0xd5, 0xe3, 0xbe, 0xa0, 0xed, 0x97,
+	0xd3, 0x15, 0xda, 0x8c, 0xdc, 0xdf, 0x49, 0x1d, 0x9f, 0x11, 0xc2, 0x11,
+	0x04, 0xcf, 0xf9, 0x46, 0x77, 0x3f, 0x55, 0xe1, 0x1e, 0x47, 0x10, 0xfc,
+	0x88, 0x76, 0xf1, 0xde, 0x22, 0xc6, 0x0b, 0x71, 0xb0, 0x35, 0x17, 0x85,
+	0x5c, 0x9c, 0x1a, 0x20, 0x7e, 0x05, 0x1e, 0x6a, 0x8f, 0x7b, 0xa3, 0xc4,
+	0x92, 0x9f, 0x2a, 0xb7, 0x24, 0x3f, 0x5d, 0x76, 0x81, 0x67, 0xce, 0x3b,
+	0x9e, 0x9c, 0xb0, 0x73, 0xce, 0x96, 0x89, 0xdf, 0xd7, 0xda, 0x87, 0x7c,
+	0x61, 0x85, 0xbf, 0x44, 0x98, 0xaa, 0xb0, 0x10, 0xb6, 0xa4, 0xc5, 0x4d,
+	0x10, 0xfc, 0xd8, 0x37, 0x6b, 0x3a, 0x55, 0x94, 0x29, 0x8c, 0x9b, 0xdb,
+	0xac, 0x88, 0x87, 0x58, 0xf2, 0x0e, 0x8c, 0xfd, 0x29, 0x8c, 0xbd, 0xbf,
+	0xcc, 0xf1, 0x20, 0x2b, 0x30, 0xf7, 0xa9, 0x4a, 0x08, 0x6f, 0xbd, 0xb1,
+	0xc3, 0x35, 0xef, 0xb5, 0x36, 0x5e, 0xf8, 0xac, 0x11, 0xd9, 0xae, 0xbc,
+	0x7e, 0xd0, 0xd7, 0xe2, 0xa6, 0xa8, 0xfc, 0x22, 0xe4, 0x6e, 0x20, 0x8f,
+	0x42, 0x9e, 0x2d, 0x6a, 0xba, 0xc9, 0x5c, 0xce, 0xff, 0x23, 0xf2, 0xeb,
+	0xeb, 0x18, 0x5f, 0x1e, 0xf6, 0x68, 0xbb, 0x2e, 0x05, 0x8b, 0x1e, 0xe5,
+	0xf3, 0x06, 0x99, 0x71, 0x73, 0xbd, 0xd0, 0x15, 0x28, 0x6b, 0xa5, 0xbf,
+	0x9d, 0xcc, 0x44, 0x52, 0xc9, 0x49, 0x61, 0x3e, 0x14, 0x73, 0x15, 0x98,
+	0x23, 0x44, 0xd9, 0x10, 0x85, 0xcc, 0xe3, 0x1a, 0x9a, 0xf1, 0x26, 0xcb,
+	0xd5, 0xba, 0x07, 0x84, 0x7b, 0x86, 0xa9, 0xc4, 0x3e, 0x6d, 0x9f, 0x88,
+	0x8c, 0x17, 0x58, 0x77, 0x3b, 0xac, 0x13, 0xaf, 0xa6, 0xbe, 0xce, 0xe1,
+	0x02, 0x9f, 0x87, 0x71, 0xac, 0x58, 0x2c, 0x53, 0x90, 0x97, 0x23, 0x03,
+	0xf2, 0x32, 0xed, 0xce, 0x61, 0xd0, 0xb6, 0xeb, 0xf1, 0xbd, 0x29, 0xcf,
+	0xf8, 0xb2, 0x94, 0x19, 0xec, 0xa3, 0x9d, 0x9d, 0x53, 0x9a, 0x27, 0x44,
+	0xa1, 0x6d, 0x2c, 0x5b, 0x96, 0x91, 0x6c, 0xc1, 0xc6, 0x7a, 0x46, 0x39,
+	0xe7, 0x0d, 0x35, 0x73, 0x6f, 0x95, 0x28, 0x60, 0x1a, 0x89, 0x24, 0x9d,
+	0x06, 0xef, 0x23, 0x2d, 0x46, 0xe7, 0x43, 0xee, 0xb7, 0xdd, 0xdf, 0xce,
+	0x3d, 0x53, 0x05, 0x1f, 0x5a, 0xb5, 0xdf, 0x7e, 0x8d, 0x1a, 0xfa, 0xf3,
+	0x04, 0xf4, 0xa0, 0x95, 0x95, 0xb1, 0x91, 0xae, 0x65, 0xfa, 0xe6, 0xf8,
+	0xd2, 0x1e, 0xf1, 0x92, 0x23, 0xc3, 0x65, 0x51, 0x91, 0x21, 0x37, 0x36,
+	0x5c, 0x5e, 0x49, 0xf3, 0x4f, 0x55, 0xfe, 0xbd, 0xb5, 0x05, 0x6b, 0x63,
+	0xaa, 0xb5, 0xef, 0xc8, 0x77, 0x2b, 0xf6, 0x2b, 0x92, 0x26, 0x07, 0x86,
+	0xfb, 0xb4, 0x5c, 0x93, 0xf4, 0x5b, 0x1b, 0xa0, 0x7c, 0x66, 0xb4, 0x8f,
+	0xc6, 0x9c, 0x8b, 0x98, 0xcd, 0x3d, 0x33, 0xb8, 0x4e, 0x97, 0x1d, 0x99,
+	0x82, 0x7c, 0x38, 0x20, 0x7f, 0x1f, 0xa4, 0xe3, 0xe6, 0xbd, 0x59, 0x5f,
+	0xd6, 0xe7, 0x5e, 0x44, 0xb3, 0xe4, 0x4f, 0x46, 0x25, 0x77, 0x92, 0x7b,
+	0x60, 0xcf, 0xed, 0xaf, 0xe6, 0x6d, 0x50, 0x0e, 0x70, 0xbf, 0xd6, 0x91,
+	0x3c, 0xfc, 0xda, 0x11, 0xee, 0xc3, 0xf7, 0xff, 0x1f, 0xf4, 0xc1, 0x7a,
+	0x61, 0xdb, 0x16, 0xb4, 0x6d, 0xb4, 0x6d, 0x47, 0xef, 0x78, 0x73, 0x6d,
+	0x5b, 0xd1, 0x36, 0x16, 0x8e, 0xfb, 0x06, 0xdb, 0x6a, 0x7c, 0x5e, 0x33,
+	0x5c, 0x28, 0x2e, 0xc1, 0x4f, 0x4e, 0x4c, 0x48, 0xda, 0x19, 0x1f, 0xd0,
+	0xf3, 0xb9, 0x66, 0xb8, 0x0c, 0x38, 0xe2, 0x41, 0x90, 0xf7, 0x43, 0x3d,
+	0xcc, 0x7f, 0xc7, 0x44, 0x3c, 0x96, 0x71, 0xdf, 0x92, 0xfe, 0x04, 0xa3,
+	0xa4, 0x2e, 0xf3, 0xd9, 0x24, 0xcf, 0xfd, 0xc9, 0xf8, 0x46, 0xdc, 0x55,
+	0x17, 0x71, 0x92, 0xf5, 0x18, 0xef, 0xdd, 0x68, 0xcb, 0x23, 0x2c, 0x4f,
+	0x45, 0x21, 0x4b, 0x4c, 0x79, 0xc4, 0x96, 0x03, 0x26, 0x3f, 0x9f, 0x04,
+	0xb7, 0xd9, 0x72, 0x3e, 0x2b, 0x5d, 0x6e, 0x9e, 0x0d, 0x0f, 0x8d, 0x09,
+	0xe3, 0x3a, 0x99, 0xeb, 0x1a, 0x64, 0x2b, 0xd6, 0x87, 0x3e, 0xa3, 0x23,
+	0xcd, 0x80, 0xe3, 0x9c, 0xff, 0x76, 0xd8, 0xd6, 0x81, 0xfc, 0xc0, 0x37,
+	0xf4, 0x3f, 0x2b, 0x3d, 0x69, 0xe5, 0x30, 0x07, 0x20, 0x90, 0x9d, 0xfe,
+	0xb6, 0xc4, 0x2e, 0xfc, 0x1e, 0xef, 0x4f, 0xca, 0xec, 0x20, 0xe8, 0xb1,
+	0x9f, 0xbc, 0xb1, 0x15, 0x36, 0x0f, 0x7e, 0xf7, 0xb4, 0xc8, 0x92, 0x9b,
+	0x73, 0xd7, 0xc1, 0x5f, 0x1b, 0xc1, 0xac, 0xe6, 0x0a, 0x9e, 0x7b, 0x1b,
+	0x84, 0x5c, 0xda, 0xed, 0xc1, 0xbd, 0x76, 0xbe, 0xdf, 0xc2, 0x7c, 0x7f,
+	0xad, 0x59, 0x9a, 0x59, 0x5e, 0x5b, 0xb7, 0x51, 0xf6, 0xb8, 0xdb, 0xdd,
+	0xd8, 0x8a, 0xba, 0xe7, 0x51, 0x97, 0x65, 0x9e, 0xcb, 0x1c, 0x9d, 0xd9,
+	0x32, 0xe9, 0xcc, 0xc0, 0xda, 0xd5, 0x13, 0x04, 0xd7, 0xf9, 0x1c, 0x37,
+	0x08, 0xae, 0xf7, 0xfb, 0xdc, 0x67, 0xe5, 0xf9, 0xc0, 0xd8, 0x54, 0x21,
+	0xed, 0x3c, 0x67, 0xe5, 0x75, 0x10, 0xbc, 0xec, 0xf7, 0xca, 0xef, 0x54,
+	0x52, 0x8f, 0xd3, 0xe7, 0x3e, 0x83, 0xe7, 0x33, 0xbe, 0xc9, 0x2b, 0xfa,
+	0x13, 0xb4, 0x8b, 0xab, 0x7e, 0xd0, 0xb0, 0x27, 0x5f, 0xd4, 0x3e, 0x3a,
+	0xf1, 0x67, 0x62, 0xfc, 0x55, 0x18, 0x30, 0x61, 0x2f, 0xb3, 0xc9, 0x65,
+	0x7e, 0xa0, 0xa6, 0xdf, 0xda, 0x77, 0x0a, 0xef, 0x58, 0x16, 0x04, 0x97,
+	0x0c, 0xfc, 0x31, 0xe6, 0x94, 0x2a, 0x71, 0xef, 0xee, 0x03, 0x9a, 0xff,
+	0x04, 0x7e, 0x3d, 0xe9, 0x24, 0xea, 0x2a, 0xe5, 0x1d, 0xee, 0x52, 0xa9,
+	0x9c, 0xc8, 0x5b, 0xb0, 0xfe, 0x5c, 0x63, 0x30, 0x48, 0x1b, 0x60, 0xdf,
+	0xb6, 0xbd, 0xd9, 0xc4, 0x92, 0xe8, 0x4b, 0xa7, 0x37, 0xc1, 0xd7, 0xd5,
+	0xf6, 0x4c, 0x14, 0x7c, 0x3d, 0xd1, 0x16, 0x04, 0xef, 0xf7, 0xc3, 0x35,
+	0xb3, 0xb1, 0x6a, 0xe8, 0xf8, 0x6c, 0xff, 0xb9, 0x66, 0x63, 0xc7, 0x31,
+	0x4f, 0x30, 0xa9, 0xe3, 0xfa, 0xaa, 0x1d, 0x3a, 0x64, 0xdb, 0x57, 0x39,
+	0x7e, 0x8e, 0xe5, 0xef, 0xf3, 0x43, 0x98, 0xaa, 0xed, 0xb3, 0xfd, 0xeb,
+	0xac, 0xcd, 0x19, 0x05, 0x2e, 0x3d, 0xb7, 0x4b, 0xfd, 0x4d, 0x60, 0x74,
+	0x6b, 0x48, 0xc3, 0x7f, 0x17, 0x3c, 0x18, 0x37, 0xcf, 0x99, 0x6d, 0xec,
+	0x63, 0xab, 0x4c, 0x6e, 0xc3, 0x73, 0xf4, 0x5a, 0xdc, 0x87, 0x2f, 0x8b,
+	0xc8, 0x15, 0x89, 0x61, 0xb5, 0xcd, 0x7d, 0x50, 0xfa, 0xac, 0x8c, 0xfb,
+	0x1a, 0xf4, 0x7d, 0x0e, 0xfe, 0x78, 0x93, 0x3c, 0x08, 0x9a, 0x56, 0x03,
+	0xa9, 0xe4, 0x82, 0x4a, 0xf5, 0xce, 0xa8, 0x94, 0x3f, 0xa6, 0xae, 0xe7,
+	0xbc, 0x06, 0x89, 0x8b, 0x19, 0xe2, 0xb7, 0x08, 0xfc, 0x17, 0x81, 0xe3,
+	0x8b, 0xee, 0xf1, 0xfa, 0x56, 0xb7, 0x18, 0xfd, 0x96, 0xd3, 0xb4, 0x69,
+	0xec, 0xf2, 0x3f, 0xf6, 0xc3, 0x35, 0x84, 0x6d, 0xc8, 0x1c, 0x99, 0xba,
+	0x6b, 0x94, 0xe5, 0x1a, 0x41, 0x31, 0xe4, 0x40, 0xf7, 0xa9, 0xe4, 0x84,
+	0x5a, 0x0a, 0x36, 0xed, 0xe8, 0xee, 0x7d, 0x42, 0xf7, 0x93, 0xf2, 0xd3,
+	0x2a, 0x0f, 0x78, 0xb6, 0x4a, 0xd3, 0x0e, 0xe2, 0x99, 0xb0, 0xc6, 0x18,
+	0x4f, 0x72, 0xef, 0x40, 0xdd, 0x31, 0xa5, 0xf7, 0xa0, 0x6d, 0x1d, 0xc2,
+	0x1c, 0x5f, 0x2f, 0xcd, 0xd4, 0x43, 0x8c, 0x93, 0xbd, 0x96, 0x2e, 0x84,
+	0x4c, 0x3a, 0x46, 0x19, 0x18, 0x31, 0xb1, 0xdf, 0xca, 0xcf, 0xa1, 0x9d,
+	0xce, 0x67, 0x89, 0x45, 0x21, 0xa3, 0xa6, 0xc0, 0xc5, 0x87, 0x8e, 0x49,
+	0xb4, 0xc1, 0xfb, 0x5f, 0xcd, 0xc6, 0x6f, 0xa2, 0x0f, 0xc5, 0xb1, 0x1b,
+	0x24, 0xbf, 0x26, 0xde, 0x52, 0x02, 0xfc, 0xcd, 0x32, 0x79, 0x8c, 0x6b,
+	0x11, 0x85, 0xcc, 0xe1, 0xd8, 0x12, 0xcd, 0xf4, 0x07, 0xc1, 0x38, 0xcb,
+	0x4f, 0x92, 0x7f, 0x25, 0xc5, 0x77, 0xb9, 0x93, 0x0b, 0x9b, 0xd4, 0x0a,
+	0x59, 0xdb, 0x62, 0xe1, 0xd0, 0x78, 0x92, 0x92, 0x96, 0x23, 0xd4, 0x37,
+	0xb7, 0xd5, 0xc0, 0x33, 0x7a, 0xc7, 0x94, 0xd7, 0xf8, 0x26, 0xe0, 0xf9,
+	0x3d, 0xc0, 0xd3, 0x62, 0xe1, 0x69, 0x5c, 0x05, 0x4f, 0x4b, 0x08, 0x0f,
+	0xe4, 0x1c, 0xe5, 0x6a, 0xec, 0x9a, 0x74, 0x59, 0x9c, 0xbc, 0x27, 0x9d,
+	0x4a, 0xfb, 0x2f, 0xd4, 0x37, 0x8d, 0xee, 0xf8, 0x80, 0x2b, 0xe3, 0x5a,
+	0xd7, 0x44, 0xaf, 0xe9, 0x2e, 0x2f, 0xc0, 0x7a, 0x15, 0x27, 0xe3, 0x11,
+	0xf6, 0x7a, 0x76, 0xd5, 0x3d, 0x90, 0xff, 0x8b, 0xa9, 0xa8, 0xb5, 0x25,
+	0x4a, 0x3e, 0xfd, 0x96, 0xb8, 0xde, 0xdb, 0xaf, 0xc2, 0xf4, 0x12, 0x60,
+	0x82, 0x3c, 0x3e, 0xd6, 0xe7, 0x8e, 0xca, 0xa5, 0xda, 0x37, 0xb3, 0xb8,
+	0xc6, 0xdc, 0x62, 0x35, 0x73, 0x83, 0xfe, 0x53, 0xe1, 0xdc, 0x20, 0x13,
+	0x51, 0xaf, 0x24, 0xf7, 0x5b, 0x5c, 0xb4, 0x62, 0x4e, 0xb1, 0x9a, 0xf9,
+	0x74, 0x27, 0xf6, 0xb3, 0xcc, 0xcc, 0xa7, 0x27, 0xef, 0xc5, 0x2c, 0x7e,
+	0x57, 0xc3, 0x58, 0xf5, 0x17, 0x67, 0x24, 0x90, 0x29, 0x1f, 0x6b, 0xd4,
+	0x4b, 0xff, 0x24, 0x66, 0xf3, 0x98, 0x15, 0x9e, 0x37, 0x58, 0xfe, 0x72,
+	0x25, 0xaf, 0xfd, 0xb7, 0x2f, 0xad, 0x37, 0x7c, 0x1a, 0xb5, 0xf9, 0x6b,
+	0xfc, 0xdd, 0xb1, 0xde, 0xee, 0xef, 0xe7, 0xd2, 0xf2, 0xfb, 0xeb, 0x69,
+	0x97, 0x34, 0x78, 0x43, 0xab, 0xca, 0x62, 0x28, 0xbb, 0x7d, 0xbd, 0x95,
+	0x0b, 0x28, 0xbb, 0x07, 0x7e, 0x1a, 0xf3, 0x34, 0xf8, 0x8e, 0x32, 0xb8,
+	0x16, 0x27, 0x7d, 0x60, 0x45, 0xf2, 0x3c, 0xe5, 0x22, 0x6d, 0x4a, 0xcc,
+	0x51, 0x7d, 0x27, 0x8c, 0xa3, 0xe3, 0x77, 0x3d, 0xdb, 0x9f, 0xf8, 0x26,
+	0xae, 0xe5, 0xdb, 0x53, 0xe0, 0xfb, 0x03, 0xbe, 0x13, 0x9d, 0x65, 0x1e,
+	0x80, 0xa6, 0xe1, 0xda, 0xbe, 0xaf, 0x47, 0xdf, 0x21, 0x2d, 0x93, 0x5e,
+	0xae, 0xd7, 0x74, 0xd3, 0x44, 0x5d, 0x7c, 0x8c, 0xf4, 0xc7, 0x58, 0x72,
+	0xb3, 0xd6, 0x8f, 0xd5, 0x75, 0x6c, 0x82, 0xae, 0x89, 0x1b, 0x1e, 0x75,
+	0xcd, 0x7e, 0x77, 0xb5, 0xbf, 0x31, 0xf4, 0x47, 0x3b, 0x0d, 0x7e, 0xba,
+	0xc7, 0x68, 0x0e, 0xe5, 0x97, 0x13, 0x55, 0x57, 0x6a, 0x3f, 0x33, 0xa6,
+	0xf3, 0x8e, 0x96, 0xeb, 0x4e, 0xd8, 0xb1, 0x49, 0xb7, 0x26, 0xfe, 0x5f,
+	0x1d, 0x5f, 0x1c, 0xb5, 0x4d, 0x40, 0x65, 0x8d, 0x32, 0x35, 0x40, 0x1a,
+	0xe5, 0xdc, 0xb5, 0x0d, 0x75, 0x0d, 0xed, 0x08, 0x43, 0x9f, 0xb4, 0x9d,
+	0xa2, 0xd7, 0x64, 0x0b, 0x8d, 0xc6, 0x67, 0x89, 0xcb, 0xe6, 0x06, 0x9d,
+	0x47, 0x80, 0xb2, 0x72, 0xa8, 0xcb, 0xa2, 0x32, 0xdb, 0xff, 0xbf, 0x83,
+	0xf4, 0x5e, 0xd6, 0xad, 0xbb, 0x6f, 0x9f, 0x98, 0x11, 0x8d, 0xa7, 0xbf,
+	0xa8, 0xe2, 0xc9, 0xce, 0x2d, 0xbe, 0x7a, 0x6e, 0x05, 0xc0, 0x7b, 0x0f,
+	0x64, 0x27, 0xd7, 0xc9, 0xe4, 0x6f, 0x3f, 0x2e, 0x4e, 0x34, 0xd3, 0x5b,
+	0x6f, 0x6e, 0xa5, 0x10, 0xaf, 0x9c, 0x1b, 0x68, 0x35, 0x9c, 0x17, 0x69,
+	0x3b, 0xae, 0xf7, 0x89, 0x94, 0x22, 0x2c, 0xad, 0xab, 0x70, 0x1b, 0xd2,
+	0x9d, 0xa1, 0xb9, 0xa7, 0x34, 0xcd, 0xb5, 0x58, 0x9a, 0x43, 0x5d, 0x97,
+	0xfb, 0xde, 0xa3, 0x2d, 0x55, 0x9a, 0xdb, 0x60, 0x69, 0xee, 0x99, 0xf5,
+	0x66, 0x4f, 0xfc, 0xfd, 0x2d, 0x66, 0x4f, 0xea, 0x2f, 0x57, 0x3d, 0x6f,
+	0xa2, 0xcd, 0x08, 0x5f, 0x2c, 0x7c, 0xae, 0x85, 0xf5, 0x0c, 0x60, 0xad,
+	0x95, 0x35, 0x4d, 0x36, 0xee, 0xc6, 0xfd, 0x73, 0xfa, 0x7d, 0x51, 0x79,
+	0x14, 0x76, 0x50, 0xbe, 0xfc, 0x8f, 0xc1, 0x02, 0x7c, 0xbf, 0xa9, 0x65,
+	0xdd, 0x7b, 0x5b, 0x0b, 0xf9, 0x6d, 0x06, 0xbf, 0x0e, 0xd6, 0xf8, 0x3c,
+	0x98, 0x2f, 0xca, 0xfe, 0x01, 0xeb, 0x01, 0xb9, 0xbc, 0x5c, 0x97, 0x31,
+	0x0b, 0xe3, 0xe3, 0x30, 0x66, 0x68, 0xf6, 0x13, 0x29, 0xe7, 0xef, 0x84,
+	0x4f, 0x74, 0x0f, 0xf4, 0x24, 0xe9, 0xfb, 0xa5, 0x16, 0x93, 0xe7, 0x1b,
+	0x87, 0x1e, 0xfb, 0x65, 0x9b, 0x0b, 0x75, 0xf8, 0x57, 0xeb, 0xe7, 0xf8,
+	0x82, 0xf6, 0x1d, 0xd2, 0xcc, 0xdf, 0xb7, 0x98, 0x98, 0xf1, 0xb7, 0x5a,
+	0xc8, 0x67, 0x6a, 0xdb, 0x0f, 0x37, 0x68, 0xbe, 0x70, 0xc2, 0xe7, 0xcf,
+	0xb4, 0xae, 0x7c, 0x0e, 0xdb, 0x3d, 0xd9, 0xba, 0xb2, 0x5d, 0x58, 0xfe,
+	0x73, 0x1b, 0x57, 0x96, 0x5f, 0xe3, 0xae, 0x6c, 0xff, 0xf5, 0x55, 0xcf,
+	0x2d, 0x9b, 0x56, 0x3e, 0x5f, 0xbd, 0xea, 0x79, 0x6a, 0xd5, 0xf3, 0x85,
+	0x55, 0xcf, 0x57, 0xb5, 0xad, 0x7c, 0xbe, 0xbd, 0xad, 0x3e, 0xbc, 0x87,
+	0xdb, 0x56, 0xc2, 0x75, 0xa7, 0x8e, 0xf7, 0xcf, 0x54, 0xa2, 0xb2, 0xab,
+	0x80, 0xf7, 0x4e, 0xe7, 0x66, 0xa3, 0xd7, 0x6a, 0xdf, 0x33, 0xbe, 0xf6,
+	0xd7, 0xab, 0xfa, 0xab, 0xb6, 0xdb, 0x5d, 0x6d, 0xe7, 0x57, 0xdb, 0x19,
+	0xd9, 0x36, 0x5b, 0xe1, 0x3b, 0x96, 0x87, 0xfd, 0x9a, 0xb6, 0x53, 0xc5,
+	0x4e, 0x9d, 0x0b, 0x3b, 0xaa, 0x73, 0x61, 0x93, 0xe0, 0xc3, 0x3b, 0x75,
+	0x4c, 0x69, 0x93, 0x42, 0x79, 0xa5, 0x55, 0xc7, 0x95, 0x74, 0x2c, 0xb5,
+	0x30, 0x0a, 0xdb, 0x96, 0x39, 0xb0, 0x81, 0xec, 0xf1, 0xcd, 0xdd, 0xe4,
+	0xc4, 0x1e, 0x0e, 0x86, 0xdd, 0x20, 0x98, 0xf4, 0x6e, 0xb3, 0xf9, 0x62,
+	0xb8, 0x57, 0x4c, 0x1b, 0xea, 0xe0, 0x27, 0xa0, 0x83, 0xab, 0xba, 0xf7,
+	0x4e, 0x8c, 0xb5, 0x00, 0x9a, 0x19, 0x90, 0xdf, 0xad, 0xa4, 0xbe, 0x24,
+	0xfa, 0xcc, 0x4d, 0x3f, 0x6c, 0xb8, 0xa5, 0x4f, 0xbd, 0xdf, 0xf3, 0x61,
+	0xeb, 0x05, 0xf2, 0xb0, 0x3f, 0x08, 0x1a, 0xea, 0x85, 0xbd, 0xe7, 0x69,
+	0xbf, 0xf4, 0xb4, 0xa6, 0x2d, 0xd2, 0x58, 0x8b, 0xce, 0xd7, 0x7f, 0xd4,
+	0x77, 0x62, 0x99, 0xfe, 0x3f, 0x32, 0x71, 0x1a, 0xbf, 0xdb, 0xfd, 0x1a,
+	0xf8, 0x76, 0xa7, 0xb7, 0x05, 0x3e, 0x0a, 0x69, 0x88, 0xf1, 0xaf, 0xcb,
+	0x75, 0x1e, 0x21, 0x03, 0x68, 0x33, 0x51, 0xc6, 0x09, 0x53, 0x83, 0x63,
+	0xc2, 0x79, 0xa7, 0x12, 0x49, 0xa5, 0xed, 0xaa, 0xe0, 0x46, 0x9f, 0x39,
+	0xb6, 0xdc, 0x63, 0x21, 0x3f, 0xef, 0xff, 0xf4, 0x94, 0x97, 0x73, 0x23,
+	0x36, 0x2f, 0x37, 0x53, 0x30, 0xb4, 0x39, 0x41, 0xda, 0x84, 0x3f, 0xb5,
+	0xd8, 0xff, 0xb7, 0x01, 0xed, 0xfb, 0xa4, 0x22, 0xed, 0xff, 0x4d, 0x30,
+	0x17, 0x65, 0x5f, 0x84, 0x7b, 0xff, 0xa7, 0x33, 0x1a, 0x57, 0x77, 0xca,
+	0x81, 0x22, 0x6d, 0xe1, 0x98, 0xce, 0xe7, 0x18, 0xf7, 0x69, 0xa7, 0xc5,
+	0x80, 0xc7, 0x0f, 0x01, 0x7f, 0x2d, 0xb0, 0xb9, 0x47, 0x50, 0x27, 0x22,
+	0x63, 0x60, 0xf1, 0xd9, 0x02, 0xf9, 0x93, 0xf7, 0x28, 0xea, 0xbb, 0x32,
+	0x5f, 0xb8, 0x59, 0xe7, 0xdb, 0x9d, 0x46, 0xdb, 0x27, 0x71, 0xcd, 0x16,
+	0x26, 0xd0, 0x66, 0xaf, 0xae, 0x3f, 0x5b, 0x62, 0x8e, 0xb2, 0x40, 0x2e,
+	0xed, 0x97, 0xfc, 0x5c, 0x97, 0x8c, 0xc5, 0x17, 0x66, 0xa2, 0xcb, 0x71,
+	0x99, 0x8f, 0x6f, 0xe0, 0x1e, 0x47, 0xfe, 0x4a, 0xee, 0x07, 0x4b, 0x74,
+	0x74, 0xbb, 0xea, 0x6d, 0xd3, 0x3e, 0xd7, 0xa0, 0xec, 0xac, 0x0c, 0xc9,
+	0x4d, 0x95, 0xcf, 0x6e, 0x36, 0xb1, 0xa8, 0x15, 0xf1, 0xad, 0xc3, 0xc4,
+	0x8a, 0x3a, 0x1a, 0xe5, 0xb9, 0x25, 0x99, 0x3d, 0x25, 0x12, 0x39, 0x1a,
+	0xc6, 0x12, 0x59, 0xe6, 0x4a, 0xd7, 0x95, 0x80, 0xeb, 0x14, 0x64, 0x6b,
+	0x3c, 0x26, 0x5f, 0xdc, 0x16, 0x8e, 0x95, 0x0b, 0xa6, 0xb7, 0xe5, 0xe4,
+	0xd3, 0xb8, 0xb2, 0x57, 0xa6, 0x4a, 0x19, 0xc5, 0x71, 0xbf, 0x13, 0x50,
+	0x96, 0xa9, 0x21, 0x4f, 0x72, 0x6d, 0xe1, 0xd8, 0xf0, 0x6f, 0x76, 0x84,
+	0xe3, 0xd3, 0xe6, 0x36, 0x67, 0x1e, 0xf2, 0xdc, 0x77, 0x01, 0xfd, 0x45,
+	0x86, 0xee, 0xde, 0x40, 0xdf, 0x61, 0x58, 0xd8, 0x0e, 0x32, 0x5d, 0xb1,
+	0x6f, 0xc2, 0x49, 0xf8, 0x6b, 0xe1, 0x5c, 0x4c, 0xc6, 0x81, 0xa3, 0xdc,
+	0xeb, 0xc2, 0xdb, 0xe7, 0x7a, 0xaa, 0x1e, 0xbc, 0xa3, 0x36, 0x96, 0xc8,
+	0xf8, 0xe0, 0x3a, 0xe0, 0xad, 0x05, 0xe5, 0x1f, 0x94, 0xa9, 0x63, 0x6f,
+	0xdb, 0xcc, 0xbd, 0xec, 0x06, 0xcf, 0xb1, 0x39, 0xa7, 0x3c, 0xbf, 0x73,
+	0x37, 0xea, 0xf0, 0xfd, 0xcd, 0x68, 0x93, 0xca, 0x65, 0x22, 0x9b, 0xe1,
+	0x13, 0x71, 0xdc, 0x20, 0xd2, 0xb5, 0xa3, 0x59, 0xe7, 0x90, 0xca, 0x29,
+	0xea, 0xf3, 0xb0, 0xed, 0xdd, 0x3a, 0x47, 0x03, 0x7e, 0x7b, 0x6e, 0x24,
+	0x42, 0xf9, 0xd5, 0x2b, 0xc3, 0xd4, 0x27, 0xa7, 0x6e, 0xd6, 0xb4, 0xdf,
+	0xbd, 0x8d, 0x67, 0x99, 0xfa, 0x8c, 0x8d, 0x1e, 0x27, 0x8c, 0xa3, 0x28,
+	0x87, 0xfd, 0xfe, 0x9a, 0x30, 0xdc, 0xf5, 0x26, 0x61, 0xb8, 0xeb, 0x4d,
+	0xc2, 0x40, 0x5c, 0x00, 0x8e, 0xca, 0x5f, 0x6c, 0x08, 0x63, 0xd5, 0x97,
+	0x62, 0x1e, 0x07, 0x8b, 0x77, 0xc9, 0xa1, 0xa2, 0xa3, 0xe3, 0x8e, 0x0b,
+	0x8a, 0x32, 0xc1, 0x05, 0x4f, 0x82, 0xf7, 0x8a, 0xe0, 0xcd, 0x22, 0x78,
+	0xb1, 0x08, 0xbe, 0x84, 0xfd, 0x7f, 0x06, 0xf6, 0xff, 0x93, 0x58, 0x9b,
+	0xd3, 0x2b, 0x78, 0x39, 0xad, 0x79, 0x39, 0x5f, 0xa4, 0xaf, 0xd6, 0x7f,
+	0x11, 0x7e, 0x8d, 0xca, 0x70, 0x21, 0x05, 0x55, 0xe2, 0x44, 0xb3, 0xfd,
+	0x9f, 0x24, 0xbf, 0xca, 0x83, 0xfe, 0x0d, 0x68, 0x73, 0x18, 0x34, 0x9e,
+	0xa2, 0x1d, 0x48, 0xfb, 0x27, 0x07, 0xde, 0x3c, 0x4c, 0x5f, 0x4d, 0x5d,
+	0xb9, 0x49, 0xa8, 0x5f, 0xa2, 0x3b, 0x98, 0x7b, 0xc8, 0xb9, 0x26, 0x57,
+	0xe1, 0xc9, 0xf0, 0xef, 0x84, 0x47, 0x3d, 0x43, 0xbe, 0x7d, 0x99, 0x7c,
+	0x5b, 0xc3, 0xab, 0x01, 0xe7, 0x17, 0xb8, 0xdb, 0xea, 0xb5, 0xad, 0xd6,
+	0xdf, 0xb4, 0x5c, 0x5f, 0x8f, 0x5f, 0x22, 0x3f, 0x42, 0x27, 0x11, 0xf7,
+	0xc9, 0x4c, 0x64, 0x8b, 0xc5, 0x3d, 0x6c, 0xb7, 0x1d, 0x97, 0x00, 0xf7,
+	0x9d, 0x92, 0x9b, 0x0f, 0xc4, 0xdb, 0x11, 0xf6, 0x59, 0xed, 0xc7, 0xb5,
+	0xfd, 0x8c, 0x17, 0x1c, 0x19, 0xd9, 0xc6, 0x7d, 0x08, 0x07, 0x7a, 0x3e,
+	0x5c, 0x0f, 0xd8, 0xfb, 0x7a, 0xcd, 0x29, 0x63, 0x29, 0x5b, 0x5b, 0x6c,
+	0xfc, 0x89, 0xfd, 0x1d, 0x5e, 0xb5, 0x4e, 0x17, 0x02, 0x9e, 0x11, 0x9b,
+	0xf2, 0x6e, 0xa8, 0xa1, 0x95, 0xfb, 0x2c, 0xad, 0xa8, 0x55, 0xf3, 0xb8,
+	0xdd, 0xd2, 0x4a, 0x08, 0x6f, 0x3c, 0xa4, 0x95, 0xa6, 0x90, 0x56, 0x72,
+	0x33, 0x21, 0xad, 0xb0, 0xed, 0xed, 0x21, 0xad, 0x24, 0x6b, 0x69, 0x25,
+	0x37, 0xe3, 0xe0, 0x5a, 0x0d, 0x07, 0xe9, 0x85, 0xfd, 0x90, 0x5e, 0x00,
+	0x4b, 0xe5, 0xd6, 0xd6, 0x90, 0x5e, 0xe2, 0xe8, 0xe7, 0x50, 0xd1, 0xe4,
+	0x74, 0xc0, 0xef, 0xb2, 0x3a, 0xc4, 0xc5, 0x9a, 0x1b, 0x1f, 0xb1, 0x3e,
+	0x8d, 0xf8, 0x96, 0x46, 0xaa, 0x79, 0xee, 0xab, 0x68, 0x03, 0xb8, 0x67,
+	0x2e, 0xeb, 0x76, 0x4d, 0x1b, 0xf7, 0xfb, 0x53, 0xa8, 0xbb, 0x07, 0xb4,
+	0x11, 0xe2, 0xe0, 0x7a, 0x8b, 0x83, 0xd5, 0x6b, 0x39, 0x66, 0x71, 0xb0,
+	0xc7, 0xe2, 0x40, 0xf3, 0x4b, 0x8e, 0x6b, 0xa6, 0x34, 0x0e, 0x9a, 0x34,
+	0x0e, 0x44, 0x85, 0x6d, 0xc7, 0xea, 0xe0, 0x80, 0x75, 0xf6, 0xe8, 0xf9,
+	0x47, 0x30, 0xff, 0xfd, 0x98, 0xbf, 0xd2, 0xf3, 0xe7, 0x3a, 0x70, 0xfe,
+	0x80, 0xa5, 0x72, 0x72, 0x79, 0xfe, 0x6d, 0xe8, 0xe3, 0x60, 0x31, 0xa2,
+	0xe7, 0x0f, 0xdb, 0x7e, 0x30, 0x9c, 0xff, 0xe9, 0x8a, 0xc9, 0x7f, 0x3e,
+	0xbd, 0x46, 0xcf, 0x4d, 0x59, 0xde, 0xf0, 0xb4, 0x5f, 0xcc, 0x98, 0xf6,
+	0x19, 0xe8, 0xb6, 0x69, 0x3f, 0x69, 0xcf, 0x43, 0x19, 0x7b, 0xe9, 0x1b,
+	0x3e, 0x79, 0xe7, 0xe3, 0x3a, 0x0f, 0xe5, 0x71, 0xda, 0x4d, 0xc5, 0x36,
+	0x19, 0x99, 0xae, 0x85, 0x9b, 0xf0, 0xe6, 0xb4, 0x1c, 0xcd, 0x62, 0x7e,
+	0xe3, 0x7e, 0x2f, 0xe4, 0x9b, 0xa6, 0x25, 0x94, 0xa7, 0x72, 0xc3, 0x91,
+	0x26, 0x51, 0x0f, 0x7c, 0x08, 0x73, 0x8e, 0xca, 0x66, 0xaf, 0xdb, 0xdd,
+	0xa1, 0xa8, 0x0b, 0x2f, 0xab, 0xd1, 0x85, 0xed, 0x56, 0x17, 0x6e, 0xa2,
+	0x2e, 0x04, 0xdc, 0x77, 0xca, 0xe1, 0x22, 0xd7, 0x2f, 0x97, 0x6c, 0x82,
+	0xfe, 0xff, 0x81, 0xc7, 0xb3, 0x27, 0x3a, 0x6e, 0x96, 0x38, 0xac, 0x69,
+	0x99, 0x3a, 0x2d, 0xa5, 0xcf, 0x6a, 0x2c, 0xd2, 0xc6, 0x8e, 0x33, 0x16,
+	0x4a, 0xbd, 0xf7, 0xe3, 0xe0, 0x73, 0x75, 0xf4, 0xde, 0x64, 0xd1, 0xd8,
+	0x6f, 0x0d, 0xb0, 0x09, 0xe5, 0x44, 0x3b, 0xae, 0x8d, 0x3c, 0xab, 0xd0,
+	0xdb, 0xa3, 0x9a, 0xa5, 0xe1, 0x44, 0xab, 0x4c, 0x4c, 0x1b, 0x1b, 0x57,
+	0x9d, 0x00, 0xfe, 0x4f, 0x30, 0xdf, 0x55, 0x74, 0x7e, 0x7e, 0xb6, 0x04,
+	0x3b, 0x77, 0xf6, 0x4e, 0x93, 0xb7, 0x32, 0xdd, 0xa0, 0x7f, 0xd3, 0x06,
+	0xc9, 0xfb, 0x69, 0xe8, 0xbb, 0x98, 0x4c, 0xa0, 0xcf, 0xee, 0x6d, 0x8d,
+	0x98, 0x73, 0x1c, 0x6d, 0xe9, 0xf3, 0x31, 0x8e, 0xd6, 0x28, 0xd1, 0xd9,
+	0xb8, 0xce, 0xad, 0xe7, 0xd9, 0xd1, 0xcc, 0x60, 0x1b, 0xde, 0x31, 0x9f,
+	0xc1, 0xc5, 0x58, 0xa1, 0xec, 0x47, 0xbf, 0x47, 0xc5, 0xee, 0xf7, 0x0c,
+	0x69, 0xfd, 0x17, 0x39, 0xea, 0xda, 0x33, 0x74, 0x83, 0x58, 0xf7, 0x7a,
+	0x7a, 0xd1, 0x18, 0xb9, 0x19, 0xac, 0x9f, 0x3a, 0x15, 0xc5, 0xbd, 0x13,
+	0xf7, 0xb0, 0xbf, 0x50, 0x8f, 0x40, 0x37, 0xbe, 0xb3, 0x6f, 0xa3, 0x34,
+	0x03, 0xdf, 0xb3, 0x0a, 0xb8, 0x36, 0x39, 0x59, 0x39, 0xcd, 0x0b, 0x55,
+	0x7a, 0x78, 0xf2, 0x75, 0xf9, 0x81, 0x34, 0x41, 0x5a, 0xa0, 0x5c, 0x24,
+	0x6d, 0x50, 0x26, 0x3a, 0xfa, 0x6c, 0x03, 0xe9, 0xe1, 0x09, 0xdf, 0x8b,
+	0x70, 0xdf, 0xde, 0xc4, 0xe5, 0x49, 0x1b, 0xa4, 0xf9, 0xa4, 0x8e, 0xd7,
+	0xa7, 0xe5, 0x7b, 0x92, 0x6e, 0xeb, 0x86, 0x5d, 0xf6, 0x2f, 0xbb, 0xc6,
+	0xe6, 0xdc, 0xad, 0xa6, 0x39, 0xe8, 0x26, 0xe6, 0xd0, 0xf5, 0xca, 0xfb,
+	0x2a, 0x39, 0xe0, 0xe1, 0x5e, 0x28, 0xe5, 0x3b, 0x75, 0x5e, 0xe2, 0xee,
+	0xc2, 0x46, 0xb9, 0xc5, 0x8f, 0xd9, 0xb8, 0xfb, 0x41, 0xd0, 0xc1, 0xa2,
+	0x23, 0x27, 0xce, 0xe2, 0x3a, 0xe7, 0x70, 0xfd, 0xce, 0xfb, 0xe9, 0x94,
+	0x22, 0xb3, 0x7b, 0xd1, 0xc4, 0xa2, 0xf4, 0xb9, 0x13, 0xfa, 0x0c, 0xc8,
+	0x82, 0xd3, 0x74, 0xe2, 0xd0, 0x46, 0xe3, 0x4b, 0x03, 0x16, 0xaf, 0xd1,
+	0x1d, 0xa1, 0x2d, 0xe7, 0x07, 0x41, 0x96, 0x76, 0x83, 0x28, 0xed, 0x23,
+	0xc1, 0xe7, 0x43, 0x19, 0xe3, 0x13, 0x5b, 0x9d, 0xc6, 0x53, 0x2f, 0x5a,
+	0x5a, 0x91, 0x88, 0x1a, 0x7a, 0xc6, 0x69, 0x38, 0x71, 0x9c, 0x6b, 0xa6,
+	0xf3, 0xa4, 0x0d, 0x5d, 0x3d, 0xe7, 0x54, 0xe9, 0xea, 0x1b, 0xf6, 0xb7,
+	0x1a, 0x6a, 0x92, 0x74, 0xaa, 0x09, 0xf3, 0x1d, 0x2e, 0x84, 0x30, 0x7e,
+	0x1f, 0x70, 0x11, 0x1e, 0xd0, 0xed, 0xec, 0x9f, 0xe1, 0x5a, 0x02, 0x2c,
+	0xf7, 0x01, 0xee, 0xf3, 0x80, 0xf9, 0x02, 0x2e, 0xd5, 0x11, 0x91, 0x3f,
+	0x76, 0x22, 0xb3, 0xb5, 0xf0, 0x12, 0xc6, 0xd3, 0x16, 0xde, 0xd7, 0x82,
+	0xd5, 0x95, 0xc5, 0x81, 0x2e, 0xc0, 0x43, 0x38, 0x5f, 0x02, 0x8c, 0xb4,
+	0x5b, 0x9f, 0xc7, 0xb3, 0x0b, 0xf8, 0x5e, 0xb0, 0x30, 0x81, 0x1e, 0xa7,
+	0xff, 0x47, 0xf5, 0x77, 0x81, 0x76, 0xf4, 0x9f, 0xdb, 0xe7, 0xce, 0x55,
+	0x32, 0xa0, 0xc7, 0x21, 0x9e, 0xa7, 0x8a, 0x4b, 0xb4, 0x03, 0xc0, 0xf7,
+	0x3f, 0x94, 0xc8, 0xa9, 0x84, 0x1c, 0x2a, 0x70, 0x0f, 0xe8, 0x24, 0xf0,
+	0xa1, 0xcf, 0xa4, 0xa0, 0xce, 0x15, 0xb8, 0xa0, 0xec, 0x67, 0xb7, 0xe3,
+	0xea, 0xc5, 0xf5, 0x56, 0x5c, 0x20, 0x87, 0xd9, 0x13, 0xb8, 0xfa, 0xd0,
+	0xb7, 0x8a, 0x37, 0x09, 0x73, 0xa9, 0xbe, 0x8d, 0x36, 0xda, 0xb6, 0xcc,
+	0xa9, 0xa1, 0x01, 0xe0, 0x6f, 0x00, 0xb0, 0x25, 0x70, 0x31, 0xff, 0xf8,
+	0x87, 0x8e, 0x9c, 0x7a, 0x19, 0x17, 0x18, 0xec, 0x14, 0x08, 0xf3, 0xd4,
+	0x20, 0x2e, 0x28, 0xb1, 0x53, 0x69, 0x5c, 0x23, 0xb8, 0xfe, 0xd2, 0x31,
+	0x3c, 0xd7, 0x09, 0x7c, 0x85, 0x3c, 0x02, 0x9c, 0xaf, 0xe0, 0xb9, 0xaf,
+	0x3b, 0x6f, 0x9c, 0xe7, 0x7e, 0xe2, 0x18, 0x9e, 0x7b, 0xc5, 0xa9, 0xf2,
+	0xdc, 0x59, 0x47, 0x3d, 0xfc, 0x8c, 0x13, 0x79, 0x98, 0xbe, 0xc4, 0x59,
+	0xc7, 0xf0, 0x7f, 0x44, 0x86, 0xf7, 0x82, 0x96, 0x1e, 0x5e, 0xc0, 0x45,
+	0xba, 0x7a, 0x16, 0xe5, 0x2f, 0xac, 0x1a, 0xf7, 0xf9, 0x37, 0x31, 0xee,
+	0xab, 0x76, 0x5c, 0x51, 0xd5, 0x71, 0x2f, 0xa0, 0xef, 0x97, 0xec, 0xb8,
+	0x17, 0x6a, 0xc6, 0x05, 0xad, 0x3c, 0xbc, 0x84, 0x8b, 0x74, 0xf1, 0x22,
+	0xca, 0x43, 0x99, 0x80, 0x85, 0x6e, 0x6e, 0xd0, 0x67, 0x9d, 0xe2, 0x5e,
+	0xc3, 0xb2, 0x6e, 0x4c, 0xd7, 0xe8, 0x87, 0x37, 0xa2, 0x1f, 0x27, 0x8b,
+	0xb4, 0x11, 0x17, 0x6a, 0xe4, 0x02, 0x7d, 0xa3, 0x40, 0x8e, 0x69, 0x3f,
+	0x88, 0x3e, 0x11, 0xfd, 0xa3, 0xd5, 0xb6, 0xd5, 0x27, 0x75, 0xee, 0xd8,
+	0xaf, 0x15, 0x3a, 0xe5, 0xd3, 0x05, 0xda, 0x84, 0xa4, 0x97, 0x20, 0x98,
+	0xd8, 0x41, 0xfb, 0x34, 0x17, 0x5c, 0xe2, 0x91, 0x4e, 0x3c, 0xf7, 0x33,
+	0x6b, 0x75, 0x46, 0x69, 0x18, 0xbe, 0x7b, 0xe6, 0xe8, 0xaf, 0x40, 0x67,
+	0x34, 0x00, 0x6e, 0xd2, 0x5b, 0x87, 0xdc, 0x58, 0x52, 0x53, 0x9b, 0x25,
+	0x21, 0x37, 0x15, 0x1a, 0x61, 0xf7, 0x30, 0xaf, 0xaa, 0x59, 0xba, 0x77,
+	0xc4, 0x4c, 0xde, 0xb7, 0x1b, 0xc7, 0x6f, 0xd7, 0xe4, 0xa1, 0xc7, 0x13,
+	0x78, 0xff, 0x7b, 0x2e, 0xe5, 0x60, 0xdc, 0xbb, 0x56, 0xe7, 0xf4, 0x74,
+	0xed, 0xa0, 0xdd, 0x72, 0xbd, 0xd6, 0xe1, 0xd1, 0x35, 0x76, 0x92, 0xea,
+	0x70, 0xa5, 0x6a, 0xa3, 0x8d, 0x17, 0x52, 0x49, 0xc2, 0xf5, 0x90, 0x70,
+	0xff, 0xeb, 0x1e, 0xc9, 0xfb, 0xad, 0xf0, 0x0b, 0x18, 0x3b, 0x4f, 0xf5,
+	0xd2, 0x36, 0x9a, 0x9d, 0x76, 0x6d, 0x5e, 0xf4, 0x46, 0x79, 0x4e, 0x8f,
+	0xd3, 0xa8, 0x61, 0x34, 0x67, 0x25, 0xb8, 0x8f, 0x10, 0xd3, 0xe7, 0x73,
+	0x66, 0xcb, 0x2d, 0x5a, 0xef, 0xcc, 0x96, 0x99, 0x87, 0x0f, 0x7f, 0xaa,
+	0xcc, 0xbc, 0x7b, 0x5f, 0xdc, 0x77, 0xc2, 0xcf, 0x2d, 0x6f, 0x91, 0xf1,
+	0xe9, 0x75, 0xd2, 0xe8, 0xa9, 0xf8, 0x66, 0xc8, 0x47, 0xb6, 0xe9, 0xda,
+	0x01, 0xff, 0x70, 0x66, 0xab, 0x3c, 0x39, 0xc3, 0xbe, 0x3b, 0x64, 0x6e,
+	0x5e, 0x1c, 0xf7, 0x9d, 0xeb, 0x51, 0x07, 0x72, 0x7d, 0x07, 0xcb, 0x92,
+	0xb8, 0x8b, 0x72, 0xdf, 0x19, 0x95, 0x73, 0x03, 0x7c, 0x66, 0xee, 0xbf,
+	0x44, 0xd9, 0xdf, 0xb9, 0x81, 0x4e, 0x79, 0x7c, 0x1e, 0x34, 0x01, 0xb9,
+	0x3f, 0x72, 0x82, 0x30, 0x89, 0xec, 0x9a, 0x65, 0x2c, 0xbd, 0xdb, 0x65,
+	0xdc, 0x94, 0xfb, 0x34, 0xb7, 0x0c, 0x70, 0x2c, 0xe8, 0x25, 0xe8, 0xb8,
+	0xae, 0x1d, 0x46, 0x16, 0xa4, 0x67, 0x1b, 0x50, 0xce, 0x7e, 0xe1, 0x3f,
+	0xee, 0x65, 0x3f, 0x61, 0x5b, 0x85, 0x39, 0x35, 0x6a, 0x7a, 0x59, 0x5a,
+	0xa5, 0x3f, 0xce, 0xfc, 0x4c, 0xf6, 0x37, 0xfb, 0xe8, 0xd5, 0x7b, 0x21,
+	0xdc, 0x53, 0x36, 0xb6, 0x15, 0xd7, 0x44, 0xef, 0x29, 0xc0, 0xae, 0xba,
+	0x42, 0xdb, 0x17, 0x73, 0x15, 0xae, 0x20, 0x63, 0x51, 0xe1, 0x1a, 0x25,
+	0xe4, 0xd1, 0xe2, 0xf2, 0x3a, 0x6d, 0x69, 0x58, 0xb9, 0x4e, 0xa4, 0x15,
+	0x7f, 0xcc, 0xda, 0x1e, 0x8b, 0x92, 0x83, 0x5d, 0xd6, 0xab, 0xd7, 0x6c,
+	0x11, 0xb6, 0xac, 0x5d, 0x33, 0x6d, 0xcf, 0xe6, 0xc3, 0x35, 0x1b, 0x85,
+	0xc6, 0x29, 0xab, 0x4d, 0x5c, 0x33, 0x97, 0xf1, 0x6e, 0xe0, 0x3d, 0x87,
+	0x75, 0xca, 0x61, 0x8d, 0x72, 0xe5, 0x0e, 0x99, 0x3d, 0xa6, 0x3a, 0x1b,
+	0x44, 0x92, 0xe3, 0x5e, 0x87, 0x4c, 0xce, 0x33, 0x96, 0xb0, 0x05, 0x36,
+	0xd8, 0x56, 0x5c, 0x9d, 0x78, 0x66, 0x3b, 0xf0, 0x54, 0x59, 0xa1, 0x6d,
+	0xd3, 0x1a, 0x3b, 0xeb, 0x71, 0x8c, 0xcd, 0x1c, 0xe1, 0x27, 0x80, 0x87,
+	0x2a, 0xef, 0x4c, 0xd5, 0xc4, 0x9f, 0x38, 0x57, 0xad, 0x43, 0x31, 0xdf,
+	0xb8, 0x5e, 0x4f, 0x1d, 0x87, 0x2a, 0x36, 0xbe, 0x19, 0x7b, 0x2a, 0x41,
+	0x7b, 0x2a, 0x5b, 0x72, 0xcd, 0xf9, 0x80, 0x51, 0xf8, 0x4e, 0x5e, 0xef,
+	0x26, 0xd2, 0xfa, 0xd8, 0x0c, 0xe1, 0x8a, 0x85, 0x70, 0xad, 0x58, 0x33,
+	0x9e, 0xe7, 0x5a, 0x1b, 0xe7, 0x98, 0x5a, 0xce, 0x5f, 0x34, 0xb1, 0x7d,
+	0xc6, 0x51, 0x3a, 0xeb, 0xc0, 0x74, 0xa7, 0xb6, 0x61, 0x45, 0x8d, 0xc9,
+	0x81, 0x22, 0xcf, 0x82, 0x31, 0x9e, 0x78, 0x23, 0xe3, 0x49, 0xbd, 0xb3,
+	0xf2, 0x5e, 0x8c, 0xcd, 0x5c, 0x1d, 0x65, 0xe3, 0x37, 0x1b, 0x6c, 0x8e,
+	0x48, 0x6d, 0x0c, 0xc7, 0xe4, 0xf2, 0xac, 0xcc, 0x8b, 0x4e, 0x8d, 0x2e,
+	0x61, 0x9d, 0x7f, 0x5d, 0xef, 0x0d, 0x4a, 0x29, 0x02, 0xed, 0x37, 0x3e,
+	0x90, 0x1a, 0x34, 0xe7, 0x60, 0x92, 0xb2, 0xb3, 0x68, 0xe6, 0x7f, 0x5e,
+	0xe7, 0xf4, 0x98, 0xdc, 0x45, 0x93, 0xef, 0x73, 0x8f, 0x9c, 0x87, 0x0e,
+	0xaf, 0xae, 0x6d, 0x93, 0x4c, 0x02, 0x17, 0x59, 0xbd, 0x2f, 0x91, 0x94,
+	0xec, 0xc0, 0xc7, 0x37, 0xf1, 0x9c, 0x44, 0x0c, 0xeb, 0x93, 0x9f, 0xe1,
+	0xd9, 0x49, 0xf6, 0x7b, 0xb1, 0xbe, 0x28, 0x66, 0x99, 0x87, 0x0f, 0x59,
+	0xf9, 0xb6, 0xbe, 0x44, 0xb3, 0x7e, 0xbf, 0xce, 0xe6, 0x5b, 0x3b, 0x22,
+	0x37, 0x06, 0xf2, 0x87, 0x10, 0x9f, 0x8f, 0xd9, 0x39, 0x25, 0x75, 0xcc,
+	0x4a, 0x82, 0x73, 0x7e, 0xc2, 0xc6, 0x2c, 0x39, 0x97, 0x1b, 0x2c, 0x7d,
+	0x1b, 0xfb, 0xa7, 0x6a, 0x43, 0x9b, 0x7d, 0xbf, 0x27, 0xb5, 0x2c, 0xec,
+	0xb7, 0xb6, 0xb3, 0x8e, 0xf3, 0x1c, 0x17, 0x9d, 0x13, 0x10, 0xfa, 0x46,
+	0x3d, 0x35, 0x7e, 0x81, 0xf1, 0xe5, 0xf2, 0xd3, 0xf5, 0x64, 0x54, 0xd5,
+	0x27, 0xa4, 0x2f, 0x37, 0xb1, 0x8d, 0xdf, 0x2d, 0x08, 0x7d, 0xb9, 0x7e,
+	0xeb, 0xcb, 0xb5, 0x6a, 0x5f, 0xce, 0xc4, 0x1e, 0x5a, 0x97, 0x7d, 0xb9,
+	0xfc, 0x74, 0x0e, 0xb4, 0x12, 0x7e, 0x67, 0xc1, 0xd8, 0x42, 0x93, 0x05,
+	0x9e, 0x79, 0x69, 0x94, 0xec, 0xa8, 0x82, 0xdf, 0x60, 0x7c, 0x2c, 0xc6,
+	0x2a, 0x94, 0xfa, 0x96, 0xf5, 0x2f, 0x3a, 0x25, 0xdd, 0xbe, 0x0e, 0xf3,
+	0xbe, 0x53, 0xaf, 0xf9, 0x5c, 0xc1, 0xec, 0x7d, 0x66, 0xf7, 0x32, 0x26,
+	0xc4, 0x73, 0x4d, 0x9a, 0xbf, 0x92, 0xc3, 0x91, 0x5e, 0x63, 0xcf, 0x7a,
+	0xdf, 0x04, 0xde, 0x4f, 0x02, 0xe7, 0x31, 0x3b, 0x6e, 0x12, 0x30, 0x1d,
+	0xc0, 0xda, 0x5c, 0x6b, 0x65, 0x32, 0xc7, 0xde, 0xd3, 0xc4, 0xd8, 0xc0,
+	0x7c, 0x21, 0x8c, 0x11, 0x46, 0xec, 0x99, 0x4a, 0x2f, 0xd2, 0xe8, 0xad,
+	0xab, 0x6b, 0xab, 0x9e, 0x7e, 0x5d, 0xdd, 0x44, 0x5a, 0xba, 0x53, 0xe7,
+	0xb9, 0xac, 0x1f, 0x48, 0xed, 0xd1, 0x39, 0xf2, 0x3a, 0xc6, 0x98, 0x13,
+	0xe6, 0x94, 0x7d, 0x57, 0xde, 0xa1, 0x65, 0xfe, 0x01, 0x9f, 0xfa, 0x6b,
+	0x87, 0xfe, 0xdd, 0x38, 0x14, 0x04, 0xe7, 0x06, 0xee, 0x86, 0xad, 0xe2,
+	0xb9, 0xdf, 0x97, 0xee, 0xc4, 0xb0, 0xb6, 0x9d, 0xb0, 0x46, 0x7b, 0x9b,
+	0x65, 0x9d, 0x77, 0xb3, 0xcd, 0x99, 0xc9, 0x41, 0x6e, 0xa6, 0x60, 0x33,
+	0xf1, 0x4c, 0x70, 0x8f, 0x7d, 0x97, 0x0b, 0x9a, 0x41, 0x47, 0x1f, 0x13,
+	0x23, 0x63, 0xb2, 0x55, 0x19, 0xc3, 0x5c, 0x83, 0x34, 0x09, 0x39, 0x7a,
+	0x44, 0x52, 0xfc, 0xee, 0x07, 0xc7, 0xce, 0xcb, 0xa5, 0xd0, 0xcb, 0x6c,
+	0xa7, 0xbf, 0xd9, 0x83, 0x67, 0xee, 0xe1, 0x78, 0xee, 0x41, 0xe8, 0x96,
+	0xeb, 0xd7, 0xea, 0x96, 0x04, 0xfd, 0xfa, 0x6c, 0x89, 0xbe, 0xe1, 0x7a,
+	0xb4, 0xe9, 0x90, 0x8f, 0x4f, 0x77, 0xb7, 0x91, 0xb7, 0xc6, 0x20, 0xd7,
+	0xd5, 0xfd, 0xe1, 0x59, 0x20, 0x96, 0xf1, 0x3d, 0xfb, 0x6d, 0x92, 0xe4,
+	0xfb, 0x5d, 0xf9, 0x7c, 0x25, 0x95, 0x5c, 0x82, 0x6e, 0x1a, 0x73, 0x7e,
+	0xf1, 0x72, 0x13, 0x53, 0x7d, 0x7b, 0x9b, 0x39, 0x3b, 0xd0, 0x4c, 0x9b,
+	0xdd, 0xc6, 0x59, 0x6b, 0x69, 0x76, 0xc9, 0xca, 0xe3, 0x20, 0x68, 0x1e,
+	0xd0, 0x32, 0x78, 0x0f, 0x65, 0xf0, 0x01, 0xbf, 0xc7, 0xd0, 0xbe, 0xf6,
+	0x99, 0x02, 0xac, 0x23, 0xf0, 0x30, 0x10, 0x65, 0x7e, 0x9e, 0xe5, 0x4f,
+	0x2f, 0xbd, 0x68, 0xe5, 0x92, 0x72, 0xd6, 0xf2, 0xa5, 0xba, 0x2a, 0xb6,
+	0x42, 0xe6, 0x1e, 0x9a, 0xa6, 0x3e, 0xf6, 0x17, 0xbe, 0x0b, 0x39, 0x95,
+	0xd5, 0x78, 0xe8, 0x90, 0xfb, 0xa6, 0x25, 0x7d, 0x1e, 0xba, 0x2a, 0x3f,
+	0xbf, 0x92, 0x37, 0xd7, 0xf6, 0xc7, 0xb9, 0x7e, 0xb8, 0xcd, 0xf8, 0xb6,
+	0x2b, 0xe7, 0xba, 0x80, 0xb9, 0xa6, 0xf5, 0x5c, 0xb9, 0x6f, 0xf3, 0x31,
+	0x3b, 0xd7, 0xf5, 0xe1, 0x5c, 0x07, 0x57, 0xce, 0x35, 0xf4, 0xed, 0x43,
+	0xb9, 0x9b, 0xd4, 0xf9, 0xf2, 0x3a, 0x4f, 0x7b, 0x7a, 0xbd, 0x0c, 0x97,
+	0x5a, 0xad, 0xbc, 0x74, 0xa1, 0x7b, 0x98, 0xc3, 0xbe, 0x70, 0xaf, 0x2b,
+	0x16, 0x67, 0x8a, 0x78, 0xa0, 0xac, 0x6d, 0xd3, 0x67, 0x6c, 0x66, 0xe1,
+	0x5f, 0xdd, 0x5a, 0x60, 0xdd, 0xf0, 0xfd, 0xc5, 0x62, 0xc7, 0xa1, 0x4f,
+	0x4d, 0xbf, 0xa9, 0x77, 0x4d, 0x4c, 0xc1, 0xc4, 0x87, 0x19, 0x17, 0x36,
+	0x67, 0x7f, 0x99, 0x8b, 0x78, 0x07, 0x78, 0xea, 0x53, 0x85, 0xd4, 0x60,
+	0x26, 0x42, 0x39, 0x7a, 0x5c, 0x0e, 0x55, 0x46, 0xa4, 0x4b, 0x9f, 0xff,
+	0x7c, 0xdd, 0xd8, 0x71, 0xba, 0x36, 0x76, 0xcc, 0x74, 0x02, 0xc6, 0x8e,
+	0xf7, 0xfc, 0x0c, 0xb1, 0x63, 0x71, 0x4c, 0xec, 0xb8, 0x9e, 0x7f, 0x35,
+	0x55, 0x3c, 0x8e, 0x79, 0x35, 0x43, 0x96, 0x2c, 0x3a, 0xd9, 0xf9, 0x16,
+	0xdc, 0xcf, 0xe2, 0x1e, 0xc3, 0xfd, 0x3c, 0xee, 0x2e, 0xee, 0x17, 0x70,
+	0x8f, 0xcb, 0xd4, 0xb2, 0xce, 0x38, 0x0e, 0xb9, 0x41, 0x5d, 0xc6, 0xb6,
+	0xc6, 0x1f, 0x98, 0x2b, 0xb7, 0xf3, 0x7b, 0x2d, 0xce, 0xec, 0x3c, 0xe7,
+	0xd0, 0x2a, 0x93, 0xd3, 0x94, 0xd9, 0x6d, 0x52, 0x9a, 0x0e, 0x6d, 0xdb,
+	0x9f, 0xef, 0xe0, 0x9e, 0xc1, 0x98, 0x84, 0xb6, 0xeb, 0x3d, 0x1d, 0x66,
+	0xaf, 0xf1, 0x3b, 0x58, 0xe3, 0x8d, 0x58, 0x83, 0x93, 0x72, 0x7e, 0x66,
+	0xe3, 0x0a, 0x1b, 0x36, 0x69, 0x63, 0x82, 0x33, 0x56, 0xf7, 0xd6, 0x97,
+	0x11, 0xb5, 0xeb, 0x9f, 0xb0, 0x67, 0xcb, 0xc2, 0x1c, 0xa1, 0xa4, 0x5e,
+	0x9f, 0xd1, 0xca, 0x71, 0x8c, 0x37, 0x28, 0xe9, 0x19, 0xce, 0x73, 0xf9,
+	0x9b, 0x11, 0x90, 0x87, 0x27, 0xa0, 0x57, 0x57, 0xd0, 0x25, 0xe8, 0x96,
+	0x73, 0x73, 0x40, 0xbb, 0x8f, 0xca, 0x6c, 0x89, 0xf0, 0xf5, 0x24, 0x22,
+	0xfa, 0xac, 0x19, 0x9e, 0x67, 0x4c, 0x8e, 0xfb, 0x70, 0x25, 0x3c, 0x67,
+	0xb6, 0x89, 0x67, 0x07, 0x57, 0x9d, 0x35, 0xb3, 0xfa, 0x59, 0xdb, 0x0e,
+	0x3c, 0x73, 0x16, 0xce, 0xa1, 0x1e, 0x3d, 0x05, 0x32, 0xa9, 0xf3, 0xce,
+	0x36, 0xcb, 0x63, 0x0f, 0x2e, 0xe7, 0xbc, 0xb6, 0xc1, 0x46, 0xe9, 0x84,
+	0x89, 0x3c, 0x1a, 0x1d, 0xea, 0x81, 0x8f, 0xc7, 0x3c, 0x99, 0x9e, 0xc4,
+	0x6d, 0x3a, 0x17, 0xb9, 0x7a, 0xee, 0xaf, 0x9a, 0x8f, 0x1c, 0x9e, 0xb3,
+	0x4a, 0xe8, 0xef, 0x5a, 0xec, 0xd4, 0xe5, 0x71, 0xcc, 0x87, 0xfb, 0x7e,
+	0x1a, 0x0f, 0x09, 0x7e, 0xa7, 0xeb, 0x29, 0xe0, 0x60, 0xb2, 0xf2, 0x6d,
+	0xd0, 0xbb, 0x63, 0xcf, 0x9c, 0x91, 0xc6, 0x06, 0x64, 0xa2, 0x9c, 0x70,
+	0x26, 0xca, 0x03, 0xce, 0xbe, 0xb2, 0x7d, 0x37, 0xb0, 0x67, 0xb3, 0x34,
+	0xe3, 0xf7, 0x4c, 0x97, 0x33, 0x06, 0x7c, 0xe5, 0x8b, 0xdd, 0x4e, 0x5a,
+	0xdf, 0x3d, 0x7b, 0x87, 0x1c, 0xc0, 0x5a, 0x0d, 0xcf, 0xc4, 0xb5, 0x9c,
+	0xaf, 0x7e, 0x5b, 0x2a, 0x5c, 0x57, 0x7e, 0x13, 0x89, 0x7c, 0x7c, 0x5c,
+	0x7f, 0xe7, 0xc8, 0xd8, 0x0e, 0x27, 0xd1, 0xdf, 0x71, 0x1b, 0x13, 0xef,
+	0x73, 0xb2, 0xba, 0x1f, 0xb3, 0x1e, 0xf9, 0xe2, 0x09, 0xdc, 0x57, 0x9f,
+	0x79, 0x0e, 0xf5, 0x8c, 0x85, 0xbb, 0x10, 0xdc, 0x63, 0xe4, 0xd5, 0x71,
+	0x99, 0xaa, 0x30, 0x7f, 0xc4, 0xd1, 0x7c, 0x34, 0x59, 0x3e, 0x00, 0x9d,
+	0xb4, 0xf2, 0xcc, 0xdf, 0xce, 0xea, 0x3a, 0x24, 0x67, 0x84, 0xb0, 0x70,
+	0x0d, 0x56, 0x9e, 0x87, 0xbf, 0xf8, 0xbf, 0x70, 0x5f, 0xd1, 0xc8, 0x50,
+	0x0b, 0x47, 0x9a, 0xf2, 0xce, 0xc8, 0x95, 0x69, 0x39, 0x08, 0x78, 0x0e,
+	0xe3, 0x52, 0xf7, 0xf3, 0x3b, 0x2c, 0xf3, 0x92, 0x9f, 0xbb, 0x4f, 0xd4,
+	0x43, 0xe7, 0x9d, 0xe8, 0x43, 0x07, 0x25, 0xf2, 0xd0, 0xa2, 0xd3, 0xf0,
+	0x50, 0xb7, 0xf6, 0xcb, 0x77, 0xfb, 0xdd, 0x89, 0x7d, 0x72, 0x52, 0xa2,
+	0xf7, 0x2b, 0x7d, 0xfe, 0x2b, 0xef, 0x32, 0xc6, 0x77, 0x52, 0x22, 0xf7,
+	0xc7, 0xec, 0xd9, 0x51, 0x13, 0xd7, 0x5b, 0xd2, 0x7c, 0xff, 0x9b, 0x71,
+	0xe2, 0x6c, 0x49, 0x8e, 0x6b, 0xde, 0x19, 0x86, 0x9e, 0xc8, 0x94, 0x92,
+	0xcb, 0x75, 0x4c, 0xbe, 0xe7, 0xf3, 0x9b, 0x0d, 0xbf, 0xb0, 0x4e, 0x8f,
+	0xc3, 0xef, 0x38, 0x18, 0x9d, 0x91, 0xb9, 0x2c, 0xcc, 0xfd, 0x34, 0x6b,
+	0xca, 0xf7, 0x67, 0xb1, 0x86, 0x3d, 0x58, 0x2f, 0x8e, 0xe7, 0xe8, 0xfd,
+	0x5c, 0x9e, 0x9d, 0x75, 0xa5, 0x2f, 0xd1, 0xb4, 0x6c, 0x07, 0xb1, 0xee,
+	0x7d, 0xd2, 0x04, 0xb8, 0xd5, 0x43, 0x79, 0x63, 0xd7, 0x09, 0xe9, 0x54,
+	0x20, 0xb9, 0x49, 0xb3, 0x3d, 0x83, 0xbb, 0xf5, 0x1a, 0xde, 0x6b, 0x69,
+	0x66, 0x9d, 0xb1, 0x1f, 0xf1, 0x6c, 0xe8, 0x22, 0x2f, 0xbb, 0xa6, 0x7f,
+	0x08, 0x3d, 0xcf, 0x7d, 0x17, 0x6d, 0x2f, 0xd6, 0xb1, 0x05, 0xc9, 0x4b,
+	0xcf, 0x58, 0xbf, 0x32, 0x08, 0xa6, 0x7d, 0x1f, 0x78, 0xac, 0xe7, 0x4b,
+	0x6e, 0x71, 0xe6, 0x4a, 0x5b, 0x9d, 0xd9, 0x52, 0x20, 0x13, 0x3e, 0xbf,
+	0xe3, 0xc1, 0x1c, 0x00, 0xda, 0x5b, 0x2c, 0xeb, 0x86, 0x6e, 0xfd, 0xeb,
+	0xcd, 0x3c, 0x8f, 0x74, 0x93, 0xf7, 0xa2, 0x98, 0x7a, 0xc4, 0x31, 0x7d,
+	0xe4, 0xee, 0xe3, 0x59, 0xe1, 0xf7, 0x34, 0xfa, 0x12, 0x71, 0xfd, 0x5d,
+	0x8f, 0xcf, 0xa1, 0x1d, 0xc6, 0x28, 0x72, 0xdc, 0x67, 0x9d, 0x59, 0xc8,
+	0xb3, 0xb9, 0x69, 0x9e, 0xe1, 0x67, 0x3e, 0x6d, 0xa4, 0x53, 0xc9, 0x15,
+	0xee, 0xa4, 0xfd, 0x06, 0x5c, 0x0e, 0x2e, 0x50, 0x44, 0x97, 0xf5, 0xb9,
+	0xe3, 0xcb, 0xdf, 0x85, 0x0b, 0xcb, 0xc2, 0xef, 0xc3, 0x29, 0x9d, 0x3b,
+	0x0d, 0x5f, 0xf6, 0xb1, 0x31, 0xf9, 0x89, 0x33, 0x5f, 0x78, 0xc5, 0x79,
+	0xb4, 0x90, 0xbe, 0xea, 0x12, 0xd0, 0xc7, 0x39, 0xbf, 0x97, 0xf2, 0x0b,
+	0x36, 0x5f, 0x41, 0x72, 0x95, 0x09, 0x99, 0xe9, 0xe8, 0x76, 0xef, 0xd7,
+	0x6b, 0x33, 0x03, 0x9c, 0x7d, 0x1b, 0xeb, 0xf7, 0xc9, 0x38, 0xf5, 0xdb,
+	0x78, 0x41, 0x81, 0x97, 0xd5, 0xcf, 0xe3, 0x82, 0x6d, 0xdb, 0xa8, 0x6d,
+	0x94, 0x7d, 0x3e, 0xeb, 0x6d, 0x75, 0x86, 0x4b, 0x5b, 0xb0, 0x8e, 0x7b,
+	0xa1, 0x3f, 0x1d, 0xd8, 0x69, 0xa0, 0x6d, 0x94, 0x4d, 0x02, 0x07, 0xe3,
+	0xbe, 0x91, 0xe7, 0xc3, 0x92, 0xd3, 0x3e, 0x9e, 0xb9, 0xa7, 0x95, 0x89,
+	0x99, 0x05, 0xc1, 0x1c, 0xec, 0x83, 0x6c, 0x7f, 0x09, 0xbc, 0xf0, 0x08,
+	0xae, 0xb7, 0xdb, 0x3d, 0xed, 0x17, 0x2e, 0xb2, 0xa7, 0xed, 0xca, 0xc9,
+	0x8a, 0x3e, 0xd7, 0xae, 0xf3, 0xab, 0x92, 0xea, 0xbf, 0x5f, 0xa2, 0xd7,
+	0x4a, 0xf5, 0xe8, 0x9c, 0xb4, 0xb4, 0x7c, 0x38, 0x6e, 0xf4, 0x30, 0x61,
+	0x4a, 0x02, 0x9e, 0xad, 0xc0, 0x05, 0xe1, 0x31, 0x6d, 0x44, 0x6d, 0xba,
+	0x94, 0xfa, 0x70, 0x49, 0x3e, 0x12, 0x0f, 0xcf, 0x14, 0xa0, 0x1f, 0xc8,
+	0xb8, 0x8f, 0x5d, 0x6a, 0xf4, 0xe4, 0xe6, 0x3a, 0xfd, 0x84, 0x73, 0x73,
+	0xec, 0xdc, 0x48, 0xb7, 0x7f, 0x96, 0xa0, 0x4f, 0xb1, 0x24, 0x4d, 0xab,
+	0xea, 0x33, 0xa6, 0xbf, 0xe1, 0x72, 0x73, 0x46, 0x81, 0x75, 0x5d, 0xd8,
+	0xa6, 0xb4, 0x73, 0x89, 0x47, 0xbd, 0x6e, 0x05, 0x25, 0x3c, 0x67, 0x00,
+	0x6e, 0xae, 0x5c, 0xe1, 0xbe, 0x43, 0x91, 0x0e, 0x43, 0x5c, 0x7f, 0x5b,
+	0xf3, 0xc9, 0x78, 0x81, 0xb1, 0x95, 0x47, 0x83, 0xf4, 0x28, 0x79, 0x8c,
+	0x7d, 0xf0, 0x7d, 0x41, 0xc7, 0x73, 0xf7, 0xfa, 0x8c, 0x15, 0x75, 0x1f,
+	0xbf, 0x43, 0x85, 0x72, 0x0a, 0xfa, 0xb7, 0xb8, 0xe8, 0xf0, 0x1b, 0x78,
+	0x37, 0x0a, 0xee, 0xf3, 0x8b, 0xce, 0x77, 0xa7, 0x9f, 0xc5, 0x73, 0x83,
+	0xfd, 0xee, 0x9d, 0xd1, 0x53, 0x22, 0xc5, 0x70, 0xbe, 0x89, 0x1c, 0xd6,
+	0xfe, 0x02, 0xd6, 0xbe, 0xfe, 0x77, 0xee, 0xf0, 0xae, 0x8c, 0x77, 0xe5,
+	0x0f, 0x07, 0xe9, 0x36, 0xd2, 0x22, 0xe9, 0xef, 0xb5, 0xfc, 0xe6, 0x41,
+	0xcd, 0x17, 0x93, 0xc5, 0xc7, 0xc1, 0x17, 0x69, 0xee, 0x37, 0x07, 0x0f,
+	0xfb, 0x37, 0x80, 0x2f, 0xf6, 0xc8, 0xef, 0xc3, 0x2e, 0xf8, 0xdd, 0xca,
+	0x10, 0xf8, 0x63, 0x10, 0xfc, 0x32, 0x00, 0x1e, 0xf1, 0xb5, 0x8d, 0xfc,
+	0x04, 0xf4, 0x1f, 0xf4, 0x9a, 0xb3, 0xaf, 0xd4, 0xe5, 0x64, 0x4b, 0x9e,
+	0x33, 0x51, 0xe2, 0xf7, 0x5a, 0xd4, 0x5b, 0x1b, 0x24, 0x9a, 0x98, 0x13,
+	0xf2, 0x42, 0x37, 0x73, 0x1c, 0xdb, 0x81, 0xab, 0x53, 0xc4, 0xd5, 0x5c,
+	0xa5, 0xcf, 0xbd, 0x04, 0x3c, 0xd1, 0xae, 0x79, 0xa2, 0xd5, 0x49, 0xbb,
+	0x37, 0x58, 0x9e, 0x78, 0x11, 0x3c, 0x71, 0x7e, 0x0d, 0x4f, 0x3c, 0x6d,
+	0xe9, 0x7f, 0xa1, 0x86, 0x27, 0xe6, 0x6c, 0xd9, 0xcc, 0x45, 0x78, 0xe2,
+	0x52, 0x2f, 0xf5, 0xa5, 0x31, 0x79, 0x15, 0x3c, 0x21, 0x8a, 0x3c, 0x71,
+	0xa9, 0xe6, 0x09, 0xc6, 0x8e, 0xc8, 0x17, 0x9d, 0x90, 0x23, 0xe4, 0x8b,
+	0xb3, 0xb2, 0x04, 0xbe, 0x78, 0x5e, 0x71, 0xec, 0x19, 0xda, 0x0a, 0x25,
+	0xfa, 0x64, 0x27, 0x8a, 0x5d, 0xe0, 0x77, 0x25, 0xff, 0x65, 0x3a, 0x08,
+	0x16, 0xe1, 0xa7, 0x3f, 0x08, 0x7b, 0x3e, 0xaa, 0xbf, 0xa9, 0xb8, 0x00,
+	0xba, 0x0f, 0xe9, 0x7d, 0xc2, 0x01, 0xbd, 0x1f, 0x9e, 0xc5, 0x1c, 0x26,
+	0xd4, 0x7f, 0x86, 0x2f, 0xec, 0x62, 0x5d, 0x69, 0xe7, 0x1f, 0xd3, 0x3c,
+	0xd4, 0x00, 0x7d, 0xf0, 0xe8, 0x00, 0x63, 0x4d, 0x9e, 0xbb, 0x4f, 0x75,
+	0xe7, 0x46, 0x00, 0x73, 0x44, 0xdd, 0x2f, 0x8c, 0x73, 0xb4, 0xad, 0xb2,
+	0xf3, 0x29, 0x23, 0x46, 0x21, 0xeb, 0xcc, 0xbb, 0x5c, 0xd0, 0x04, 0x9b,
+	0xb4, 0x49, 0x19, 0x1b, 0x5d, 0xed, 0x48, 0xb9, 0x1f, 0x84, 0x00, 0x6d,
+	0x84, 0xbd, 0xb0, 0x0b, 0xab, 0x3d, 0x52, 0xa8, 0xb5, 0xf1, 0xff, 0x03,
+	0x6c, 0x7c, 0xb6, 0x91, 0xa8, 0xb1, 0xf1, 0x7f, 0xcd, 0xf2, 0x1a, 0x7f,
+	0xbb, 0xda, 0xde, 0x3f, 0x00, 0xf8, 0x76, 0x2f, 0xdb, 0xfb, 0xec, 0x83,
+	0x76, 0x87, 0xc8, 0xf5, 0xb0, 0xf9, 0xde, 0x0d, 0x1e, 0xbc, 0x01, 0xbe,
+	0xd4, 0x7b, 0x0a, 0xae, 0xec, 0x29, 0xb4, 0xc3, 0xe7, 0xee, 0x94, 0xf7,
+	0x4e, 0x6f, 0x95, 0x9d, 0x25, 0xff, 0x12, 0x69, 0xee, 0x80, 0x8d, 0x5a,
+	0x00, 0x9c, 0x11, 0x2b, 0xb7, 0xcf, 0x02, 0x6f, 0xdd, 0xc9, 0x9f, 0xa8,
+	0x17, 0xad, 0x5d, 0xc4, 0xb3, 0x8e, 0xf5, 0xfa, 0x89, 0xa3, 0x3d, 0x63,
+	0x29, 0x1d, 0x72, 0xea, 0x18, 0xbd, 0xaf, 0x24, 0xec, 0x72, 0x1f, 0x36,
+	0xc9, 0x16, 0xf4, 0xc7, 0x78, 0xf2, 0x46, 0x79, 0xfa, 0xaa, 0xe8, 0x5d,
+	0x59, 0xcd, 0x87, 0x9d, 0x4e, 0x66, 0x1a, 0x3e, 0xc0, 0xde, 0x18, 0xe6,
+	0xa0, 0xda, 0x37, 0xcb, 0x75, 0xb2, 0x53, 0xcf, 0x67, 0x46, 0x0e, 0x42,
+	0x37, 0xff, 0x41, 0x61, 0xa7, 0x2c, 0x8d, 0xb6, 0xe1, 0x39, 0x26, 0x4f,
+	0x17, 0xfa, 0xe0, 0xfb, 0xbc, 0x0b, 0x38, 0x6a, 0xc4, 0x73, 0xa3, 0x0c,
+	0x5f, 0x42, 0x5e, 0x6d, 0x91, 0x45, 0x94, 0xbf, 0x5b, 0x7e, 0xc1, 0x96,
+	0xb3, 0x8c, 0xbc, 0xd1, 0x82, 0xb6, 0x31, 0x39, 0x57, 0xa0, 0x5d, 0xa9,
+	0x79, 0x62, 0xf0, 0x7b, 0xd2, 0x97, 0xfe, 0x1e, 0xec, 0xd4, 0xb3, 0xb8,
+	0x9e, 0x91, 0xd4, 0x9e, 0x71, 0xa7, 0x2f, 0xd9, 0xed, 0x40, 0x77, 0xe2,
+	0x8a, 0x3a, 0x7d, 0x6e, 0xa3, 0x73, 0x85, 0xed, 0xa3, 0x41, 0x9e, 0xd9,
+	0xab, 0x12, 0x2d, 0x58, 0x93, 0xed, 0x4e, 0x8f, 0x2d, 0xe3, 0x73, 0xca,
+	0x78, 0x40, 0xa7, 0xd4, 0x96, 0x0d, 0x22, 0x5d, 0x2d, 0xb0, 0x79, 0x26,
+	0x44, 0xb5, 0xb7, 0x48, 0x54, 0xba, 0x67, 0x55, 0x27, 0xca, 0x3c, 0x5b,
+	0x16, 0x6f, 0x81, 0x7e, 0x40, 0x59, 0x07, 0xca, 0xb6, 0xd9, 0xb2, 0xb6,
+	0x16, 0x69, 0x44, 0xd9, 0x8c, 0xe6, 0xf9, 0xf3, 0x3d, 0x9e, 0x9b, 0x75,
+	0x9a, 0xa5, 0xeb, 0x44, 0x0b, 0x64, 0xc3, 0x46, 0x59, 0xbc, 0xaa, 0x49,
+	0xba, 0xf0, 0x8e, 0x71, 0x6e, 0xff, 0x44, 0x4c, 0xae, 0x3d, 0xd1, 0x9d,
+	0xf8, 0x38, 0xe6, 0xd0, 0x7d, 0x8a, 0x71, 0xef, 0xfc, 0x25, 0x8c, 0xfb,
+	0x74, 0x9d, 0xe2, 0xbd, 0x49, 0xcb, 0x1f, 0xe2, 0xc3, 0x7c, 0x93, 0x88,
+	0x32, 0xf9, 0x24, 0xfc, 0x5c, 0xea, 0xf0, 0x6e, 0xfb, 0xfd, 0x8c, 0xe3,
+	0x97, 0xd0, 0x6f, 0x9b, 0xa5, 0x5d, 0x52, 0x24, 0x3f, 0x52, 0x0f, 0xe1,
+	0x3e, 0xe3, 0x48, 0xbe, 0x2a, 0xb3, 0xe6, 0xc9, 0x57, 0xc7, 0x14, 0x73,
+	0x59, 0x50, 0x56, 0xf9, 0xc5, 0xc0, 0xac, 0x31, 0x79, 0xc1, 0xc8, 0xa5,
+	0x0f, 0x18, 0xb9, 0xf4, 0xd8, 0x99, 0x15, 0x72, 0xe9, 0xbc, 0x96, 0x4b,
+	0x7b, 0x05, 0xf7, 0xf9, 0xf3, 0x90, 0x4b, 0x2f, 0xe2, 0xd9, 0xd5, 0x72,
+	0x29, 0x2e, 0xd6, 0x5e, 0x96, 0xaf, 0xea, 0xf1, 0xe7, 0x8a, 0x51, 0x6d,
+	0x57, 0xe5, 0x67, 0x60, 0x93, 0x14, 0xa7, 0xac, 0xfe, 0x96, 0xa1, 0x36,
+	0xe9, 0x19, 0xfc, 0xa9, 0x84, 0x36, 0xe7, 0x7f, 0xba, 0x84, 0xdf, 0xee,
+	0x7c, 0x5e, 0x51, 0x86, 0xbd, 0x0a, 0x19, 0x26, 0xaa, 0xbe, 0x0c, 0xc3,
+	0xbb, 0x32, 0xde, 0x95, 0xd9, 0xef, 0x8f, 0x7e, 0x3a, 0xe6, 0x52, 0x7e,
+	0x50, 0x66, 0x40, 0x26, 0x15, 0x21, 0x93, 0x8a, 0x90, 0x53, 0x45, 0xc8,
+	0x25, 0xd8, 0x6c, 0x67, 0x8a, 0x90, 0x4b, 0x45, 0xc8, 0x25, 0xc8, 0xb8,
+	0x27, 0x20, 0xe3, 0x8c, 0x4c, 0x1b, 0x85, 0x4c, 0x9b, 0x91, 0xfb, 0xac,
+	0xae, 0x37, 0xb1, 0x92, 0x7e, 0xeb, 0x23, 0x0d, 0xe8, 0x18, 0xf2, 0x99,
+	0x9a, 0xd8, 0xe0, 0x8d, 0x47, 0x34, 0xbf, 0xbb, 0x9e, 0xba, 0xc2, 0x61,
+	0x0e, 0xcd, 0x4f, 0xb4, 0xff, 0xbe, 0x9d, 0xbf, 0xa5, 0x09, 0x7c, 0xfd,
+	0x03, 0xcb, 0xd7, 0xdb, 0x97, 0xf9, 0x3a, 0xe5, 0x30, 0x56, 0x5c, 0x9f,
+	0xaf, 0x3b, 0xec, 0xbb, 0x5c, 0xb0, 0x0e, 0x7c, 0xbd, 0x6e, 0x15, 0x5f,
+	0xc7, 0xc0, 0xd7, 0x7b, 0xd6, 0xf0, 0xf5, 0x06, 0x67, 0x58, 0xb7, 0xe1,
+	0x19, 0x09, 0x3e, 0x37, 0x3a, 0x55, 0xbe, 0xbe, 0x47, 0xf3, 0xf5, 0x21,
+	0xf0, 0xf5, 0x75, 0x35, 0x7c, 0xbd, 0x47, 0x52, 0x37, 0x67, 0x22, 0x5b,
+	0x65, 0xfc, 0x7e, 0xd5, 0xbe, 0x49, 0xfe, 0x49, 0x4c, 0x7b, 0xc3, 0x63,
+	0xc3, 0xd3, 0xed, 0x92, 0x7d, 0xe8, 0x15, 0x94, 0x91, 0xcf, 0x52, 0x63,
+	0x69, 0xc7, 0x95, 0x83, 0x47, 0x7e, 0x22, 0x0b, 0x9a, 0xb7, 0x44, 0x26,
+	0x8e, 0xc4, 0x64, 0xf2, 0x08, 0xe3, 0x10, 0x7f, 0x63, 0xe9, 0xbd, 0x49,
+	0x26, 0xf7, 0x32, 0x6f, 0x2e, 0x2a, 0xe3, 0x47, 0xe0, 0x6f, 0x1d, 0x61,
+	0x1c, 0xe2, 0xa5, 0x65, 0x1e, 0x5b, 0x80, 0x6c, 0x19, 0x3f, 0xc2, 0xb5,
+	0x8e, 0xa1, 0x9f, 0x16, 0x39, 0x74, 0x44, 0xe4, 0xb6, 0x23, 0x51, 0xf9,
+	0xe8, 0x91, 0x65, 0x5e, 0x1b, 0x0d, 0x79, 0xed, 0x59, 0xf0, 0x5a, 0xb7,
+	0xe5, 0x35, 0xb5, 0xcc, 0x6b, 0x7f, 0x5a, 0xc3, 0x6b, 0x6c, 0x4f, 0x5e,
+	0x7b, 0xce, 0x96, 0xf1, 0x39, 0x2a, 0xfb, 0x8e, 0x74, 0xca, 0xf8, 0x43,
+	0x6f, 0x91, 0x89, 0xfb, 0x09, 0xab, 0xf9, 0x8e, 0x13, 0x6d, 0xb1, 0x99,
+	0x4a, 0x37, 0xfa, 0x0f, 0x73, 0x88, 0xf4, 0xf7, 0x10, 0x7a, 0x67, 0x25,
+	0x95, 0xe3, 0x78, 0x8d, 0xf0, 0xa3, 0x4f, 0xc0, 0xbf, 0xd8, 0x07, 0x98,
+	0x6e, 0x39, 0x22, 0xa9, 0xa8, 0xbc, 0x2c, 0x53, 0xfe, 0x27, 0x2e, 0x37,
+	0xf6, 0x04, 0x6c, 0x11, 0x6d, 0xfb, 0xa4, 0x25, 0xfb, 0xce, 0x40, 0xfb,
+	0x18, 0xa5, 0xb2, 0x30, 0x16, 0xc0, 0xb8, 0xb9, 0x63, 0xbe, 0xc7, 0xc4,
+	0xfc, 0xc7, 0x06, 0x7d, 0xe6, 0x45, 0xc7, 0x6c, 0x07, 0xf8, 0x9e, 0xcf,
+	0xb0, 0x67, 0xf4, 0x59, 0x43, 0xb6, 0x7f, 0x44, 0x7f, 0x1b, 0x91, 0x31,
+	0xf5, 0x7c, 0x99, 0xdf, 0xb0, 0x81, 0xff, 0x59, 0xe6, 0xb7, 0xb0, 0xf6,
+	0xb7, 0x9b, 0xf8, 0x2c, 0xf9, 0xee, 0x87, 0x0e, 0xbf, 0x5d, 0x35, 0xa5,
+	0x73, 0xbd, 0xf0, 0xbb, 0xcc, 0x67, 0xd6, 0x7f, 0x84, 0xf1, 0x8e, 0x64,
+	0x52, 0xbd, 0xf7, 0x72, 0xe6, 0x1e, 0xec, 0x9d, 0x67, 0xdd, 0xad, 0x96,
+	0x47, 0xb7, 0x6a, 0xbf, 0x83, 0x36, 0xd6, 0x78, 0xe9, 0x45, 0xc9, 0xd3,
+	0x36, 0x19, 0xdd, 0xea, 0xe4, 0x66, 0x92, 0x97, 0x1b, 0xfb, 0x79, 0xdd,
+	0xa5, 0xcc, 0x3b, 0x4c, 0xab, 0xb5, 0x32, 0xf9, 0x84, 0x84, 0x32, 0x39,
+	0x75, 0x33, 0xbf, 0xb7, 0x9b, 0x3d, 0xa2, 0xbf, 0x2f, 0x95, 0xec, 0x56,
+	0x9c, 0xd3, 0xa7, 0x21, 0x5f, 0x43, 0x5a, 0x48, 0xc8, 0x27, 0x8f, 0x90,
+	0x1e, 0x54, 0xbc, 0x55, 0x3e, 0x61, 0xe9, 0x61, 0x46, 0x0a, 0x90, 0x3b,
+	0x47, 0x8e, 0x7c, 0x54, 0x66, 0x6e, 0x5c, 0x4d, 0x0f, 0x13, 0x55, 0x7a,
+	0x88, 0xc3, 0x3e, 0x73, 0x6a, 0xe9, 0xe1, 0x97, 0x97, 0xe9, 0x61, 0xc6,
+	0xf9, 0xe7, 0xd2, 0xc3, 0xf5, 0x2b, 0xe8, 0x61, 0x4a, 0xd3, 0xc3, 0xce,
+	0x65, 0x7a, 0x98, 0x3a, 0xc2, 0x71, 0xf5, 0xde, 0xa8, 0xbb, 0xe8, 0x70,
+	0xcd, 0x97, 0x69, 0x21, 0x39, 0xa9, 0xf3, 0xf5, 0x53, 0x39, 0x9e, 0x6f,
+	0xda, 0xa0, 0x18, 0x27, 0xa9, 0xae, 0x7f, 0xeb, 0xbf, 0xe8, 0xfa, 0xbf,
+	0xfc, 0xff, 0x79, 0xfd, 0xd5, 0xa5, 0xcc, 0xdd, 0xe7, 0x99, 0x55, 0x23,
+	0x8f, 0x43, 0x7a, 0x88, 0x5d, 0x6a, 0xf4, 0x02, 0xd7, 0x98, 0xcf, 0x90,
+	0x67, 0x90, 0x7f, 0x67, 0x20, 0xff, 0x9e, 0x84, 0xfc, 0x3b, 0xbd, 0x62,
+	0x4f, 0x60, 0xd0, 0xc6, 0x23, 0x02, 0x39, 0xe8, 0x57, 0xf1, 0xb1, 0x38,
+	0x40, 0x7c, 0x98, 0xfc, 0x13, 0xe6, 0xfe, 0xae, 0xc4, 0x49, 0x54, 0xe7,
+	0x1c, 0x3d, 0xea, 0xd7, 0xe2, 0x84, 0x70, 0xbf, 0x5c, 0x33, 0x47, 0xfc,
+	0x2e, 0xf3, 0x79, 0x46, 0xe7, 0x91, 0xe4, 0xf5, 0x1e, 0x14, 0xf1, 0xc2,
+	0x3d, 0x28, 0xe2, 0x24, 0xaa, 0xed, 0xfd, 0x7c, 0xb9, 0x49, 0xe7, 0xd0,
+	0x1f, 0x98, 0x8f, 0xcb, 0x62, 0x9c, 0x31, 0x3e, 0x7e, 0x97, 0x90, 0x7e,
+	0xb3, 0x97, 0xc8, 0x4b, 0x8e, 0xb9, 0x72, 0xe0, 0xe9, 0x0d, 0x96, 0xb6,
+	0x19, 0x1b, 0xe4, 0x99, 0xdd, 0x70, 0x2f, 0xa2, 0xd7, 0xca, 0xba, 0x96,
+	0x9a, 0x98, 0x25, 0xf0, 0x3e, 0x2d, 0xc9, 0xcc, 0x00, 0xee, 0xf3, 0x1c,
+	0x7b, 0xbf, 0x4c, 0x3d, 0x38, 0x01, 0x5b, 0x6e, 0x2f, 0x74, 0x0e, 0xcf,
+	0x9f, 0x99, 0xef, 0x70, 0x13, 0x86, 0x59, 0xfd, 0xdd, 0x29, 0xfa, 0x80,
+	0xa4, 0x87, 0x04, 0x9e, 0x67, 0x6c, 0x5c, 0x29, 0x21, 0xf9, 0xc2, 0x05,
+	0xf3, 0x6d, 0xcb, 0xc2, 0x4b, 0xb8, 0xbf, 0xde, 0x7a, 0x18, 0x3f, 0x64,
+	0xd4, 0xdc, 0xd1, 0xd7, 0x92, 0xa4, 0xcb, 0x26, 0xc7, 0xa5, 0x1a, 0x37,
+	0x99, 0x91, 0xc3, 0xda, 0x7e, 0x1e, 0xb2, 0xb9, 0x2d, 0xa9, 0xd1, 0x9c,
+	0x18, 0x1b, 0xfa, 0x77, 0x60, 0x43, 0x7f, 0xb1, 0x92, 0xd6, 0xfb, 0x58,
+	0xa7, 0x61, 0x43, 0x3f, 0x01, 0xdd, 0x43, 0x9d, 0x13, 0xb7, 0x3a, 0x67,
+	0x4a, 0xdd, 0xa8, 0x75, 0xce, 0x37, 0xb5, 0xce, 0x79, 0xef, 0x1a, 0x9d,
+	0x73, 0x48, 0x75, 0x97, 0xa8, 0x73, 0x86, 0xd5, 0x1e, 0x87, 0xf6, 0xe2,
+	0xe6, 0x3a, 0x3a, 0xe7, 0x7d, 0xf2, 0x2e, 0xfb, 0xee, 0x1e, 0x79, 0xff,
+	0x0e, 0xbd, 0x77, 0xe3, 0xce, 0x2a, 0x7e, 0x6b, 0xc9, 0xe8, 0xa0, 0xeb,
+	0x54, 0xaf, 0xde, 0xf3, 0xfd, 0x46, 0x8d, 0xce, 0xe9, 0x52, 0x03, 0xce,
+	0xb0, 0x6e, 0xc3, 0xd8, 0x04, 0x9f, 0x7d, 0x27, 0x3d, 0xda, 0x84, 0xe7,
+	0x84, 0x44, 0x8e, 0x60, 0xee, 0xe6, 0x7b, 0x50, 0xca, 0xbc, 0x7b, 0xab,
+	0x7d, 0xa7, 0xc2, 0xf2, 0xa8, 0x29, 0xef, 0xb6, 0xe5, 0x46, 0x57, 0x75,
+	0xa9, 0x4e, 0xad, 0xab, 0xb6, 0x83, 0xa1, 0x66, 0xa1, 0x5f, 0x67, 0x8b,
+	0xa1, 0xce, 0xe2, 0x6f, 0xc6, 0x9e, 0x19, 0xa3, 0x08, 0x63, 0xd8, 0x49,
+	0xd4, 0xc1, 0x55, 0x0c, 0x6d, 0x4a, 0xfe, 0x86, 0xaf, 0x80, 0x6b, 0x1e,
+	0x78, 0xbd, 0x19, 0xfc, 0xf3, 0x6f, 0x0a, 0x8c, 0x81, 0xb6, 0xcb, 0xd1,
+	0xe9, 0xda, 0x77, 0x9d, 0xf2, 0x9e, 0xe9, 0x2d, 0xb2, 0xbf, 0xf4, 0x2d,
+	0xf0, 0xc1, 0x56, 0x99, 0x2a, 0x15, 0xf4, 0x79, 0xf5, 0x4d, 0xfa, 0x3b,
+	0x1e, 0xfc, 0xbe, 0x8d, 0x91, 0x91, 0x3b, 0x1d, 0x23, 0x23, 0xd3, 0xaa,
+	0x6a, 0xb3, 0x86, 0x7d, 0xf2, 0xdb, 0x21, 0x23, 0xa5, 0x84, 0xfe, 0xc6,
+	0xe9, 0x6c, 0xe5, 0x0a, 0xf9, 0xc2, 0x31, 0x75, 0xa7, 0xaa, 0x9e, 0xef,
+	0xd5, 0x36, 0xeb, 0xdc, 0x0a, 0x9b, 0xf5, 0xaf, 0x64, 0xf1, 0xfd, 0x31,
+	0xcc, 0x13, 0x34, 0x7c, 0xe5, 0xf7, 0xb8, 0x17, 0xda, 0x1e, 0x97, 0x0b,
+	0x32, 0xa2, 0xf1, 0x47, 0x79, 0xda, 0x02, 0x39, 0xb8, 0xa4, 0xf5, 0xeb,
+	0x66, 0xd0, 0x20, 0x65, 0xe9, 0xc7, 0xe4, 0x45, 0x2d, 0xcf, 0x36, 0x5b,
+	0xdb, 0x75, 0x81, 0xb1, 0xd4, 0x23, 0xb4, 0x5d, 0xbf, 0x69, 0xcb, 0x59,
+	0x96, 0x4a, 0x2c, 0x09, 0xf5, 0x5d, 0x1c, 0x32, 0x94, 0xf2, 0xf4, 0x8d,
+	0xda, 0xae, 0x5f, 0xb3, 0x7d, 0x50, 0x7e, 0x1a, 0xd9, 0xbd, 0xdd, 0x59,
+	0xb0, 0x65, 0x7c, 0x0e, 0xe3, 0xe9, 0x5e, 0x3a, 0x6b, 0xf9, 0x4c, 0x39,
+	0x5f, 0xc2, 0xfb, 0x4d, 0x78, 0x4f, 0x3e, 0x3b, 0xad, 0xf9, 0x4c, 0xdb,
+	0x27, 0x4e, 0xbf, 0xdd, 0x5f, 0x58, 0xde, 0x1b, 0xc8, 0x91, 0xcf, 0xd4,
+	0x51, 0x77, 0xc1, 0xc8, 0x03, 0xe6, 0xa9, 0x7e, 0x1e, 0xba, 0x83, 0x6d,
+	0x51, 0xfe, 0x70, 0x9a, 0xbe, 0x2d, 0xfc, 0x9f, 0x56, 0x3c, 0xb7, 0xe3,
+	0x79, 0x56, 0xde, 0xbb, 0x37, 0xa6, 0xe7, 0x3d, 0x85, 0x79, 0x1c, 0x38,
+	0x82, 0x39, 0x39, 0xc6, 0x76, 0x8e, 0x9e, 0x8a, 0x4a, 0xc3, 0x29, 0xf2,
+	0x1d, 0xcf, 0xda, 0x04, 0xc1, 0xbe, 0x7e, 0xd2, 0x6d, 0xca, 0xdd, 0xa9,
+	0xcf, 0x96, 0x6e, 0x4f, 0x44, 0x80, 0x93, 0x03, 0x58, 0x8f, 0xa9, 0x82,
+	0xe7, 0x66, 0x1c, 0x2f, 0x81, 0x79, 0xc2, 0x06, 0xec, 0x86, 0x2d, 0xd8,
+	0x0d, 0x3b, 0xb0, 0x1b, 0x76, 0xe0, 0x46, 0x39, 0x71, 0x15, 0x73, 0x4c,
+	0x72, 0xd7, 0xc2, 0x2b, 0x97, 0xef, 0xe8, 0x38, 0x7d, 0xe3, 0xcd, 0x23,
+	0xf0, 0xd9, 0xc5, 0x4d, 0x8d, 0x32, 0x0f, 0x7f, 0xc9, 0x6d, 0xbc, 0x79,
+	0xa7, 0x74, 0x0f, 0xe2, 0xfd, 0xe0, 0x05, 0xe9, 0xb9, 0xf9, 0x56, 0xa7,
+	0x71, 0x74, 0x04, 0x78, 0x4c, 0x3b, 0xa9, 0xc4, 0x98, 0xb3, 0x80, 0x71,
+	0x32, 0xdb, 0x23, 0xc2, 0xb8, 0xe5, 0x02, 0x63, 0x11, 0x37, 0x77, 0x47,
+	0xfa, 0x92, 0xe3, 0x4e, 0x6a, 0x54, 0x45, 0x52, 0xa3, 0x23, 0x4e, 0x58,
+	0x8f, 0xdf, 0x48, 0x85, 0x9c, 0x01, 0xac, 0x07, 0x8a, 0xd3, 0xa0, 0xa7,
+	0xff, 0x28, 0xf9, 0x63, 0x2d, 0x32, 0x5f, 0xe8, 0x76, 0x33, 0x2a, 0xae,
+	0x73, 0x4b, 0xd4, 0x09, 0x10, 0xfd, 0xa9, 0x98, 0xcc, 0x96, 0xb6, 0x8a,
+	0xd2, 0xb6, 0x7b, 0x87, 0x64, 0xa6, 0x4b, 0x72, 0x6e, 0x40, 0xda, 0x14,
+	0xfa, 0xe7, 0xb7, 0x67, 0xd5, 0x09, 0xee, 0x25, 0x86, 0xbc, 0x70, 0x39,
+	0xf9, 0xa4, 0x04, 0x1c, 0x82, 0x6e, 0x19, 0xe3, 0x6d, 0x12, 0xca, 0xbd,
+	0x8f, 0xea, 0xf8, 0x29, 0x63, 0xb6, 0xb5, 0x7b, 0x0f, 0xe4, 0x8f, 0x58,
+	0x5d, 0xfe, 0x98, 0x2b, 0x72, 0x9f, 0x46, 0x72, 0x51, 0xc6, 0x88, 0x3d,
+	0xfc, 0x9e, 0x61, 0xdd, 0x26, 0x99, 0x1a, 0xc8, 0xd9, 0x3c, 0x8f, 0x47,
+	0x12, 0xcc, 0x21, 0x26, 0x4e, 0xc6, 0x07, 0xc8, 0xeb, 0xab, 0xf7, 0x36,
+	0x62, 0x35, 0xf2, 0xc0, 0x91, 0xc5, 0x52, 0xb8, 0x17, 0xc2, 0xfe, 0xf0,
+	0x3c, 0x63, 0xe4, 0x6d, 0x66, 0x4d, 0x3b, 0xc2, 0xc5, 0xfd, 0xca, 0x95,
+	0x32, 0x56, 0x79, 0x94, 0xa9, 0xae, 0x96, 0xaf, 0x8f, 0x55, 0x8c, 0x6c,
+	0x9d, 0xa9, 0x84, 0xba, 0x25, 0x66, 0x74, 0xe9, 0x1a, 0x7d, 0x62, 0xa2,
+	0x99, 0x55, 0x7d, 0x42, 0xbd, 0xa8, 0xe4, 0x03, 0xf3, 0x1d, 0x12, 0x7d,
+	0x58, 0x96, 0xa6, 0xbc, 0xec, 0xe5, 0xcc, 0xd5, 0x98, 0xf2, 0xdf, 0x8c,
+	0x7e, 0xfc, 0x6f, 0x09, 0xea, 0xc3, 0x31, 0xf5, 0x75, 0xdc, 0x37, 0x69,
+	0xfa, 0x03, 0x4f, 0xe1, 0xd9, 0xf8, 0x09, 0xbf, 0x03, 0x3f, 0xe1, 0x8b,
+	0xd0, 0x75, 0x67, 0xe0, 0x27, 0x3c, 0x09, 0x3f, 0xe1, 0x34, 0xfc, 0x84,
+	0x27, 0xa0, 0x27, 0x6b, 0xfd, 0x83, 0xc9, 0x15, 0xfe, 0x41, 0xa0, 0xf9,
+	0x9f, 0xf1, 0xc0, 0x27, 0x6b, 0x7c, 0x83, 0x7d, 0x46, 0x5f, 0xc1, 0xef,
+	0x37, 0x7c, 0xd4, 0xa5, 0x6e, 0xd2, 0xfa, 0xd1, 0xe4, 0xed, 0x8e, 0x2e,
+	0xeb, 0xab, 0x2e, 0x65, 0xf4, 0xd5, 0x6c, 0x55, 0x5f, 0x19, 0x3e, 0x7a,
+	0xb8, 0x24, 0x11, 0xaf, 0xb4, 0x90, 0xf1, 0x77, 0x69, 0x1e, 0x6a, 0xf3,
+	0xb6, 0x4a, 0xe4, 0x01, 0xd5, 0xde, 0x20, 0x19, 0xfb, 0x0c, 0xfa, 0x3a,
+	0x3a, 0x8d, 0xbe, 0xae, 0x95, 0xac, 0xb6, 0xcf, 0x2e, 0x8e, 0xef, 0x27,
+	0x56, 0xe1, 0x3b, 0x5f, 0xbc, 0x5b, 0xe3, 0xfc, 0xfe, 0x32, 0xf7, 0x59,
+	0x5a, 0x64, 0xb2, 0x1c, 0xe2, 0x9c, 0xe7, 0x59, 0x99, 0x8b, 0xd1, 0x29,
+	0x91, 0x87, 0x3b, 0x78, 0xce, 0x4a, 0x65, 0xfd, 0xf5, 0x3a, 0x87, 0xe5,
+	0xc4, 0x80, 0x24, 0xb2, 0x03, 0xa4, 0xd5, 0xfb, 0x64, 0x56, 0xaf, 0x45,
+	0x87, 0x34, 0x3c, 0x4c, 0x1b, 0x25, 0xdc, 0xcf, 0xeb, 0xba, 0xcc, 0x7e,
+	0x23, 0x35, 0x66, 0xea, 0x89, 0x1c, 0xd4, 0xeb, 0x75, 0x5c, 0xe7, 0x19,
+	0xde, 0x34, 0xcf, 0xb8, 0x3c, 0xbf, 0x47, 0xc5, 0x98, 0xfc, 0x3f, 0x67,
+	0xfd, 0x7e, 0xe1, 0x32, 0x63, 0xcf, 0x6c, 0xb2, 0x76, 0x8c, 0x89, 0x53,
+	0xd5, 0xb7, 0x61, 0xd8, 0x4f, 0xed, 0x37, 0x14, 0xb7, 0x38, 0x93, 0xa5,
+	0xad, 0x4e, 0xbe, 0xc4, 0xbd, 0x6c, 0xfb, 0xf7, 0x2e, 0xdc, 0x3d, 0xce,
+	0x01, 0x6f, 0x0b, 0xca, 0x18, 0xb3, 0x64, 0xcc, 0xe6, 0x97, 0x2e, 0x63,
+	0x8c, 0x36, 0xe3, 0x71, 0x6c, 0x96, 0x6d, 0x71, 0xa6, 0x4a, 0xdd, 0xf0,
+	0xcd, 0x79, 0xae, 0x8a, 0xef, 0x77, 0x72, 0xed, 0xa0, 0x83, 0x5d, 0x7d,
+	0x66, 0x77, 0x42, 0xae, 0xb0, 0x31, 0x68, 0xea, 0xe1, 0x9f, 0x5f, 0xb1,
+	0x77, 0x7b, 0x08, 0x7a, 0xec, 0x16, 0xc8, 0x23, 0xea, 0xe1, 0x43, 0x72,
+	0xb5, 0xa5, 0xe7, 0x95, 0x7a, 0xf8, 0xbc, 0x30, 0x4e, 0xdc, 0x8f, 0x77,
+	0xb9, 0x20, 0x06, 0x7a, 0x38, 0x5c, 0xe3, 0xab, 0xd1, 0xef, 0x6b, 0x1a,
+	0x32, 0xfb, 0x61, 0x2b, 0xfd, 0x3e, 0xc8, 0x81, 0x78, 0xe8, 0xe7, 0x35,
+	0x2e, 0xef, 0xd7, 0xee, 0xb1, 0x6d, 0xa7, 0xfc, 0xfb, 0x89, 0xa3, 0xe4,
+	0x21, 0xe9, 0x81, 0x2e, 0x63, 0x0e, 0xc8, 0x6f, 0x69, 0x9c, 0x89, 0x22,
+	0xed, 0x6d, 0xd2, 0x30, 0x5a, 0x39, 0x9f, 0x0c, 0x73, 0x38, 0xf2, 0xb6,
+	0xed, 0x84, 0xdd, 0x93, 0xcf, 0xcb, 0xdc, 0x65, 0xd4, 0x83, 0x23, 0x91,
+	0xf5, 0xfc, 0x7e, 0x22, 0xda, 0xf6, 0x18, 0xbd, 0x28, 0x61, 0x5f, 0x7c,
+	0x6e, 0xa8, 0xe9, 0x9b, 0x76, 0x14, 0xef, 0xab, 0xcf, 0x91, 0x3d, 0xa3,
+	0xf7, 0x19, 0xcd, 0xf7, 0x12, 0x42, 0x3e, 0x21, 0xef, 0x24, 0xf5, 0x59,
+	0x27, 0xef, 0x61, 0xda, 0x3d, 0xdc, 0x83, 0x75, 0x17, 0x26, 0xfd, 0x4f,
+	0xe8, 0x6f, 0xfc, 0xcd, 0x88, 0x38, 0x79, 0xff, 0x36, 0x9d, 0x7b, 0x92,
+	0xd7, 0xb1, 0xe6, 0x1c, 0xee, 0x55, 0x1f, 0xb5, 0xeb, 0x61, 0xfe, 0x4d,
+	0x0b, 0x96, 0x65, 0x01, 0x1b, 0x75, 0x08, 0x65, 0x6f, 0x5c, 0xba, 0x8e,
+	0x7e, 0x58, 0xf3, 0xc2, 0x66, 0xf8, 0x02, 0xc3, 0x47, 0xa1, 0xab, 0x8f,
+	0x26, 0x64, 0xe7, 0x51, 0xad, 0x1b, 0xd3, 0x6b, 0x63, 0x05, 0x7d, 0x6e,
+	0xd4, 0x79, 0x8f, 0x3e, 0xc7, 0xf6, 0xd6, 0xa3, 0x11, 0x39, 0x1c, 0xef,
+	0x73, 0x7b, 0x9c, 0xf7, 0x5a, 0x5d, 0x18, 0xc6, 0xb0, 0x5b, 0xd0, 0xfe,
+	0xf5, 0xe2, 0xd8, 0x61, 0xfc, 0x3a, 0x22, 0x33, 0x7b, 0x3b, 0x01, 0xdb,
+	0x5f, 0x5d, 0x66, 0xce, 0x20, 0x63, 0xad, 0xf4, 0xb7, 0xe7, 0xa3, 0x09,
+	0xca, 0xb2, 0x2e, 0xc0, 0x32, 0x72, 0x94, 0xfa, 0xcc, 0xd3, 0x3c, 0x0e,
+	0x18, 0xdc, 0x06, 0xed, 0x87, 0x90, 0x2f, 0xdf, 0x22, 0xde, 0x03, 0x90,
+	0x71, 0x47, 0x63, 0xd2, 0x73, 0xb4, 0x45, 0xb6, 0x1d, 0xa5, 0x1f, 0x52,
+	0xeb, 0x97, 0xd2, 0x2e, 0x7d, 0x04, 0x73, 0x7c, 0xb7, 0x96, 0x93, 0xdc,
+	0xd3, 0xdc, 0x4f, 0xde, 0x45, 0xdd, 0x2c, 0x6c, 0xe6, 0xcc, 0x51, 0x57,
+	0xef, 0x91, 0x66, 0x30, 0xe7, 0x6c, 0xd9, 0xc5, 0x38, 0x46, 0xe6, 0xe4,
+	0xe9, 0xa7, 0x8c, 0x76, 0x00, 0xc7, 0xef, 0xb5, 0xbc, 0xb3, 0xbe, 0xc3,
+	0xf2, 0xe8, 0xcf, 0xc8, 0x7b, 0x5b, 0x3a, 0x8c, 0xec, 0x7c, 0x4b, 0x07,
+	0x73, 0x93, 0x36, 0x7b, 0xbc, 0x37, 0x69, 0x7b, 0xc2, 0xc8, 0xd0, 0xd7,
+	0xe2, 0x45, 0x01, 0x8e, 0xc2, 0x7d, 0x29, 0x7d, 0x96, 0x2f, 0x38, 0xe7,
+	0xeb, 0xf3, 0x2b, 0xfe, 0xa2, 0xfe, 0x3b, 0x21, 0xdc, 0x23, 0xab, 0x7e,
+	0x6f, 0x65, 0x57, 0x85, 0x71, 0xf2, 0xcf, 0x86, 0x7f, 0x97, 0xa4, 0x26,
+	0xef, 0xb0, 0x76, 0x0f, 0x8c, 0xb1, 0xa6, 0xe5, 0xdc, 0xa0, 0xa0, 0xa4,
+	0xbf, 0x5f, 0xf4, 0x9c, 0x73, 0xbe, 0x70, 0xd6, 0xf9, 0xee, 0xb4, 0x04,
+	0x51, 0xef, 0x27, 0xce, 0xf7, 0x3d, 0xee, 0x99, 0x7f, 0xdd, 0xf9, 0x5e,
+	0xc1, 0x03, 0x1f, 0xde, 0x87, 0x79, 0xbc, 0xe2, 0xfc, 0x00, 0xeb, 0x7b,
+	0xb0, 0x98, 0x4e, 0xb9, 0x36, 0x26, 0x7e, 0xb6, 0xf0, 0x8a, 0xf3, 0xb5,
+	0x6a, 0x3c, 0x69, 0x30, 0xa4, 0x91, 0x43, 0x7c, 0x57, 0xc6, 0xbb, 0xb2,
+	0xde, 0xff, 0x71, 0xe6, 0xa6, 0x6d, 0x7e, 0x89, 0xe6, 0xe3, 0x85, 0xe5,
+	0x7d, 0x99, 0x51, 0xbd, 0x57, 0xf1, 0xac, 0x33, 0x37, 0x7f, 0x77, 0x87,
+	0xc9, 0x33, 0x3a, 0x8b, 0x77, 0x26, 0xe7, 0x72, 0x76, 0xfe, 0x2c, 0xea,
+	0x3c, 0xe3, 0xcc, 0xea, 0xf8, 0x97, 0xf6, 0xc5, 0x9d, 0x99, 0xf9, 0x67,
+	0x9c, 0x79, 0xbd, 0x07, 0x7d, 0xce, 0x79, 0x74, 0x9a, 0x7d, 0x9f, 0x43,
+	0x9d, 0x05, 0xe7, 0x04, 0xfa, 0x9b, 0x9f, 0xe6, 0x79, 0xdc, 0x6e, 0xd8,
+	0x05, 0xfc, 0x7b, 0x3f, 0xfc, 0x1e, 0xc7, 0xb3, 0xce, 0xfc, 0x72, 0xbf,
+	0x8b, 0xe8, 0x87, 0x75, 0x49, 0x8b, 0x1c, 0xf7, 0x59, 0xf4, 0xbf, 0x76,
+	0xaf, 0x6a, 0x2d, 0x4e, 0x5e, 0x00, 0x4e, 0x2e, 0x58, 0x9c, 0xbc, 0x6a,
+	0x71, 0xf2, 0x7c, 0x0d, 0x4e, 0x44, 0xad, 0xc4, 0xc9, 0xab, 0xc0, 0x89,
+	0xa8, 0xfa, 0x38, 0xc1, 0xbb, 0x32, 0xde, 0x69, 0x9c, 0xbc, 0xb4, 0x0a,
+	0x27, 0x4b, 0xcb, 0x71, 0x79, 0x83, 0x93, 0x17, 0x81, 0x93, 0xaf, 0x5a,
+	0xd8, 0x2f, 0x58, 0x9c, 0xe0, 0x3e, 0x7f, 0x01, 0x75, 0x5e, 0xaa, 0xc1,
+	0xc9, 0x05, 0xe0, 0xe4, 0x25, 0x8b, 0x93, 0xef, 0x5b, 0x9c, 0x7c, 0x1f,
+	0x75, 0x96, 0x80, 0x93, 0xf3, 0x75, 0x70, 0xf2, 0x22, 0x70, 0x12, 0xf6,
+	0x7b, 0x1e, 0xfd, 0x7c, 0xbf, 0x06, 0x27, 0x2f, 0xd6, 0xc1, 0x09, 0xf7,
+	0x62, 0xc3, 0x9c, 0xee, 0x99, 0xd7, 0xc9, 0xe9, 0x96, 0x3b, 0x5f, 0x3f,
+	0xa7, 0x9b, 0x75, 0x66, 0xa4, 0xfa, 0x37, 0x25, 0xee, 0xb6, 0x39, 0x6a,
+	0x26, 0x17, 0xb0, 0xfa, 0xcd, 0xa6, 0x6e, 0xf0, 0x79, 0x3e, 0xe7, 0x8a,
+	0xc9, 0x29, 0x8d, 0xee, 0xf8, 0x10, 0x78, 0x6d, 0x97, 0x1c, 0x38, 0xd6,
+	0x78, 0x38, 0x6b, 0xcb, 0xbc, 0x1d, 0xdd, 0x39, 0xa5, 0xf8, 0x2e, 0xcc,
+	0x49, 0xa0, 0x5f, 0xd2, 0xc0, 0x6f, 0x0b, 0xf6, 0xa6, 0xa5, 0x76, 0x4f,
+	0xba, 0xc0, 0x6f, 0x34, 0x61, 0xec, 0x25, 0xfe, 0xfd, 0x8b, 0x24, 0xf3,
+	0xac, 0xf2, 0x1a, 0xde, 0x14, 0xf4, 0xc7, 0xa0, 0xce, 0xad, 0xca, 0x14,
+	0x68, 0x73, 0x27, 0x99, 0xa3, 0x06, 0x5b, 0x79, 0xc8, 0x9e, 0x09, 0xf3,
+	0xf5, 0x39, 0x95, 0x2a, 0xff, 0xd4, 0x9e, 0x87, 0x26, 0xdf, 0x55, 0xe9,
+	0xe6, 0xe0, 0xf2, 0x77, 0x02, 0x4f, 0xca, 0xd3, 0x3a, 0x56, 0xdc, 0x8c,
+	0xf5, 0x09, 0x82, 0xc7, 0x7c, 0x13, 0xa3, 0x5d, 0xd4, 0x31, 0x5a, 0x81,
+	0x37, 0x3e, 0x69, 0xe3, 0xb4, 0x3d, 0x83, 0x2f, 0x2d, 0xc7, 0x68, 0x6b,
+	0xf3, 0x59, 0xcc, 0xfe, 0x7a, 0xa6, 0xf4, 0x88, 0xce, 0xd1, 0x19, 0xe1,
+	0xf7, 0x37, 0x20, 0x23, 0x26, 0x66, 0xe6, 0x65, 0xf2, 0x41, 0x3e, 0x53,
+	0xbf, 0x45, 0xa0, 0xc3, 0x28, 0xc3, 0x73, 0x92, 0x19, 0x64, 0x99, 0x69,
+	0x33, 0xa2, 0xfd, 0xe5, 0x93, 0x32, 0xbc, 0x3c, 0x3e, 0xf1, 0x7b, 0x57,
+	0xcd, 0x77, 0xab, 0x69, 0xf3, 0xa4, 0x9d, 0x4c, 0x85, 0xef, 0xc3, 0x3d,
+	0xf2, 0xbb, 0xec, 0xb7, 0xb3, 0xf8, 0xbe, 0xf6, 0x5b, 0xad, 0x5a, 0x74,
+	0xe0, 0x37, 0xbf, 0x87, 0x36, 0xe5, 0x8c, 0xa0, 0xcd, 0x82, 0xdb, 0x32,
+	0xaa, 0x86, 0x6e, 0x18, 0xe5, 0xb9, 0xb9, 0xd9, 0x35, 0xdf, 0xba, 0xae,
+	0xea, 0xc5, 0xbc, 0x5e, 0x53, 0xe6, 0x67, 0xdd, 0x05, 0x5a, 0xd4, 0xb4,
+	0xa5, 0xe9, 0xff, 0xc0, 0xb2, 0xbe, 0xa4, 0x9e, 0x35, 0xdf, 0x9e, 0x31,
+	0xfa, 0x32, 0x95, 0x18, 0xc1, 0xf8, 0xfa, 0x6f, 0x2a, 0xd8, 0x73, 0xbd,
+	0xd9, 0xf9, 0xdb, 0xb5, 0xae, 0x9f, 0xf2, 0xd3, 0xc9, 0xa8, 0xd4, 0xa9,
+	0x5b, 0xaa, 0xa9, 0xab, 0xe7, 0xed, 0xca, 0x7f, 0xc5, 0xda, 0x7c, 0xbe,
+	0x58, 0x96, 0xe1, 0xe9, 0xbf, 0x84, 0xff, 0x98, 0x90, 0xdf, 0x2e, 0x96,
+	0x40, 0xaf, 0xb9, 0xcd, 0xf6, 0x5b, 0x4d, 0x19, 0xc0, 0xcd, 0x6f, 0xaf,
+	0xe8, 0x7c, 0xe2, 0xc8, 0x17, 0x40, 0x17, 0x9f, 0x2b, 0x71, 0x0c, 0xc0,
+	0x12, 0x81, 0x6d, 0x0f, 0x3b, 0x61, 0xa6, 0xa4, 0x73, 0xe7, 0xae, 0x2b,
+	0x97, 0x74, 0xcc, 0x62, 0x67, 0xb9, 0x53, 0x76, 0x95, 0x5b, 0x64, 0x37,
+	0xf4, 0xc2, 0xee, 0xb2, 0x87, 0x2b, 0x26, 0xef, 0x2e, 0x9b, 0x75, 0xfa,
+	0x58, 0x99, 0xeb, 0xbd, 0x43, 0x66, 0x8f, 0xad, 0xfe, 0x3e, 0xe7, 0x42,
+	0x2e, 0xfc, 0x3b, 0x4b, 0x4a, 0x31, 0xbf, 0x8c, 0xb4, 0x84, 0xab, 0x98,
+	0x3a, 0xbc, 0xa0, 0xf1, 0xc0, 0x0c, 0xd7, 0x54, 0x69, 0x49, 0x98, 0xa7,
+	0xcf, 0xbf, 0xad, 0x34, 0x73, 0x39, 0xcf, 0x4d, 0xf3, 0x5b, 0x5e, 0x3b,
+	0x2b, 0x61, 0xde, 0x78, 0xbd, 0x9c, 0x71, 0xd8, 0xf9, 0x3b, 0xc2, 0x1c,
+	0xbf, 0x18, 0x73, 0xc6, 0xa5, 0xeb, 0x54, 0x0b, 0xee, 0xa7, 0x2f, 0xd7,
+	0x67, 0x9b, 0x4f, 0x89, 0x2d, 0xd3, 0xf9, 0xe4, 0x78, 0x5e, 0xfd, 0x7d,
+	0xb5, 0x90, 0x1f, 0xaa, 0x7f, 0xa7, 0x40, 0xe4, 0xff, 0x02, 0xfb, 0x2e,
+	0x88, 0x71, 0xec, 0x6e, 0x00, 0x00, 0x00 };
+
+static const u32 bnx2_CP_b09FwData[(0x0/4) + 1] = { 0x0 };
+static const u32 bnx2_CP_b09FwRodata[(0x118/4) + 1] = {
+	0x0800061c, 0x0800083c, 0x08000780, 0x080007a8, 0x080007d0, 0x080007f8,
+	0x08000654, 0x08000640, 0x08000864, 0x08000864, 0x08000670, 0x0800068c,
+	0x0800068c, 0x08000864, 0x080006a4, 0x080006b8, 0x08000864, 0x080006cc,
+	0x08000864, 0x08000864, 0x080006e0, 0x08000864, 0x08000864, 0x08000864,
+	0x08000864, 0x08000864, 0x08000864, 0x08000864, 0x08000864, 0x08000864,
+	0x08000864, 0x080006f4, 0x08000864, 0x08000708, 0x0800071c, 0x08000730,
+	0x08000864, 0x08000744, 0x08000758, 0x0800076c, 0x08003200, 0x08003218,
+	0x08003228, 0x08003238, 0x08003250, 0x08003268, 0x08003278, 0x08003288,
+	0x080032a8, 0x080032b8, 0x080032c8, 0x08003358, 0x08003298, 0x080032d8,
+	0x080032e8, 0x08003300, 0x08003320, 0x08003358, 0x08003338, 0x08003338,
+	0x080050d4, 0x080050d4, 0x080050d4, 0x080050d4, 0x080050d4, 0x080050fc,
+	0x080050fc, 0x08005124, 0x08005174, 0x08005144, 0x00000000 };
+static const u32 bnx2_CP_b09FwBss[(0x3b0/4) + 1] = { 0x0 };
+static const u32 bnx2_CP_b09FwSbss[(0xa1/4) + 1] = { 0x0 };
 
 static struct fw_info bnx2_cp_fw_09 = {
-	.ver_major			= 0x1,
-	.ver_minor			= 0x0,
-	.ver_fix			= 0x0,
+	.ver_major			= 0x3,
+	.ver_minor			= 0x4,
+	.ver_fix			= 0x3,
 
 	.start_addr			= 0x0800006c,
 
 	.text_addr			= 0x08000000,
-	.text_len			= 0x73cc,
+	.text_len			= 0x6ee8,
 	.text_index			= 0x0,
 	.gz_text			= bnx2_CP_b09FwText,
 	.gz_text_len			= sizeof(bnx2_CP_b09FwText),
 
-	.data_addr			= 0x08007500,
-	.data_len			= 0x50,
+	.data_addr			= 0x08007020,
+	.data_len			= 0x0,
 	.data_index			= 0x0,
 	.data				= bnx2_CP_b09FwData,
 
-	.sbss_addr			= 0x08007554,
-	.sbss_len			= 0xe9,
+	.sbss_addr			= 0x08007024,
+	.sbss_len			= 0xa1,
 	.sbss_index			= 0x0,
 	.sbss				= bnx2_CP_b09FwSbss,
 
-	.bss_addr			= 0x08007640,
-	.bss_len			= 0x870,
+	.bss_addr			= 0x080070d0,
+	.bss_len			= 0x3b0,
 	.bss_index			= 0x0,
 	.bss				= bnx2_CP_b09FwBss,
 
-	.rodata_addr			= 0x080073d0,
+	.rodata_addr			= 0x08006ee8,
 	.rodata_len			= 0x118,
 	.rodata_index			= 0x0,
 	.rodata				= bnx2_CP_b09FwRodata,
 };
 
 static u8 bnx2_RXP_b09FwText[] = {
-	0x1f, 0x8b, 0x08, 0x08, 0x19, 0xfd, 0x2f, 0x45, 0x00, 0x03, 0x74, 0x65,
-	0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, 0xec, 0x5c, 0x6b, 0x6c,
-	0x1c, 0xd7, 0x75, 0x3e, 0xf3, 0x20, 0xb5, 0xa2, 0xf8, 0x18, 0x2e, 0x57,
-	0xcc, 0x4a, 0x66, 0xec, 0x5d, 0x71, 0x24, 0xb2, 0x16, 0x6b, 0x8c, 0xd8,
-	0xad, 0x4d, 0x04, 0x6b, 0x7b, 0x33, 0xbb, 0x92, 0x98, 0x54, 0x85, 0x29,
-	0x87, 0x75, 0x0c, 0xc3, 0x75, 0xd9, 0xa5, 0x1a, 0xbb, 0xae, 0x51, 0xc8,
-	0x8f, 0xc4, 0x06, 0x6a, 0xd6, 0x9b, 0x25, 0xdd, 0xa8, 0xe9, 0x82, 0x43,
-	0x4b, 0xaa, 0xe9, 0x02, 0x69, 0xbb, 0x20, 0xa9, 0xc7, 0x8f, 0x85, 0x56,
-	0x76, 0x52, 0xc7, 0xf9, 0xe1, 0x48, 0x50, 0x95, 0x20, 0x28, 0x0c, 0x43,
-	0x48, 0x8d, 0xd6, 0x3f, 0xda, 0x40, 0x95, 0x9f, 0x68, 0x92, 0x42, 0x41,
-	0x0b, 0xc7, 0x68, 0x6c, 0x4f, 0xbf, 0xef, 0xce, 0x0c, 0xb9, 0xa4, 0x5f,
-	0x40, 0x7f, 0xf4, 0x4f, 0xe7, 0x02, 0x8b, 0xb9, 0xf7, 0xce, 0x3d, 0xe7,
-	0x9e, 0x7b, 0xde, 0xe7, 0x0e, 0xa5, 0xdf, 0xef, 0x94, 0x0e, 0x09, 0x5b,
-	0x17, 0x7e, 0x99, 0xc3, 0x8f, 0x3d, 0x74, 0xc3, 0xd8, 0x0d, 0xa3, 0x22,
-	0x7b, 0xf6, 0x18, 0x5b, 0x12, 0x7a, 0x34, 0x1f, 0xb7, 0xb8, 0xc5, 0x2d,
-	0x6e, 0x71, 0x8b, 0x5b, 0xdc, 0xe2, 0x16, 0xb7, 0xb8, 0xc5, 0x2d, 0x6e,
-	0x71, 0x8b, 0x5b, 0xdc, 0xe2, 0x16, 0xb7, 0xb8, 0xc5, 0x2d, 0x6e, 0x71,
-	0x8b, 0x5b, 0xdc, 0xe2, 0x16, 0xb7, 0xb8, 0xc5, 0x2d, 0x6e, 0x71, 0x8b,
-	0x5b, 0xdc, 0xe2, 0x16, 0xb7, 0xb8, 0xc5, 0x2d, 0x6e, 0x71, 0x8b, 0x5b,
-	0xdc, 0xe2, 0x16, 0xb7, 0xb8, 0xc5, 0x2d, 0x6e, 0x71, 0x8b, 0x5b, 0xdc,
-	0xe2, 0xf6, 0xff, 0xbd, 0x19, 0x22, 0x16, 0x9f, 0x5d, 0xe1, 0x4f, 0x12,
-	0x7a, 0xfe, 0xf2, 0x1f, 0xba, 0xb6, 0x24, 0x8c, 0xfc, 0xcf, 0x66, 0xa6,
-	0x6d, 0x91, 0x42, 0x63, 0x77, 0xa6, 0x28, 0xef, 0xfb, 0x95, 0x94, 0x29,
-	0x9c, 0xff, 0x6c, 0xfe, 0xbd, 0xbf, 0x7d, 0xf1, 0xa6, 0xec, 0xd5, 0xba,
-	0x21, 0x09, 0x2b, 0x3f, 0xb7, 0xc7, 0xda, 0x25, 0x89, 0x01, 0xc0, 0x7c,
-	0x6b, 0xe8, 0xc7, 0xdd, 0xd2, 0x2d, 0x6b, 0x78, 0xec, 0x84, 0x5c, 0x36,
-	0x5e, 0xd0, 0xdc, 0xa6, 0xef, 0x9f, 0x70, 0x7c, 0xff, 0x87, 0xf8, 0xbd,
-	0xe5, 0x60, 0xec, 0x7d, 0xe0, 0x17, 0x4c, 0x43, 0x74, 0xfb, 0x2f, 0x34,
-	0x77, 0xb9, 0x43, 0xaa, 0x8b, 0xa6, 0xcc, 0x7a, 0x29, 0x39, 0xe2, 0x55,
-	0xb4, 0x52, 0xb3, 0xa6, 0xed, 0x3d, 0x35, 0xaf, 0xed, 0x3b, 0x75, 0x44,
-	0xdb, 0x7f, 0x6a, 0x41, 0x73, 0x4f, 0x49, 0x45, 0xdf, 0xd3, 0x29, 0x05,
-	0xeb, 0xb4, 0x56, 0x6c, 0xf6, 0x6b, 0xee, 0xe2, 0x7b, 0xbe, 0xeb, 0x64,
-	0xad, 0xbb, 0xc4, 0x2c, 0x80, 0x16, 0x71, 0x6b, 0x3e, 0xc6, 0xa6, 0x14,
-	0x52, 0xbe, 0xaf, 0xe7, 0xfd, 0x27, 0xdc, 0x9c, 0x6d, 0xe9, 0x5a, 0x4a,
-	0xaa, 0xcd, 0x7e, 0xe0, 0xed, 0xd4, 0x8a, 0x8b, 0xa6, 0x56, 0xf2, 0xfc,
-	0x73, 0xae, 0x23, 0x03, 0x86, 0xf8, 0xfe, 0x9c, 0xb3, 0x33, 0x7d, 0x48,
-	0x4e, 0x02, 0x6f, 0x03, 0xf8, 0xc4, 0xd2, 0xf3, 0xa4, 0x8f, 0x74, 0x92,
-	0xe4, 0x8a, 0x56, 0x1c, 0x8a, 0xe8, 0x93, 0x0c, 0xe9, 0x2f, 0xaf, 0xe8,
-	0xa0, 0x73, 0x8b, 0x94, 0xeb, 0x96, 0x4c, 0xad, 0x6c, 0x5c, 0x7f, 0xd9,
-	0x7f, 0x71, 0x28, 0x25, 0xcf, 0x36, 0xb3, 0x47, 0x2a, 0x92, 0x90, 0x39,
-	0x2f, 0x23, 0x7a, 0x5e, 0x0a, 0x6e, 0x6e, 0x40, 0xce, 0x35, 0xd3, 0xf2,
-	0x5c, 0xd3, 0x4e, 0x57, 0x65, 0x93, 0x94, 0x53, 0x96, 0x9c, 0x6d, 0xa6,
-	0x70, 0x46, 0xff, 0x9c, 0x6e, 0xdb, 0x56, 0x15, 0x6b, 0xab, 0xcd, 0x97,
-	0xf8, 0xef, 0x5f, 0xac, 0xe9, 0x9c, 0x82, 0xa9, 0x80, 0xee, 0x70, 0x2d,
-	0xcf, 0xa1, 0xd6, 0xaa, 0xb3, 0x04, 0x6b, 0xa5, 0x32, 0x9d, 0xc3, 0x5c,
-	0x73, 0x34, 0xe4, 0xef, 0x16, 0x9c, 0x97, 0x4f, 0x4b, 0xaa, 0x9e, 0x01,
-	0xde, 0xb0, 0xff, 0xcf, 0xc0, 0x37, 0x80, 0xf3, 0x5e, 0xab, 0x7e, 0xee,
-	0xa2, 0xa4, 0x74, 0xd9, 0x99, 0x2e, 0x0b, 0x78, 0xdb, 0xec, 0xc4, 0x98,
-	0xf4, 0xf9, 0xfe, 0x7e, 0x47, 0xac, 0xaa, 0xd3, 0x03, 0x98, 0x8c, 0x54,
-	0x9d, 0x6e, 0xe0, 0x69, 0x13, 0xcb, 0xe6, 0xb9, 0xb8, 0xd7, 0x66, 0xcc,
-	0xfb, 0x5d, 0x46, 0xde, 0xf7, 0xa7, 0x73, 0xd2, 0x1d, 0xcc, 0xed, 0x56,
-	0x38, 0xa6, 0x26, 0x34, 0xac, 0xfb, 0x05, 0x69, 0x4e, 0x24, 0xf3, 0xec,
-	0xf3, 0x99, 0x13, 0x77, 0xfe, 0xda, 0x90, 0x96, 0x34, 0x68, 0xb9, 0x26,
-	0xec, 0x83, 0xff, 0x1e, 0xf8, 0xe0, 0x7c, 0x06, 0x63, 0xed, 0x3a, 0xe0,
-	0x19, 0xae, 0x0a, 0xf7, 0xe8, 0x93, 0xa5, 0x94, 0xe8, 0x57, 0x9c, 0xde,
-	0x70, 0x5d, 0x37, 0x68, 0x8d, 0xf4, 0xa0, 0x5f, 0xe6, 0x16, 0xc9, 0xeb,
-	0x1a, 0x64, 0x83, 0xe7, 0x8d, 0x15, 0xad, 0xd0, 0x3c, 0x82, 0xbe, 0x29,
-	0xd3, 0xb6, 0x7f, 0x6e, 0xce, 0x99, 0xd7, 0x8a, 0xa7, 0x4e, 0x6a, 0xa5,
-	0x53, 0x2f, 0x68, 0x7b, 0x9b, 0x2f, 0x74, 0x49, 0x47, 0x16, 0xa7, 0x4e,
-	0xc8, 0x93, 0x9e, 0x26, 0xa4, 0x73, 0x09, 0xbc, 0x2b, 0x58, 0x15, 0x31,
-	0xed, 0x6e, 0x6d, 0x1f, 0xf0, 0xb4, 0xd9, 0x7f, 0xd2, 0x29, 0xdd, 0x86,
-	0x6c, 0xb2, 0xa3, 0xb5, 0x29, 0xf9, 0x33, 0xd0, 0x74, 0xc1, 0x49, 0x91,
-	0x5f, 0x3d, 0x01, 0x4c, 0x44, 0x07, 0xf5, 0x8a, 0x3a, 0xa5, 0x17, 0x4a,
-	0xc7, 0xff, 0xbc, 0xaf, 0x3a, 0xb2, 0x85, 0x6b, 0xa0, 0xff, 0xd6, 0xfd,
-	0xd3, 0xb6, 0xdb, 0x6b, 0x4a, 0xc5, 0xd2, 0x25, 0x6b, 0x15, 0xe5, 0x3a,
-	0x99, 0x73, 0x44, 0x8a, 0x35, 0xec, 0x69, 0x9b, 0xe0, 0x8d, 0x0d, 0xde,
-	0xec, 0x3c, 0x32, 0xa8, 0xff, 0x96, 0x64, 0xfa, 0x2b, 0x9a, 0x19, 0xf2,
-	0x71, 0x49, 0x6e, 0x51, 0xf0, 0x7a, 0xde, 0x81, 0x7e, 0x76, 0xb0, 0x8f,
-	0x7d, 0x13, 0x6a, 0x5f, 0x23, 0x6f, 0xa7, 0x97, 0x45, 0x34, 0x3d, 0xbf,
-	0x1b, 0xf8, 0xa8, 0xb7, 0x5c, 0xf7, 0x04, 0x68, 0x24, 0xed, 0xec, 0xdb,
-	0x80, 0x49, 0x88, 0xeb, 0x74, 0xb5, 0xd0, 0x49, 0x79, 0x93, 0xd7, 0xe4,
-	0x9d, 0x3a, 0xa7, 0xb6, 0x76, 0xce, 0x5f, 0xf9, 0x9b, 0x46, 0x4d, 0xf9,
-	0xa1, 0x3a, 0x2f, 0x6d, 0x8c, 0xeb, 0x52, 0xa1, 0x4e, 0x24, 0xa0, 0x47,
-	0xa2, 0x95, 0x1d, 0x6b, 0x15, 0x57, 0x59, 0x44, 0x37, 0xf2, 0x9d, 0x52,
-	0x54, 0xf4, 0x8d, 0x61, 0x2f, 0xda, 0x1e, 0x6c, 0xc8, 0xe6, 0x59, 0x38,
-	0x97, 0x87, 0x8d, 0x67, 0xd9, 0x97, 0xf2, 0x02, 0xed, 0x9d, 0xb4, 0x9d,
-	0xcf, 0xaa, 0x7f, 0x8e, 0x45, 0x5d, 0x3c, 0xd6, 0x03, 0xda, 0x38, 0x86,
-	0x1d, 0xda, 0x78, 0x3f, 0xa2, 0x89, 0x3b, 0x36, 0x08, 0xfe, 0x70, 0x9d,
-	0x9d, 0x81, 0x9c, 0x0b, 0x2e, 0xf6, 0x74, 0x9d, 0xdf, 0x50, 0x3c, 0xe8,
-	0xc5, 0x79, 0x06, 0xe7, 0xc9, 0xaf, 0x0e, 0xe8, 0xb6, 0x26, 0x65, 0x27,
-	0x9b, 0xa1, 0xdc, 0x03, 0xda, 0x75, 0xd9, 0x74, 0x63, 0x2b, 0xed, 0x91,
-	0xac, 0xa8, 0x87, 0xa6, 0x24, 0x47, 0xb9, 0x96, 0xeb, 0xb8, 0x3e, 0x3b,
-	0x26, 0xfa, 0xaf, 0x7c, 0x6b, 0xdd, 0x59, 0x6d, 0xd9, 0x31, 0x0f, 0x1a,
-	0x02, 0xde, 0x82, 0x27, 0x9f, 0xb6, 0x96, 0x7c, 0xdd, 0xc8, 0x3f, 0xae,
-	0x6d, 0x5d, 0x07, 0x9d, 0xe8, 0x27, 0x0d, 0x27, 0x3a, 0x03, 0x5b, 0x8b,
-	0x68, 0x8a, 0x64, 0xa3, 0x85, 0x38, 0x3e, 0xe9, 0x1c, 0x5c, 0x0f, 0x1f,
-	0xe0, 0xc1, 0x07, 0xc0, 0xaf, 0x3d, 0xeb, 0xc1, 0xfe, 0x3d, 0xfa, 0x8c,
-	0x8c, 0xbc, 0x38, 0x04, 0x1f, 0xb7, 0xe6, 0x63, 0xd0, 0xc6, 0xd1, 0xd7,
-	0xc5, 0x80, 0x8f, 0x99, 0xad, 0xeb, 0xb0, 0x59, 0xf0, 0x78, 0x85, 0x73,
-	0xb0, 0xed, 0x95, 0x12, 0x9e, 0xb6, 0x54, 0x1b, 0xd4, 0xab, 0xc8, 0x97,
-	0xd2, 0xe7, 0xa4, 0xe1, 0x5f, 0xe8, 0x77, 0xe8, 0x57, 0xb8, 0xd6, 0xf7,
-	0x4b, 0x0e, 0x61, 0x7d, 0x99, 0x70, 0x68, 0x43, 0x9d, 0xa2, 0x27, 0x2b,
-	0xda, 0xc1, 0x21, 0xd8, 0xd6, 0xf5, 0x6d, 0xa0, 0x95, 0x36, 0x76, 0x8d,
-	0x48, 0x3b, 0xf7, 0xfb, 0x69, 0x57, 0xf0, 0xef, 0xee, 0x36, 0x61, 0x0d,
-	0x9f, 0xef, 0x86, 0x63, 0x2d, 0xf4, 0x2d, 0x7c, 0x9f, 0xcd, 0x14, 0xa4,
-	0x3f, 0x1c, 0xb3, 0xbf, 0x4a, 0xaf, 0xa3, 0xdf, 0x98, 0x90, 0x1d, 0x27,
-	0x03, 0x9f, 0xb8, 0x63, 0xc9, 0x12, 0xfb, 0x64, 0x40, 0xe3, 0x8e, 0x33,
-	0x91, 0x6f, 0x7c, 0x1f, 0xf0, 0xa0, 0xcf, 0x5b, 0x8d, 0x03, 0x68, 0x3f,
-	0xd3, 0x60, 0x2a, 0x98, 0xdb, 0xc8, 0x0b, 0xfa, 0x63, 0xda, 0x9b, 0xd5,
-	0x6a, 0x6f, 0x7b, 0x60, 0x6f, 0x4e, 0xbb, 0x64, 0x9d, 0xbf, 0x87, 0xbd,
-	0x7d, 0xc3, 0xd1, 0xc0, 0x1b, 0x91, 0x8b, 0xb5, 0x34, 0x6c, 0xdd, 0x4c,
-	0xbf, 0x26, 0x3b, 0x33, 0xb3, 0xa2, 0xc9, 0x09, 0xce, 0x35, 0x30, 0xa7,
-	0x7c, 0x71, 0xe0, 0x0b, 0x2e, 0x1b, 0x4f, 0x81, 0x2e, 0xdf, 0x9f, 0x05,
-	0xce, 0xf2, 0x88, 0x11, 0xda, 0x56, 0x34, 0x6f, 0xdd, 0xef, 0xda, 0xee,
-	0xaf, 0x19, 0x52, 0x19, 0x6e, 0x93, 0xec, 0xf0, 0x12, 0x70, 0x4f, 0x3b,
-	0x81, 0x1d, 0x53, 0xd7, 0x97, 0x81, 0x7f, 0xce, 0x1b, 0x82, 0x1e, 0xd3,
-	0x0e, 0x40, 0x17, 0xf0, 0x2f, 0x03, 0xff, 0x5c, 0xb3, 0x4d, 0xbe, 0x6e,
-	0x46, 0xb1, 0x32, 0x3a, 0x4f, 0x37, 0x96, 0x45, 0xfb, 0x1e, 0x96, 0x2f,
-	0x7a, 0x49, 0xcd, 0x3d, 0x46, 0xff, 0x5a, 0x1d, 0x86, 0x9d, 0x68, 0x55,
-	0x87, 0x7b, 0x1b, 0xb2, 0xbc, 0xba, 0x46, 0x0a, 0xd5, 0xc0, 0x06, 0x0b,
-	0xee, 0x50, 0x25, 0x6d, 0x28, 0x5f, 0x22, 0xb2, 0x0f, 0xb6, 0xb7, 0x6c,
-	0x73, 0xcc, 0xf9, 0x60, 0x6e, 0xbc, 0xd6, 0x0f, 0x9f, 0xc8, 0xf1, 0x7b,
-	0xfe, 0xb4, 0x13, 0xcc, 0x7d, 0xa1, 0x76, 0x57, 0x37, 0xfd, 0x2e, 0xe2,
-	0x44, 0xa6, 0xea, 0xfc, 0xbb, 0x0f, 0xfd, 0x5d, 0x07, 0xf3, 0xd1, 0x78,
-	0xb2, 0xe3, 0x81, 0xce, 0x8a, 0xb6, 0xdf, 0xd6, 0xfb, 0xdb, 0x43, 0x1f,
-	0xb6, 0x1f, 0x93, 0x7b, 0x6b, 0xd5, 0xbe, 0x76, 0x79, 0xcf, 0x60, 0x1c,
-	0xbd, 0x22, 0x62, 0xba, 0xb5, 0x5d, 0xe0, 0x47, 0xb5, 0xb7, 0x65, 0x2e,
-	0x51, 0xaa, 0xf9, 0x72, 0xc1, 0x09, 0x60, 0x30, 0xee, 0x2c, 0xd6, 0xf4,
-	0xfe, 0x84, 0xac, 0x8e, 0x2d, 0xc2, 0xac, 0xc8, 0xae, 0xe1, 0x65, 0x51,
-	0xb0, 0x7d, 0x89, 0x35, 0xd8, 0x54, 0xa9, 0x56, 0xed, 0x6d, 0x19, 0xa7,
-	0x8b, 0xc0, 0xa5, 0xef, 0x59, 0x85, 0x1d, 0x58, 0x83, 0xdd, 0x2a, 0x99,
-	0x5e, 0xc2, 0xeb, 0xfd, 0x9b, 0xd7, 0x70, 0x67, 0x42, 0x7a, 0xfa, 0x36,
-	0xaf, 0xe1, 0xb0, 0x89, 0xb3, 0x65, 0x3c, 0x4c, 0x9c, 0x3b, 0xd6, 0x70,
-	0x8e, 0xac, 0xa7, 0xe7, 0xb0, 0xc0, 0x07, 0x25, 0xda, 0xf3, 0xb2, 0xe7,
-	0x62, 0x6d, 0x70, 0xe2, 0x8b, 0x82, 0x58, 0x37, 0xb2, 0x29, 0xf4, 0xc9,
-	0xe6, 0x1e, 0x17, 0xbc, 0x32, 0x85, 0x3e, 0x4e, 0x93, 0x2a, 0xe4, 0x7c,
-	0x7f, 0x43, 0xf6, 0x5c, 0x68, 0x98, 0xa1, 0x2e, 0x51, 0x27, 0xde, 0x86,
-	0x8d, 0x75, 0x4e, 0x99, 0x88, 0xc3, 0xe7, 0x94, 0x8d, 0xc9, 0x44, 0xb5,
-	0x26, 0x95, 0xed, 0xf9, 0x27, 0x7c, 0xe8, 0xe2, 0x94, 0x05, 0x3f, 0x5a,
-	0x94, 0xce, 0x31, 0x37, 0x87, 0xf9, 0x06, 0x6d, 0x0b, 0x7e, 0x05, 0xb0,
-	0xd0, 0xb5, 0x84, 0x31, 0xbf, 0xf3, 0x55, 0xd7, 0xe0, 0x3e, 0x19, 0xe4,
-	0x4d, 0x89, 0x84, 0x3e, 0x7f, 0xd5, 0xa7, 0x9e, 0x4d, 0x8f, 0x5c, 0x45,
-	0x9e, 0x62, 0xc1, 0x57, 0xc2, 0x7f, 0x40, 0xdf, 0x67, 0x9b, 0x82, 0xb8,
-	0xfe, 0x40, 0x4f, 0x60, 0x63, 0x47, 0xb7, 0x06, 0x4f, 0x31, 0xe9, 0x9b,
-	0xa7, 0x73, 0xcc, 0x01, 0xda, 0x13, 0x6e, 0x6e, 0x7c, 0x9b, 0x71, 0xe6,
-	0xc0, 0x36, 0xfd, 0x4c, 0x65, 0x9b, 0x0e, 0x9f, 0x0e, 0x9b, 0xd2, 0xdd,
-	0x1c, 0xfa, 0x67, 0x22, 0x1b, 0x4a, 0xc3, 0x86, 0xde, 0x56, 0x39, 0xc8,
-	0xb9, 0xe6, 0x29, 0xd8, 0xab, 0xa2, 0x55, 0x26, 0x90, 0x13, 0xe8, 0xa3,
-	0xef, 0x43, 0x4f, 0x70, 0x16, 0xf8, 0xc0, 0x02, 0xb8, 0xa4, 0x8f, 0xbe,
-	0x11, 0xda, 0x33, 0xfb, 0xef, 0xf8, 0x41, 0x7c, 0xf8, 0x7c, 0xb8, 0xff,
-	0x3f, 0x75, 0x07, 0x3e, 0x20, 0xc2, 0x45, 0x3c, 0xc3, 0xda, 0x04, 0xf2,
-	0x99, 0x89, 0xa6, 0xa9, 0xd1, 0x9f, 0x17, 0x3d, 0xe6, 0x21, 0xcc, 0x41,
-	0x1e, 0x0b, 0xfd, 0x22, 0x73, 0x8f, 0xce, 0x90, 0xa7, 0xb9, 0x28, 0xce,
-	0x29, 0x7b, 0x43, 0xcc, 0xc9, 0x94, 0x9d, 0x36, 0xe5, 0x93, 0xa7, 0x73,
-	0x9d, 0x58, 0x87, 0xb9, 0x26, 0xce, 0x0d, 0xbf, 0x84, 0x5c, 0x06, 0x6b,
-	0xce, 0x63, 0x7d, 0x7b, 0x68, 0xf3, 0x17, 0xa5, 0x0c, 0x9f, 0x6a, 0xda,
-	0x7c, 0x9f, 0xeb, 0x91, 0x0e, 0x8c, 0x1b, 0xd8, 0x0b, 0x7e, 0xc2, 0x50,
-	0x7c, 0x46, 0x2c, 0x48, 0x5d, 0xc7, 0x1c, 0x09, 0x6b, 0x33, 0x58, 0x4b,
-	0xbf, 0xcb, 0xb5, 0xcf, 0x82, 0x0e, 0x8c, 0x1b, 0x84, 0xa1, 0x8f, 0x12,
-	0xdf, 0xcd, 0x6d, 0x86, 0x26, 0xf9, 0xe7, 0x0c, 0x3b, 0x5a, 0x1b, 0xe1,
-	0xdd, 0xb8, 0x96, 0xf9, 0x09, 0x71, 0xf7, 0x84, 0xf1, 0x7f, 0x5c, 0x0a,
-	0xcd, 0x02, 0x7e, 0x22, 0xd3, 0xc7, 0x90, 0x8f, 0xd9, 0x6d, 0x88, 0x55,
-	0x9c, 0xdf, 0x6a, 0x05, 0x67, 0x8d, 0xe0, 0xee, 0xef, 0x5b, 0x3f, 0xfe,
-	0x42, 0x72, 0xcd, 0x47, 0xd2, 0xc2, 0xa4, 0x80, 0x18, 0x01, 0x5e, 0x65,
-	0xa6, 0x98, 0xc3, 0x15, 0x1b, 0x4a, 0xa6, 0x98, 0x1b, 0x83, 0x5f, 0x0c,
-	0xf2, 0xa2, 0x73, 0xde, 0x46, 0xd9, 0x59, 0xe0, 0x77, 0x01, 0x3c, 0xce,
-	0x40, 0x87, 0xc6, 0x01, 0x2b, 0x87, 0x81, 0x83, 0xf1, 0xd7, 0xd1, 0xf3,
-	0x49, 0x29, 0x5b, 0xcc, 0x13, 0xda, 0x49, 0x67, 0x81, 0xf6, 0xaf, 0xe7,
-	0x37, 0x63, 0x8e, 0xfd, 0x7b, 0x7b, 0x02, 0x99, 0x75, 0x71, 0x3c, 0xa1,
-	0xe7, 0x7b, 0x36, 0xcc, 0x7f, 0xbf, 0x2b, 0xa0, 0x4d, 0x8d, 0x31, 0xff,
-	0xf2, 0x86, 0xf1, 0xef, 0x25, 0xd7, 0x8f, 0xef, 0xda, 0x16, 0xea, 0x20,
-	0xfa, 0x8f, 0x85, 0xf4, 0x82, 0xb6, 0x55, 0x5a, 0xa3, 0x9c, 0x57, 0x16,
-	0x74, 0xe4, 0x7f, 0x6e, 0x6e, 0x27, 0x62, 0x7d, 0x46, 0x4a, 0x4d, 0xd0,
-	0xbd, 0x1a, 0xcb, 0x56, 0xd7, 0x54, 0xd6, 0xd6, 0x04, 0xbe, 0xbe, 0xd4,
-	0xf4, 0x91, 0x3b, 0xb5, 0xc6, 0xbd, 0x61, 0xf4, 0x2b, 0xd8, 0xa7, 0x20,
-	0xd3, 0xde, 0x85, 0x82, 0x6e, 0x1f, 0x09, 0xf2, 0x3e, 0xfb, 0x9b, 0x5a,
-	0x69, 0x99, 0xf9, 0x20, 0xec, 0xc9, 0x56, 0xf9, 0x3f, 0xe2, 0xca, 0x51,
-	0xad, 0x70, 0xea, 0x38, 0xf2, 0xc1, 0x15, 0xfc, 0x4e, 0xe3, 0xd7, 0xc0,
-	0x2f, 0xca, 0xc3, 0x9f, 0x41, 0x1e, 0xaf, 0x7c, 0x2c, 0xe2, 0x41, 0xb0,
-	0xff, 0x1b, 0x2b, 0xd0, 0xb3, 0xe3, 0x29, 0xf9, 0x86, 0xad, 0xf7, 0xe9,
-	0x81, 0x5f, 0x29, 0x20, 0x8f, 0xb5, 0xde, 0x96, 0xdf, 0x0e, 0xf3, 0x22,
-	0x91, 0xd7, 0x16, 0xc0, 0xc7, 0x91, 0xfd, 0xa1, 0xce, 0x16, 0xee, 0x75,
-	0x95, 0xff, 0x0c, 0xf3, 0x1e, 0xe4, 0x5f, 0x05, 0xb5, 0xea, 0x5b, 0xe0,
-	0x8d, 0x26, 0x6f, 0x41, 0x87, 0x5e, 0x5b, 0xe8, 0x00, 0x3d, 0xb6, 0x94,
-	0x27, 0x91, 0x2f, 0x68, 0x83, 0xd6, 0x26, 0xad, 0x03, 0x76, 0x0c, 0x1b,
-	0x57, 0x63, 0x49, 0xb4, 0xe5, 0x2f, 0xcd, 0x2c, 0xd5, 0x74, 0xac, 0x45,
-	0xee, 0x93, 0x43, 0x1f, 0xb2, 0xbf, 0xb2, 0x40, 0x38, 0x5d, 0x5e, 0x5f,
-	0x30, 0xe4, 0x4d, 0xe4, 0x52, 0x6f, 0xd9, 0x97, 0x66, 0x10, 0xb7, 0xfa,
-	0x11, 0x23, 0x50, 0x8b, 0xec, 0xa4, 0x9f, 0xde, 0x61, 0xe2, 0x59, 0xc2,
-	0x6f, 0x1f, 0x72, 0xc1, 0x8f, 0x86, 0xf9, 0xb8, 0xf5, 0xa4, 0x2d, 0x01,
-	0x18, 0xae, 0x37, 0x41, 0x5b, 0x37, 0xe4, 0x9f, 0xb5, 0xa6, 0xe4, 0xf5,
-	0x1e, 0x95, 0xaf, 0x68, 0x9c, 0x0f, 0x7c, 0xd3, 0x87, 0xe7, 0xc9, 0x67,
-	0x03, 0x3a, 0xce, 0x31, 0xdf, 0xd1, 0x87, 0x12, 0x5f, 0x76, 0xac, 0x80,
-	0xc3, 0x5c, 0x59, 0x08, 0xfa, 0xd1, 0x9c, 0x68, 0x51, 0x1c, 0xa3, 0x6f,
-	0x2c, 0xc1, 0x4e, 0x38, 0x9e, 0x10, 0x25, 0x83, 0x75, 0xf2, 0x94, 0x84,
-	0x99, 0x3f, 0x3b, 0x33, 0x67, 0x53, 0xae, 0xf0, 0x71, 0xb5, 0x48, 0xae,
-	0x94, 0x51, 0xbb, 0x54, 0x17, 0xbe, 0x09, 0xb9, 0xea, 0x61, 0xbe, 0x0f,
-	0x1b, 0x3f, 0x4e, 0xf9, 0xa2, 0xfe, 0x5b, 0x40, 0xee, 0xb3, 0x20, 0xc9,
-	0xa0, 0x5e, 0x39, 0x8a, 0x3c, 0x1f, 0xf2, 0xab, 0x1d, 0x07, 0x0e, 0xd8,
-	0x69, 0x6d, 0x05, 0x4f, 0xd4, 0x16, 0xb5, 0xd3, 0x78, 0x0e, 0xe0, 0xd9,
-	0xa0, 0x6e, 0x86, 0xb9, 0xc6, 0x87, 0xe8, 0x81, 0x3d, 0x95, 0x68, 0x4f,
-	0xf2, 0xfd, 0x66, 0x5e, 0xbe, 0xdb, 0x1c, 0x93, 0xe7, 0x9b, 0x39, 0xf9,
-	0xbb, 0xa6, 0x23, 0xdf, 0x69, 0x8e, 0xc8, 0xb7, 0x9b, 0xc3, 0xac, 0xc9,
-	0x90, 0x37, 0x65, 0x98, 0x37, 0xc9, 0xbd, 0xde, 0xad, 0xb0, 0x77, 0xca,
-	0xff, 0xd2, 0x4c, 0xa1, 0x31, 0x28, 0xe5, 0x63, 0xf0, 0xcf, 0xce, 0xcd,
-	0xac, 0x25, 0xe5, 0x11, 0x87, 0x35, 0x41, 0x1b, 0xdf, 0xa3, 0xce, 0x84,
-	0xff, 0x86, 0x3f, 0x9b, 0x4a, 0x65, 0x4f, 0xbb, 0x46, 0x47, 0xe8, 0x03,
-	0x6e, 0x49, 0x4a, 0x07, 0xf6, 0x82, 0x0f, 0x5c, 0x7a, 0x1a, 0x36, 0xa0,
-	0x6a, 0x9a, 0x04, 0xfc, 0x0d, 0x73, 0x01, 0x93, 0x76, 0x8c, 0x3a, 0x30,
-	0x9b, 0x71, 0x0d, 0xd6, 0x77, 0xb4, 0x67, 0x03, 0x81, 0x83, 0x70, 0xfb,
-	0x2c, 0xca, 0xcd, 0xb4, 0xe9, 0x57, 0x0b, 0xa1, 0x8f, 0x4b, 0x84, 0x7a,
-	0x69, 0x61, 0xfe, 0xf1, 0xd0, 0x27, 0x6f, 0xdc, 0x07, 0xf1, 0x02, 0xf9,
-	0x64, 0xb0, 0x8e, 0xb0, 0x5a, 0x08, 0xdb, 0x17, 0xce, 0x75, 0x82, 0xdf,
-	0x8e, 0x94, 0xbd, 0x37, 0x35, 0xe6, 0xd9, 0xc8, 0x77, 0x30, 0x1e, 0xc1,
-	0xf8, 0x4a, 0x38, 0xfe, 0x9c, 0x4c, 0x2f, 0x0a, 0x68, 0xfd, 0x89, 0x56,
-	0x54, 0xe3, 0x31, 0x8c, 0x75, 0x8c, 0x0d, 0xd6, 0x02, 0x68, 0x37, 0x27,
-	0xa9, 0xeb, 0xba, 0x4d, 0x5f, 0x38, 0x19, 0xfa, 0xc3, 0x82, 0x1c, 0xf6,
-	0x06, 0x0b, 0x57, 0x11, 0x33, 0xb4, 0xb6, 0x28, 0xff, 0xd9, 0x0e, 0xbe,
-	0xf8, 0xfe, 0xed, 0xac, 0xb9, 0x93, 0xa6, 0x7c, 0x7b, 0x3e, 0x6b, 0x3d,
-	0xa4, 0x7f, 0x0d, 0x67, 0xf2, 0xfd, 0x83, 0x76, 0xf6, 0xc8, 0x94, 0xde,
-	0x25, 0xdf, 0x3d, 0xca, 0xd8, 0x7b, 0x76, 0xe6, 0x07, 0xd0, 0xbd, 0xfa,
-	0x4a, 0xbb, 0xd4, 0xeb, 0xa6, 0x5c, 0x19, 0x1d, 0x04, 0x9d, 0x96, 0xd4,
-	0x1b, 0x49, 0xe4, 0x73, 0x9b, 0x65, 0xb6, 0x5f, 0x19, 0x18, 0xfc, 0xf4,
-	0xb0, 0xf2, 0xd3, 0xae, 0x8d, 0x67, 0xe3, 0xe7, 0x3d, 0xeb, 0xcf, 0x5c,
-	0x02, 0xfd, 0xd0, 0xeb, 0xe4, 0x76, 0x25, 0xe7, 0xb2, 0x37, 0x68, 0x95,
-	0x75, 0xc4, 0x2e, 0x73, 0xd0, 0xba, 0x57, 0xff, 0x2f, 0xff, 0xf3, 0x26,
-	0x65, 0xf7, 0xaa, 0xaa, 0x61, 0x54, 0xac, 0xc3, 0x7e, 0x4b, 0x2b, 0x2f,
-	0x83, 0x16, 0xf8, 0xd8, 0xc6, 0xf6, 0x70, 0x9c, 0x51, 0xbc, 0x38, 0xdb,
-	0xe8, 0x90, 0xef, 0xd4, 0xb7, 0xc8, 0x72, 0x9d, 0xef, 0xdb, 0x65, 0xa9,
-	0x3e, 0x78, 0xb5, 0x4f, 0xef, 0x97, 0xf3, 0xd7, 0x5c, 0x6f, 0xdd, 0xa3,
-	0x23, 0x37, 0x98, 0xfc, 0x40, 0x7e, 0x39, 0xda, 0x23, 0x3f, 0xfe, 0x72,
-	0xf6, 0x99, 0x3f, 0xd5, 0x61, 0x03, 0xa3, 0x9d, 0xb4, 0x6d, 0xf4, 0x39,
-	0x9f, 0xbd, 0x5a, 0xd0, 0xa9, 0xdb, 0x3f, 0x02, 0x4f, 0xb3, 0x0b, 0x81,
-	0x1d, 0x10, 0x37, 0xf1, 0x42, 0x37, 0xec, 0xef, 0x01, 0x27, 0xde, 0x35,
-	0x06, 0x81, 0xeb, 0x7b, 0x8a, 0x17, 0xb7, 0x3b, 0xd9, 0xab, 0x08, 0x49,
-	0xfe, 0x15, 0x7b, 0x70, 0x78, 0x87, 0xbe, 0x5d, 0xea, 0xe9, 0xeb, 0xad,
-	0xe7, 0xe0, 0xff, 0x0b, 0xa9, 0xec, 0x91, 0xcb, 0x72, 0x76, 0xe6, 0xa2,
-	0x4d, 0xfd, 0xa7, 0xdf, 0x78, 0x09, 0xb9, 0xa7, 0x25, 0x0b, 0x0d, 0xfa,
-	0x4b, 0xe2, 0x62, 0xfe, 0xbf, 0xcb, 0x3a, 0xac, 0x33, 0x4f, 0xc0, 0x3b,
-	0xcc, 0x1b, 0xbf, 0x4e, 0x39, 0xb7, 0x11, 0x76, 0xb8, 0xa0, 0xff, 0x62,
-	0x03, 0x8f, 0x06, 0xad, 0xbd, 0x3a, 0xf7, 0xfb, 0x37, 0xec, 0xfb, 0x0e,
-	0x68, 0x1d, 0x04, 0x2c, 0x62, 0x66, 0xba, 0x75, 0x8f, 0x57, 0xd4, 0x1e,
-	0xc7, 0x1a, 0xc8, 0xf5, 0x56, 0xf7, 0xc0, 0x5c, 0x43, 0xc7, 0x39, 0x4d,
-	0x25, 0x97, 0x2b, 0xa3, 0xe4, 0xef, 0x9e, 0x5e, 0xe6, 0x99, 0x46, 0xfe,
-	0xaf, 0xfd, 0xa8, 0x7e, 0x7c, 0x7e, 0x7e, 0x12, 0xfe, 0xd9, 0xf7, 0x2f,
-	0xec, 0x1a, 0x04, 0x0d, 0xa8, 0x43, 0xd3, 0xe4, 0xf9, 0xd9, 0x19, 0x17,
-	0x38, 0x8a, 0x0a, 0xf7, 0x25, 0x59, 0x01, 0xee, 0x09, 0xf2, 0x01, 0xb8,
-	0xe7, 0x38, 0xaf, 0x64, 0x80, 0xf9, 0x46, 0x06, 0x78, 0x23, 0xfd, 0x4c,
-	0x42, 0xd7, 0x76, 0x5b, 0xb7, 0x07, 0xba, 0x9e, 0x60, 0x6c, 0x7b, 0x0e,
-	0xba, 0x57, 0x48, 0x52, 0x7f, 0xda, 0x7b, 0xd7, 0xf4, 0xa7, 0x15, 0x7f,
-	0xbb, 0x94, 0x16, 0x12, 0xc0, 0x6b, 0xca, 0x5c, 0x8e, 0x78, 0x31, 0xae,
-	0x53, 0xf7, 0x2b, 0xa1, 0xee, 0x77, 0x86, 0xb8, 0x17, 0xc1, 0x93, 0x6c,
-	0xa6, 0xae, 0xb3, 0x8e, 0xda, 0xa6, 0x6a, 0x5b, 0x03, 0x36, 0x5d, 0xae,
-	0xb1, 0x0e, 0xe5, 0xfd, 0xc8, 0xa5, 0x99, 0x69, 0xd4, 0xaa, 0xe5, 0xda,
-	0x88, 0x56, 0x6e, 0xda, 0x5a, 0xd9, 0xa3, 0xbe, 0xed, 0xb2, 0x2e, 0x28,
-	0x1e, 0xa7, 0x65, 0xa9, 0xf9, 0x4b, 0xbf, 0xba, 0x6b, 0x13, 0xfa, 0xd0,
-	0xfd, 0x09, 0xca, 0xf7, 0xb3, 0xa4, 0x0b, 0x41, 0x9c, 0xfc, 0x4e, 0xc9,
-	0xc9, 0x21, 0x14, 0xbd, 0xc8, 0xad, 0x4e, 0x0d, 0x11, 0x3f, 0xe8, 0x48,
-	0xa5, 0x64, 0xd9, 0xe3, 0x1e, 0x67, 0x67, 0xc8, 0xcb, 0xf2, 0x71, 0x4b,
-	0x0e, 0x2b, 0xf9, 0xbd, 0xac, 0x6c, 0xbb, 0xbc, 0x62, 0xc8, 0x74, 0x72,
-	0xd0, 0x7a, 0x58, 0xb2, 0x57, 0x2f, 0x18, 0xd9, 0x67, 0xa6, 0x60, 0xd7,
-	0x4b, 0x8b, 0x86, 0xb8, 0xaa, 0xde, 0xa2, 0x8c, 0xb2, 0x0b, 0xb0, 0xfc,
-	0xf0, 0xec, 0x7b, 0x5b, 0xce, 0xde, 0x2d, 0x2b, 0x4f, 0xff, 0x26, 0x7c,
-	0xce, 0x01, 0xc8, 0xc2, 0xcc, 0x1c, 0x42, 0x5e, 0xf1, 0xb4, 0x0c, 0x5a,
-	0x55, 0xe4, 0xc9, 0xe0, 0x3b, 0xda, 0x01, 0x65, 0x03, 0x17, 0x74, 0x8c,
-	0x07, 0xc8, 0x27, 0x8e, 0xaf, 0x95, 0x0b, 0xca, 0x96, 0xd2, 0xea, 0xdd,
-	0x0e, 0xe0, 0x08, 0xde, 0x71, 0xfc, 0x19, 0xd9, 0xa1, 0xde, 0xdd, 0xa9,
-	0xde, 0x55, 0xe9, 0x2b, 0x94, 0xfc, 0xbe, 0x82, 0x3d, 0xc9, 0xe3, 0x68,
-	0xbe, 0x4b, 0x02, 0x5b, 0x8a, 0xf8, 0x6e, 0xc9, 0xc1, 0x46, 0x4a, 0xbe,
-	0x84, 0xfa, 0xe7, 0x8e, 0xc6, 0x80, 0x94, 0x20, 0xc7, 0xe9, 0xdc, 0x83,
-	0xbd, 0x3c, 0x5b, 0x71, 0x25, 0xfb, 0x8c, 0xe8, 0xa4, 0xf5, 0x4e, 0x39,
-	0xe4, 0x45, 0xf4, 0x74, 0x86, 0xf4, 0x4d, 0x86, 0xe3, 0x44, 0x48, 0x43,
-	0x2b, 0xbe, 0x4e, 0xe0, 0x42, 0xac, 0xcf, 0x79, 0x21, 0x1e, 0xfa, 0x11,
-	0xd0, 0x3a, 0x99, 0x96, 0x15, 0x8f, 0x74, 0x6c, 0x91, 0x6a, 0x8a, 0xfd,
-	0x03, 0xd0, 0x37, 0xe2, 0xd9, 0xc4, 0x7c, 0x66, 0x1d, 0x8f, 0x1f, 0x6c,
-	0x54, 0xc0, 0x63, 0xf2, 0x97, 0xeb, 0x10, 0x23, 0x3e, 0x47, 0xf9, 0xed,
-	0x46, 0x2e, 0x6f, 0x07, 0xba, 0x69, 0xad, 0xed, 0x59, 0x3a, 0xde, 0x0d,
-	0x59, 0x71, 0xdf, 0x0e, 0x99, 0x84, 0xdd, 0x17, 0xeb, 0xdc, 0x7f, 0x12,
-	0x7a, 0x74, 0x51, 0xed, 0x5f, 0x5a, 0xe9, 0x0f, 0xe1, 0x09, 0xdb, 0xbd,
-	0x01, 0xb6, 0x5d, 0xf6, 0x2e, 0x58, 0x1f, 0x01, 0xff, 0xbb, 0x80, 0xd7,
-	0xe5, 0x44, 0x8e, 0xf0, 0xc4, 0x83, 0x75, 0xf5, 0xd4, 0x27, 0xe0, 0x49,
-	0xaa, 0xba, 0xbe, 0x58, 0x6f, 0x97, 0xe2, 0x42, 0x84, 0x8b, 0x78, 0x3e,
-	0x40, 0xdd, 0x7b, 0xb7, 0xc2, 0x35, 0xad, 0x70, 0xe1, 0x7d, 0x9d, 0x3e,
-	0xe7, 0x26, 0xc0, 0xa3, 0x76, 0xb7, 0x41, 0x5b, 0xb2, 0x4b, 0xaa, 0xaa,
-	0x76, 0xef, 0x50, 0xbe, 0xa6, 0x9a, 0xdc, 0x8c, 0xf7, 0x3e, 0xf6, 0xdc,
-	0x8d, 0x7c, 0xa6, 0x1b, 0x73, 0x99, 0x0d, 0x73, 0x1b, 0xe9, 0x4f, 0x6c,
-	0xa0, 0xff, 0xbf, 0x7b, 0x19, 0x52, 0xe6, 0x72, 0xc1, 0xba, 0x12, 0xd6,
-	0xcd, 0x1e, 0x87, 0x4d, 0x30, 0x4f, 0x4f, 0x31, 0x36, 0x5f, 0xa3, 0x68,
-	0x99, 0x5d, 0xf9, 0x29, 0xd6, 0xf5, 0x03, 0x36, 0x1a, 0x07, 0x7c, 0x78,
-	0x0a, 0x78, 0x8e, 0xd7, 0xd5, 0x1d, 0x05, 0x64, 0xf0, 0xbe, 0x3a, 0x7b,
-	0xb5, 0xfe, 0x69, 0x3c, 0xbb, 0xa6, 0x85, 0x5f, 0xe4, 0x15, 0xe9, 0x25,
-	0xad, 0xbc, 0x2f, 0x82, 0xbd, 0x39, 0xd0, 0xe3, 0xa4, 0x21, 0xa5, 0x1c,
-	0xe2, 0xba, 0xc7, 0xbb, 0x57, 0xda, 0xe5, 0x40, 0x50, 0x23, 0xd8, 0x8c,
-	0xef, 0xa6, 0x3a, 0xfb, 0xa1, 0x15, 0xde, 0xbf, 0x66, 0x78, 0x47, 0x37,
-	0x8c, 0xda, 0x5b, 0x1e, 0x5a, 0xb1, 0xe5, 0x6b, 0x8d, 0x61, 0x79, 0xb8,
-	0x91, 0xb5, 0xee, 0x81, 0x0f, 0x28, 0xaf, 0xde, 0xcb, 0x6e, 0x4b, 0xd2,
-	0x7f, 0x99, 0xc8, 0x3d, 0xdb, 0xec, 0x20, 0x17, 0xa9, 0xb2, 0x36, 0x3b,
-	0x9e, 0xe5, 0x7d, 0x8d, 0x55, 0x97, 0x8d, 0xf9, 0xca, 0xff, 0x65, 0xae,
-	0xc2, 0xfd, 0xe9, 0xaf, 0x91, 0x9b, 0x78, 0xc8, 0x4d, 0x3c, 0xe4, 0x26,
-	0x1e, 0x72, 0x13, 0x0f, 0xb9, 0x89, 0x87, 0xdc, 0xc4, 0x43, 0x6e, 0xe2,
-	0x21, 0x37, 0x41, 0x1d, 0x10, 0xd4, 0x07, 0xe3, 0xc8, 0xb9, 0xe1, 0xbf,
-	0xbc, 0x5b, 0xc2, 0xdc, 0x22, 0x8a, 0xcd, 0x9c, 0x3b, 0xbf, 0xc9, 0x0d,
-	0xea, 0x2b, 0xe5, 0x13, 0x0a, 0xcd, 0x89, 0x30, 0x07, 0xe2, 0x9a, 0x28,
-	0x76, 0x73, 0x9d, 0x8c, 0xb9, 0xa8, 0x3d, 0x0b, 0x93, 0xcc, 0x91, 0x82,
-	0x98, 0x15, 0xe4, 0xe7, 0xaf, 0x22, 0x4f, 0xca, 0x20, 0x4f, 0x1a, 0x40,
-	0x4e, 0xc4, 0x7b, 0xea, 0xe8, 0x2e, 0xa9, 0xa0, 0x1d, 0xf4, 0xc6, 0xb5,
-	0x2f, 0x79, 0xcc, 0xdf, 0xed, 0x4c, 0x59, 0xd7, 0x8f, 0xf7, 0x89, 0x2f,
-	0xc5, 0xd1, 0xaf, 0x23, 0x57, 0xfe, 0x4b, 0x75, 0x6f, 0x36, 0x31, 0x44,
-	0x99, 0xdf, 0xf7, 0x31, 0xf9, 0x72, 0xc4, 0xdf, 0xe0, 0xbe, 0x4f, 0x5f,
-	0x22, 0xff, 0x44, 0x7a, 0xcf, 0x80, 0xe1, 0x67, 0x12, 0x92, 0x3c, 0xb9,
-	0x05, 0x73, 0x96, 0xf4, 0xa9, 0x3b, 0x23, 0x88, 0xf2, 0xcc, 0x7f, 0x40,
-	0x5e, 0xb6, 0xe8, 0x67, 0x78, 0xb3, 0x40, 0xbc, 0xf4, 0xaf, 0xf5, 0x99,
-	0x62, 0xbd, 0xae, 0x74, 0xea, 0x60, 0xa3, 0x84, 0x3c, 0xca, 0xe8, 0x93,
-	0x0e, 0x13, 0xb5, 0x54, 0x84, 0x9b, 0x38, 0xdf, 0x4c, 0xaa, 0x1a, 0xe7,
-	0xcc, 0xaa, 0x3c, 0x21, 0x6b, 0xee, 0x53, 0x9f, 0xa9, 0x2e, 0x64, 0xd3,
-	0xac, 0x71, 0x0b, 0x56, 0x7d, 0xe6, 0x49, 0xe0, 0x58, 0x46, 0x6e, 0x60,
-	0xa8, 0xbd, 0xeb, 0x33, 0xb3, 0x0b, 0xc1, 0xbd, 0x55, 0x40, 0x03, 0xe3,
-	0x55, 0x87, 0x18, 0x4b, 0xc1, 0xfd, 0x95, 0xae, 0x60, 0x09, 0x47, 0x78,
-	0x13, 0x70, 0x94, 0xdb, 0x30, 0x60, 0x29, 0x3b, 0xd2, 0x50, 0x9f, 0xa9,
-	0xd4, 0x5b, 0x69, 0x20, 0x1e, 0xe2, 0x8d, 0xce, 0xc3, 0xb3, 0x24, 0x45,
-	0x3f, 0xe9, 0xfb, 0xe5, 0xd1, 0x81, 0xb0, 0xae, 0x44, 0x1d, 0x79, 0xcc,
-	0x0c, 0xf4, 0x5c, 0x8d, 0xff, 0x58, 0xc5, 0xa9, 0x8c, 0xce, 0x79, 0x3e,
-	0xf1, 0x2e, 0xf7, 0x28, 0xe6, 0x30, 0x5e, 0x8e, 0xd6, 0xea, 0xe1, 0xda,
-	0xae, 0x16, 0x7e, 0xb6, 0x85, 0xfb, 0x91, 0x26, 0x9e, 0xf3, 0x15, 0xec,
-	0x45, 0xba, 0xb8, 0xc6, 0x04, 0x6d, 0x90, 0xa5, 0xf7, 0xbf, 0xe5, 0x7d,
-	0xeb, 0x99, 0xc8, 0x53, 0x13, 0x30, 0x5c, 0x4f, 0x1c, 0x11, 0x0c, 0x5e,
-	0x9c, 0x09, 0xe0, 0xf4, 0xd5, 0x7b, 0xbe, 0x4f, 0xda, 0xb7, 0x95, 0xd6,
-	0x68, 0xff, 0x08, 0xcf, 0x70, 0x20, 0xb7, 0x55, 0x78, 0xf5, 0x7f, 0x7f,
-	0xe1, 0x09, 0x5d, 0xfc, 0xd0, 0x7d, 0xe9, 0x70, 0x4b, 0x8d, 0x1c, 0xdd,
-	0x3b, 0xb0, 0xfe, 0x67, 0x3d, 0xcf, 0xef, 0x03, 0xad, 0xf5, 0x69, 0x29,
-	0x8c, 0x65, 0xdb, 0xa4, 0x60, 0xb2, 0x56, 0x19, 0x0f, 0xc7, 0x5b, 0x11,
-	0xdb, 0x38, 0xbe, 0x15, 0xfc, 0x85, 0x2e, 0x3b, 0x1d, 0x61, 0xad, 0x94,
-	0x0c, 0xbe, 0xeb, 0x0c, 0xd3, 0x8e, 0x58, 0x6b, 0x6e, 0x0e, 0xe7, 0x22,
-	0x3b, 0xa2, 0x1f, 0x36, 0xc3, 0x39, 0xfa, 0x5b, 0x1d, 0xf5, 0x12, 0xfb,
-	0xc0, 0xb3, 0xdc, 0x6a, 0x4b, 0xd1, 0x33, 0x29, 0xa7, 0x17, 0x23, 0xbf,
-	0x05, 0x9f, 0x32, 0x64, 0x86, 0xbe, 0xbf, 0x13, 0xbe, 0xaf, 0x5b, 0xf6,
-	0xc2, 0x67, 0xed, 0x83, 0xcf, 0xda, 0x8f, 0x1a, 0x75, 0x7c, 0xa5, 0xf5,
-	0x3e, 0x97, 0x75, 0x71, 0x55, 0x0e, 0x29, 0xf9, 0x57, 0x7c, 0xc3, 0xfe,
-	0x00, 0x3a, 0xb0, 0x53, 0xe5, 0x7b, 0x81, 0x4e, 0xc0, 0xdf, 0x3a, 0x49,
-	0xe8, 0xc4, 0xc6, 0x7b, 0xe3, 0x61, 0xd8, 0x46, 0x47, 0x41, 0xc5, 0x86,
-	0x95, 0x80, 0xf7, 0xd5, 0x7a, 0xc0, 0x7b, 0xf8, 0x65, 0xe0, 0x37, 0xa5,
-	0xd2, 0xb0, 0xa4, 0x82, 0x7d, 0x2b, 0xd8, 0xb7, 0x82, 0xda, 0x72, 0xb6,
-	0xd1, 0xfa, 0xed, 0xaa, 0x2b, 0xa4, 0x9d, 0xb0, 0x51, 0xdf, 0x6a, 0x39,
-	0x7f, 0xf4, 0x3c, 0x02, 0xfe, 0x3f, 0x02, 0xfe, 0x1f, 0x46, 0x4d, 0xf5,
-	0x00, 0x6a, 0xaa, 0xfb, 0x50, 0x53, 0x1d, 0x42, 0x4d, 0x35, 0x85, 0x9a,
-	0xea, 0x6e, 0xf8, 0x8f, 0x3b, 0xe1, 0x3f, 0x26, 0xe1, 0x3f, 0x26, 0xd4,
-	0x9d, 0xd1, 0x41, 0x6f, 0xe3, 0x1d, 0x4a, 0xb4, 0x17, 0xdb, 0x1b, 0x22,
-	0x50, 0x81, 0xf2, 0xb1, 0x71, 0xa9, 0x37, 0x59, 0x5b, 0x39, 0xea, 0x3e,
-	0x6c, 0xda, 0x99, 0xd4, 0xa6, 0x90, 0xbf, 0xdf, 0x33, 0xc2, 0x9a, 0x2b,
-	0xa9, 0x15, 0x55, 0xcd, 0x95, 0x7d, 0xc1, 0x45, 0x8a, 0x84, 0xdc, 0x0f,
-	0x67, 0xce, 0x9e, 0x2e, 0x1a, 0x51, 0xbd, 0xd3, 0xbb, 0x5a, 0xef, 0x2c,
-	0xcf, 0xb3, 0xde, 0x79, 0x75, 0xb5, 0xde, 0x59, 0x9e, 0x67, 0xbd, 0xf3,
-	0xca, 0xba, 0x7a, 0xe7, 0xca, 0xd3, 0x97, 0xd6, 0xd5, 0x3b, 0x57, 0x9e,
-	0x7e, 0x29, 0x1c, 0x4b, 0xa8, 0x0f, 0x21, 0xad, 0x96, 0x83, 0x67, 0x4f,
-	0x98, 0x73, 0x34, 0xfb, 0xd6, 0xff, 0xdf, 0x74, 0xca, 0x96, 0x35, 0xb1,
-	0xff, 0x68, 0x6b, 0x50, 0x23, 0xb5, 0xce, 0x77, 0xb7, 0xcc, 0x5f, 0x56,
-	0xdf, 0x4b, 0xcb, 0xb5, 0xcd, 0xef, 0xc2, 0x03, 0xcb, 0xca, 0x10, 0xf3,
-	0xbc, 0x0f, 0x7c, 0x7e, 0xf3, 0x73, 0xf5, 0x0e, 0xf5, 0xcd, 0xcd, 0x55,
-	0xf9, 0x36, 0xec, 0x7c, 0xf4, 0xd1, 0xad, 0x81, 0x2f, 0x60, 0x3f, 0xa5,
-	0x05, 0xfe, 0xfd, 0x01, 0xe0, 0x01, 0xaf, 0x3d, 0x53, 0xdd, 0x07, 0x05,
-	0xe7, 0x0d, 0xee, 0xc6, 0xcd, 0xfc, 0xe5, 0x19, 0xe6, 0xd6, 0x55, 0x85,
-	0x9b, 0xf5, 0x23, 0x6b, 0xce, 0x28, 0x06, 0x44, 0xb8, 0x5e, 0x4d, 0x05,
-	0x74, 0xbb, 0xa8, 0x1d, 0xb9, 0x26, 0x1a, 0xb7, 0xd6, 0x9a, 0x9d, 0xe1,
-	0xbd, 0xdb, 0xe5, 0x20, 0xaf, 0x52, 0xf8, 0xcc, 0x10, 0xdf, 0xcf, 0xfd,
-	0xc0, 0xf7, 0x10, 0xde, 0x6a, 0x81, 0x1f, 0x47, 0xae, 0xc7, 0x7b, 0x1a,
-	0xe6, 0x6c, 0xa6, 0xbc, 0x33, 0xdf, 0x25, 0xff, 0x79, 0xd4, 0xf7, 0x27,
-	0x9c, 0xec, 0xf0, 0x25, 0xd4, 0x1e, 0x27, 0x69, 0x27, 0xa3, 0xa4, 0x73,
-	0x30, 0x33, 0x2b, 0xa9, 0x3e, 0xd2, 0x72, 0x5e, 0x3f, 0xac, 0x7d, 0x98,
-	0x6e, 0x3d, 0xdc, 0xe7, 0x1f, 0x5b, 0xf6, 0xc9, 0xb4, 0xec, 0x53, 0xa0,
-	0xcd, 0xd6, 0xef, 0xc0, 0x99, 0x2b, 0xdb, 0xaf, 0xb7, 0x52, 0x61, 0x5d,
-	0xf6, 0xf0, 0xe8, 0x66, 0x59, 0xe8, 0xcf, 0x9e, 0x7d, 0x05, 0xf9, 0x7a,
-	0x79, 0x14, 0x73, 0xa9, 0x41, 0xbc, 0xe3, 0x7c, 0xb6, 0x8e, 0x5c, 0xf4,
-	0x6c, 0x5d, 0xb6, 0x01, 0x3e, 0x5b, 0x11, 0xe1, 0x3c, 0xfb, 0x8a, 0xb6,
-	0x7a, 0xe8, 0x03, 0xd2, 0x17, 0x70, 0xe6, 0x29, 0xd4, 0x5f, 0x87, 0x83,
-	0x7b, 0xb4, 0x70, 0x9f, 0x1b, 0xb5, 0x20, 0x6f, 0xce, 0x69, 0x95, 0xf0,
-	0x0e, 0xf0, 0x2b, 0xf0, 0x17, 0x86, 0x4e, 0xd8, 0x77, 0x80, 0x5b, 0x93,
-	0xa5, 0xa3, 0x86, 0xba, 0x3b, 0x2d, 0x8f, 0x52, 0xd6, 0x7c, 0x7e, 0x14,
-	0xef, 0xa2, 0x33, 0xfd, 0x4d, 0x78, 0xa6, 0xd1, 0xb0, 0x6e, 0x8f, 0xce,
-	0x94, 0x90, 0xd7, 0xe7, 0x2d, 0xc0, 0x8e, 0x80, 0x1f, 0x25, 0x59, 0x69,
-	0x66, 0x3e, 0x05, 0x4f, 0xad, 0x85, 0x37, 0xe6, 0x06, 0x19, 0x46, 0x75,
-	0x0f, 0x78, 0x30, 0x91, 0x86, 0x1d, 0xde, 0xd7, 0x17, 0xdd, 0xe9, 0x1a,
-	0xb6, 0xae, 0x05, 0x75, 0x3c, 0xe7, 0x07, 0x60, 0x8b, 0x19, 0xd8, 0x27,
-	0x73, 0xa6, 0x12, 0x6b, 0x15, 0xda, 0x93, 0xe5, 0x1a, 0x59, 0x6b, 0x52,
-	0x86, 0x51, 0xef, 0xf0, 0xfc, 0x79, 0x59, 0x6e, 0x46, 0x34, 0xe4, 0x60,
-	0x8f, 0x63, 0xf8, 0x8d, 0xe0, 0x9d, 0x83, 0x1f, 0x6b, 0xa5, 0x82, 0x7c,
-	0x55, 0xe5, 0xe2, 0xc8, 0xb5, 0x87, 0x48, 0xdf, 0x01, 0xac, 0xa7, 0x3e,
-	0x53, 0x4f, 0x0f, 0x88, 0xdb, 0x4f, 0x5f, 0x91, 0x06, 0x6e, 0xc0, 0x78,
-	0xaf, 0xc1, 0xd6, 0x07, 0xf0, 0xcc, 0x5a, 0x65, 0xf2, 0x56, 0xe1, 0xf7,
-	0x7d, 0x23, 0xc7, 0x6f, 0x11, 0xe3, 0xe1, 0x78, 0xd0, 0xfa, 0x1d, 0xea,
-	0x5e, 0xfa, 0x5a, 0x39, 0xbb, 0x18, 0xc5, 0xc1, 0x19, 0xd8, 0x20, 0xef,
-	0x68, 0xc7, 0xc1, 0x17, 0x8e, 0xb5, 0x30, 0x1e, 0x62, 0x7e, 0xf9, 0xaf,
-	0x70, 0xee, 0xbc, 0x9c, 0x44, 0xfd, 0x2f, 0xfd, 0x7c, 0x66, 0x80, 0x7f,
-	0x4b, 0xa8, 0xef, 0xeb, 0xe1, 0x0d, 0x9b, 0xfd, 0x71, 0xd0, 0x67, 0xb6,
-	0xc0, 0x13, 0x26, 0xac, 0x4f, 0x04, 0xf1, 0x38, 0xed, 0xdf, 0xaa, 0xe7,
-	0xef, 0x96, 0x3f, 0x50, 0x67, 0xca, 0xcb, 0xa1, 0x45, 0xdf, 0x77, 0x73,
-	0x83, 0xc3, 0xcb, 0x92, 0x1d, 0x7e, 0x52, 0x76, 0x5b, 0x7b, 0x59, 0x8f,
-	0x59, 0xc4, 0xe3, 0xdf, 0xda, 0x96, 0xf7, 0xfd, 0x13, 0xa0, 0xfd, 0x07,
-	0x6a, 0x9f, 0xbb, 0x41, 0x3f, 0x78, 0xa5, 0x6a, 0x12, 0xd2, 0x0a, 0xde,
-	0xa4, 0x48, 0x6f, 0xa7, 0x1c, 0x6a, 0x3e, 0x1f, 0xca, 0xe6, 0x11, 0x71,
-	0xbd, 0xb7, 0x0d, 0xde, 0x6f, 0x97, 0x9b, 0x8f, 0x86, 0xb4, 0xe5, 0x41,
-	0x2f, 0xf6, 0x6f, 0xfe, 0x43, 0x8a, 0xbe, 0x81, 0x32, 0x77, 0x91, 0x35,
-	0xba, 0xa3, 0xcf, 0x40, 0x07, 0x3f, 0xce, 0x0f, 0x24, 0x65, 0xbd, 0x1f,
-	0x20, 0x5c, 0xf2, 0x23, 0x74, 0x85, 0x74, 0x88, 0xf2, 0x9f, 0x2a, 0x6e,
-	0x29, 0x7c, 0xc6, 0x06, 0x5f, 0xf0, 0xa4, 0x7a, 0x9e, 0x37, 0xe8, 0x9b,
-	0x18, 0xff, 0xa8, 0xc3, 0xdd, 0xf0, 0x7f, 0xd0, 0x41, 0xd8, 0x71, 0x71,
-	0x91, 0xf7, 0x13, 0x43, 0xea, 0x4e, 0xab, 0x04, 0xd9, 0x2e, 0xf1, 0x3b,
-	0x63, 0x2a, 0xc8, 0x27, 0x83, 0xfa, 0x2b, 0x43, 0x5f, 0x88, 0xf6, 0xb8,
-	0xf2, 0x93, 0x25, 0xf5, 0x5d, 0x31, 0x89, 0x35, 0x3e, 0x9e, 0xad, 0x7f,
-	0x27, 0xf1, 0xa3, 0x42, 0xf0, 0x77, 0x12, 0xe1, 0x37, 0xde, 0x7a, 0x90,
-	0x47, 0x3c, 0xd8, 0x30, 0x65, 0xaa, 0x11, 0xfd, 0xdd, 0x04, 0xe5, 0x60,
-	0x4b, 0xb9, 0x11, 0xe5, 0x0e, 0x7e, 0x50, 0xd3, 0xac, 0x93, 0xe5, 0xe3,
-	0x61, 0x4e, 0xc4, 0x1a, 0x80, 0x3c, 0xc4, 0x78, 0x39, 0x90, 0xdf, 0x92,
-	0xbe, 0x03, 0xf2, 0x03, 0xcf, 0x3d, 0x13, 0xb6, 0x94, 0x0e, 0xe3, 0xba,
-	0xc5, 0x1a, 0x33, 0xac, 0x7b, 0xb7, 0x4b, 0x75, 0x92, 0xef, 0x13, 0xf2,
-	0xda, 0xfc, 0x40, 0x70, 0x4f, 0x24, 0x89, 0xf0, 0x3d, 0xc7, 0x49, 0x29,
-	0xab, 0xf7, 0x77, 0x86, 0xf8, 0x50, 0xa7, 0xdd, 0x19, 0x8d, 0xd3, 0x90,
-	0x63, 0x00, 0x37, 0x8d, 0x58, 0xf6, 0x55, 0xc4, 0xb1, 0x69, 0xf0, 0xbd,
-	0x38, 0x51, 0x91, 0x6b, 0x6d, 0x4b, 0xc5, 0x7d, 0x37, 0x49, 0x1d, 0xa3,
-	0x7e, 0x11, 0xa6, 0x07, 0xb9, 0x2a, 0xce, 0x3b, 0x2a, 0x53, 0x46, 0xfe,
-	0xdd, 0xdb, 0xca, 0xb5, 0xac, 0x55, 0x90, 0xf7, 0x7d, 0xd7, 0xe4, 0xf8,
-	0xfc, 0x6d, 0x0f, 0x06, 0x77, 0xfe, 0xba, 0x9e, 0xbf, 0x78, 0x5b, 0x39,
-	0xe8, 0xe3, 0xcc, 0xef, 0x86, 0x7d, 0xc2, 0x19, 0xea, 0x7b, 0xec, 0x4f,
-	0x6e, 0x32, 0xe5, 0xc2, 0x4d, 0xbe, 0x7f, 0x0f, 0xbf, 0x09, 0x85, 0x75,
-	0xac, 0xa5, 0xea, 0xd8, 0x0e, 0x95, 0x8f, 0xb8, 0xa3, 0x19, 0xad, 0x04,
-	0xdb, 0x3d, 0xe9, 0xa1, 0xe6, 0xd1, 0xb3, 0x63, 0xe7, 0x75, 0x0b, 0xf1,
-	0x37, 0x9b, 0x39, 0x2e, 0xb9, 0x3e, 0x7e, 0x63, 0x9e, 0x73, 0xb8, 0x66,
-	0x5b, 0x70, 0xef, 0x75, 0x83, 0xab, 0x7c, 0xae, 0x48, 0x18, 0x87, 0x6e,
-	0x68, 0xb5, 0x8f, 0xd6, 0x3c, 0x93, 0x76, 0x21, 0x53, 0x26, 0xe8, 0xa9,
-	0xd6, 0xa2, 0x9c, 0x8d, 0x7f, 0x0f, 0x70, 0xfe, 0xb6, 0xa7, 0x1a, 0x17,
-	0x6f, 0x9b, 0x85, 0x7c, 0x78, 0xa6, 0xd9, 0x46, 0xa4, 0x7f, 0x51, 0xdd,
-	0xc0, 0x3e, 0xe2, 0xbf, 0x87, 0xf8, 0xef, 0x21, 0xfe, 0x7b, 0x88, 0xff,
-	0x1e, 0xe2, 0xbf, 0x87, 0xf8, 0x0f, 0x1e, 0x3e, 0x07, 0x7d, 0x79, 0xd6,
-	0x9b, 0x08, 0x73, 0xb6, 0xc7, 0x56, 0x73, 0x36, 0xfe, 0xcd, 0xcb, 0xb9,
-	0xa6, 0xa2, 0xa5, 0x52, 0x91, 0x20, 0xe7, 0x15, 0x9d, 0xf9, 0x4d, 0x94,
-	0xf3, 0x7e, 0xf4, 0xf7, 0x90, 0x00, 0x8e, 0xf9, 0x1e, 0xe1, 0x2a, 0x9a,
-	0x6e, 0x13, 0x2e, 0xc8, 0xf9, 0x58, 0x67, 0xad, 0x87, 0xe1, 0x77, 0x37,
-	0xfa, 0xb6, 0xe0, 0x9b, 0x4f, 0xf0, 0x7d, 0xa9, 0x76, 0x87, 0x8b, 0x58,
-	0x5c, 0x6e, 0xa8, 0x78, 0x8c, 0x71, 0xe3, 0x0e, 0xfe, 0xad, 0x02, 0x64,
-	0xc0, 0x77, 0x5f, 0x66, 0x6d, 0x51, 0x6e, 0x20, 0x2f, 0x5a, 0x8e, 0x72,
-	0x21, 0xc0, 0x79, 0x6f, 0x6a, 0xa5, 0x05, 0xca, 0x59, 0x97, 0xd9, 0x14,
-	0x98, 0x62, 0xb7, 0xe6, 0x78, 0x97, 0x54, 0xbd, 0x74, 0xb6, 0x49, 0x7a,
-	0x46, 0x40, 0x5b, 0x74, 0x8f, 0x2c, 0x62, 0xcc, 0xa7, 0x44, 0x9f, 0x47,
-	0x7e, 0x6b, 0x0f, 0xa9, 0xbf, 0x6f, 0xe8, 0xc5, 0x3e, 0xfa, 0xfc, 0x8e,
-	0x96, 0x7b, 0x5a, 0x29, 0x04, 0x3e, 0x9b, 0xb1, 0x87, 0xe7, 0x48, 0xc1,
-	0x76, 0xdd, 0x6d, 0x38, 0x1b, 0xe4, 0xfa, 0xaf, 0x5b, 0x55, 0x0e, 0x0e,
-	0x3f, 0x7a, 0x62, 0xa8, 0xbf, 0x5f, 0xba, 0xb7, 0xcb, 0xc9, 0x21, 0xd6,
-	0x6b, 0x9b, 0x81, 0x8f, 0x6b, 0x79, 0xff, 0xb4, 0x5d, 0x4e, 0x2d, 0xc2,
-	0xcf, 0x2e, 0x66, 0x1d, 0xea, 0xf2, 0xd2, 0x50, 0x0a, 0xfe, 0xf9, 0xe6,
-	0x7e, 0xc6, 0xe7, 0xe5, 0x26, 0x75, 0xa5, 0x17, 0xf0, 0x03, 0xd0, 0xcb,
-	0x4d, 0xb0, 0x27, 0x1d, 0xfb, 0x47, 0xb8, 0xff, 0x45, 0xe1, 0xee, 0xb5,
-	0x9d, 0x6d, 0x4a, 0x37, 0xf4, 0xac, 0x95, 0xd1, 0x41, 0xfb, 0xff, 0x14,
-	0x6e, 0x6d, 0x31, 0x71, 0x5c, 0x67, 0xf8, 0x3f, 0xb3, 0xdc, 0x8c, 0xd7,
-	0x30, 0x86, 0xf5, 0xb2, 0x58, 0xae, 0xba, 0x03, 0x63, 0x33, 0xd1, 0x62,
-	0x65, 0xb0, 0xec, 0x16, 0x55, 0x96, 0xba, 0xda, 0x05, 0x42, 0xe2, 0x3a,
-	0xdd, 0x24, 0xb4, 0x72, 0xd5, 0x2a, 0x42, 0x60, 0x37, 0x8e, 0xfa, 0xd2,
-	0x46, 0x55, 0xdb, 0x37, 0xaf, 0x16, 0xec, 0x38, 0xcd, 0xac, 0x17, 0x37,
-	0x38, 0xf4, 0x71, 0xb3, 0x2c, 0x0e, 0x90, 0x75, 0x56, 0x6e, 0xf2, 0x90,
-	0x3e, 0x19, 0x6d, 0xa2, 0x24, 0x55, 0xa5, 0xbc, 0x54, 0x7d, 0xab, 0x5a,
-	0x0b, 0x27, 0xc4, 0x0f, 0xa9, 0xad, 0xf6, 0xa5, 0x77, 0x4d, 0xbf, 0xef,
-	0xcc, 0x2c, 0xc6, 0xa4, 0x51, 0x91, 0x56, 0x73, 0xe6, 0xcc, 0xb9, 0x9f,
-	0xff, 0xf2, 0xfd, 0x17, 0x3e, 0x67, 0x67, 0xba, 0xc2, 0xbd, 0xcd, 0x95,
-	0x76, 0xc6, 0xfe, 0xb6, 0xd4, 0xcc, 0x02, 0xf3, 0x1a, 0x86, 0x64, 0xdc,
-	0x64, 0xae, 0xcf, 0x96, 0x3a, 0x57, 0x66, 0x1b, 0x1b, 0x65, 0xda, 0xe4,
-	0x4b, 0x6a, 0xa6, 0xdc, 0x23, 0x17, 0x41, 0xc7, 0x85, 0xe1, 0xd6, 0xd0,
-	0xf7, 0xda, 0x19, 0xf2, 0x73, 0x77, 0x3c, 0xd4, 0x57, 0x1a, 0x57, 0x16,
-	0x34, 0xb6, 0xee, 0xde, 0xf5, 0xed, 0x49, 0xac, 0x29, 0x41, 0x5f, 0x79,
-	0x5c, 0xcb, 0x26, 0x83, 0xef, 0x7d, 0xbb, 0xde, 0xe3, 0xbb, 0xde, 0x0f,
-	0xfc, 0x8f, 0xf6, 0x2c, 0xef, 0xa6, 0x07, 0xae, 0xd3, 0x1a, 0xe5, 0x2c,
-	0x05, 0xcf, 0x36, 0x66, 0x3d, 0x2b, 0x4d, 0x5c, 0x90, 0x15, 0x5f, 0x65,
-	0xdd, 0x36, 0xc8, 0xbb, 0x36, 0x99, 0x5f, 0x04, 0xcd, 0x63, 0x1f, 0xed,
-	0x36, 0x63, 0xe4, 0x43, 0x71, 0xf2, 0x4c, 0x07, 0xae, 0xc1, 0xb0, 0x07,
-	0x13, 0x68, 0xe7, 0x3f, 0xef, 0xa6, 0xcc, 0xb3, 0xda, 0x97, 0x43, 0x3c,
-	0xe3, 0xab, 0x82, 0xce, 0xf7, 0x60, 0x9b, 0x16, 0xb9, 0x63, 0x67, 0x7a,
-	0xc2, 0x7c, 0x20, 0xd8, 0xbe, 0x5f, 0x8d, 0x13, 0x6b, 0x3c, 0xe7, 0x6e,
-	0xd7, 0x99, 0x9b, 0xc2, 0x1c, 0x2b, 0x10, 0xcd, 0x53, 0x22, 0xe5, 0xaa,
-	0xc8, 0xeb, 0xf8, 0xfd, 0xa6, 0x1a, 0xc6, 0x4f, 0x14, 0xed, 0xee, 0x93,
-	0xb2, 0x5e, 0xfa, 0x9a, 0xd4, 0xa0, 0x7f, 0xd6, 0x5c, 0xdf, 0xbf, 0xeb,
-	0x26, 0xf5, 0x99, 0xbf, 0xe8, 0x29, 0x19, 0x18, 0xa1, 0x7e, 0x6b, 0x93,
-	0x97, 0x17, 0x5b, 0x64, 0xc3, 0xb4, 0xcc, 0xbb, 0x44, 0x01, 0x5e, 0x42,
-	0x26, 0x63, 0x11, 0x8d, 0x51, 0xe5, 0x5b, 0x22, 0x5b, 0xf8, 0xb6, 0xb5,
-	0xf8, 0x4c, 0x9c, 0xfe, 0x97, 0x4f, 0x16, 0xf9, 0x6e, 0xe0, 0x69, 0x48,
-	0xc3, 0x8e, 0x00, 0xcb, 0x42, 0x08, 0x99, 0x3c, 0x77, 0xee, 0xf7, 0xbb,
-	0x5c, 0x1b, 0xea, 0x68, 0xcf, 0xb6, 0x49, 0xe1, 0x30, 0x64, 0xa2, 0x1a,
-	0xd4, 0x39, 0x47, 0x8d, 0x98, 0x96, 0xd1, 0x91, 0x0a, 0x7d, 0xf8, 0xe6,
-	0x5e, 0x2d, 0xaf, 0x33, 0x37, 0x7e, 0xa4, 0xf7, 0x82, 0x72, 0xbe, 0xe2,
-	0x92, 0x56, 0x4d, 0x59, 0x03, 0xaf, 0xad, 0xd6, 0x5f, 0xed, 0xe3, 0x5d,
-	0xad, 0xd7, 0x5f, 0x88, 0x07, 0xf6, 0x1a, 0xeb, 0x7e, 0x1c, 0x0f, 0xea,
-	0x92, 0xa1, 0xfd, 0x45, 0x3b, 0xad, 0x8c, 0xbd, 0xbd, 0x20, 0xf5, 0xa5,
-	0x9f, 0xc9, 0x3b, 0xa5, 0x9f, 0xc8, 0xaf, 0x97, 0xce, 0x00, 0x7f, 0x58,
-	0xe5, 0x3c, 0xf4, 0xc9, 0xcd, 0xba, 0xef, 0xdf, 0x74, 0xa7, 0x60, 0x2b,
-	0xf8, 0xfe, 0xef, 0xdc, 0x0d, 0x19, 0x38, 0xf6, 0x3d, 0xec, 0x39, 0x07,
-	0x1e, 0xa2, 0x2c, 0x9c, 0x04, 0xbd, 0xb9, 0x7d, 0xd2, 0x19, 0xd5, 0x74,
-	0x32, 0x78, 0xac, 0x15, 0x7b, 0x30, 0x42, 0x4c, 0xce, 0xbd, 0x8c, 0xf4,
-	0x91, 0x66, 0x8c, 0x7a, 0x09, 0xf3, 0xb7, 0x82, 0x2f, 0xf6, 0xe2, 0xa7,
-	0xe4, 0xee, 0x08, 0xd6, 0x3a, 0x42, 0xda, 0x6b, 0x95, 0x81, 0x47, 0xb1,
-	0x8f, 0x5c, 0x8b, 0xdc, 0xf3, 0x7e, 0x19, 0xa7, 0x6f, 0xef, 0x9e, 0xc7,
-	0xb2, 0xf1, 0x95, 0x2e, 0xf1, 0xa5, 0x05, 0xba, 0x7c, 0xfe, 0x78, 0x80,
-	0x9b, 0xde, 0x55, 0x43, 0x68, 0x6f, 0xe7, 0xdf, 0x53, 0xc4, 0x79, 0x79,
-	0xbf, 0x15, 0xb8, 0x7c, 0x1c, 0x78, 0x28, 0x53, 0xbf, 0x20, 0x8d, 0x91,
-	0x28, 0xda, 0x10, 0xaf, 0x68, 0x59, 0x22, 0x59, 0x8f, 0x39, 0x5a, 0xcc,
-	0x97, 0xc2, 0x1a, 0xa7, 0x74, 0x2e, 0x57, 0x1f, 0xcf, 0x9c, 0x58, 0x3e,
-	0xa8, 0xb3, 0x41, 0x23, 0xac, 0x23, 0x7d, 0xa7, 0x35, 0xa6, 0x82, 0x0e,
-	0xc5, 0x78, 0xc3, 0x92, 0xd1, 0xe5, 0x2e, 0x8c, 0x77, 0x41, 0x32, 0x6e,
-	0x73, 0xcc, 0x51, 0xb4, 0xa1, 0x9c, 0x19, 0x05, 0x96, 0xf8, 0x58, 0x8d,
-	0x2d, 0xc6, 0xa0, 0xcb, 0xe3, 0x32, 0x66, 0xee, 0xd9, 0xb1, 0xc7, 0xbc,
-	0xb6, 0x15, 0x0c, 0x63, 0x38, 0x5c, 0x53, 0xd7, 0x8e, 0x35, 0xb1, 0x3f,
-	0x7e, 0xb0, 0x93, 0x33, 0x8b, 0x0b, 0x90, 0x53, 0x0b, 0x1f, 0x66, 0xdc,
-	0x67, 0x25, 0x1b, 0x6b, 0xd3, 0xb6, 0x4d, 0x05, 0xf7, 0x92, 0xf5, 0xe8,
-	0xd3, 0xfa, 0x0e, 0xe4, 0xd0, 0x9e, 0xb0, 0x8e, 0x6d, 0xc5, 0xc8, 0xe0,
-	0xec, 0x03, 0x1b, 0x97, 0x75, 0x5f, 0x96, 0xcc, 0x42, 0x4e, 0x26, 0x74,
-	0x3f, 0x9e, 0xe1, 0x41, 0x8d, 0x43, 0xc8, 0xab, 0x03, 0xbd, 0x38, 0xcb,
-	0xd4, 0x03, 0x7b, 0x38, 0xd9, 0x4b, 0x2e, 0xfa, 0x4f, 0xc8, 0xb3, 0xf8,
-	0xd6, 0xcb, 0x3b, 0x6a, 0x93, 0x81, 0x67, 0xa0, 0x2f, 0xbd, 0x66, 0x7d,
-	0x54, 0x3e, 0xf3, 0xfc, 0x38, 0x63, 0x2e, 0x7f, 0xf6, 0x4c, 0xf9, 0xc4,
-	0xd3, 0xb1, 0xd8, 0xe9, 0x88, 0x58, 0xe7, 0x03, 0x5b, 0xfd, 0xf0, 0xf4,
-	0xbc, 0xe2, 0xf7, 0xc3, 0xe7, 0x57, 0x54, 0x07, 0xda, 0x46, 0xd1, 0x8e,
-	0xeb, 0x30, 0x65, 0xdc, 0xfb, 0xab, 0x3f, 0x73, 0xc4, 0xf7, 0x27, 0x74,
-	0x4e, 0x58, 0xca, 0x9c, 0x57, 0x4d, 0x7c, 0xee, 0x88, 0x17, 0x6b, 0xc7,
-	0x5c, 0x29, 0x73, 0x45, 0x1d, 0xc6, 0x7a, 0x58, 0xee, 0x25, 0x4f, 0x24,
-	0x36, 0x84, 0xe3, 0x5b, 0x93, 0xcb, 0x2a, 0x95, 0x1c, 0x54, 0x56, 0xba,
-	0x80, 0x5f, 0x8b, 0xd2, 0x71, 0xcc, 0x44, 0x52, 0x81, 0x77, 0xb1, 0x27,
-	0xfb, 0xa8, 0xef, 0x4f, 0xda, 0xac, 0x4f, 0x99, 0x51, 0x45, 0xdf, 0x4b,
-	0xa7, 0x8e, 0x77, 0x5e, 0x3e, 0x90, 0x32, 0x8f, 0xaa, 0xfd, 0xe1, 0xfb,
-	0x28, 0x64, 0xe6, 0xf6, 0x78, 0x67, 0x96, 0x95, 0x29, 0x2f, 0x79, 0xa9,
-	0xe4, 0xac, 0xb2, 0x72, 0x18, 0x33, 0x37, 0xa6, 0x28, 0x37, 0x52, 0x66,
-	0xa7, 0xa2, 0x7f, 0xb4, 0x5d, 0xef, 0x7b, 0x12, 0xfd, 0x53, 0xaa, 0x25,
-	0x5c, 0x0f, 0xef, 0xeb, 0x4a, 0x5f, 0xc0, 0x33, 0x94, 0x39, 0xfd, 0xc6,
-	0xcc, 0x02, 0xf3, 0xcb, 0x74, 0x5e, 0x43, 0x7a, 0xe0, 0x18, 0xdf, 0x0d,
-	0xb9, 0x7f, 0xe2, 0x6f, 0xa8, 0x43, 0xb9, 0xcc, 0x3a, 0x27, 0xe4, 0xb7,
-	0x23, 0x1a, 0x3f, 0xdf, 0x3f, 0x91, 0xd7, 0xb9, 0x8b, 0x0d, 0x35, 0x10,
-	0xee, 0x7b, 0xfb, 0xce, 0x92, 0x19, 0xf7, 0x4b, 0x1c, 0x67, 0x21, 0x72,
-	0xb2, 0x5d, 0x98, 0x23, 0x3a, 0x5e, 0x6a, 0xd2, 0x06, 0x7d, 0x03, 0xcc,
-	0x15, 0x68, 0xc6, 0xdd, 0x2f, 0x88, 0x71, 0xac, 0x63, 0x07, 0x9d, 0x00,
-	0x77, 0x02, 0xaf, 0x56, 0x31, 0x4e, 0x61, 0x51, 0xf2, 0x41, 0x7f, 0xe9,
-	0x60, 0x4e, 0x6a, 0xa1, 0xfa, 0x45, 0x63, 0x04, 0x3a, 0x70, 0x1c, 0xef,
-	0xf7, 0x4f, 0x90, 0x3e, 0x79, 0x36, 0x49, 0x35, 0xbe, 0xc4, 0xf5, 0x1c,
-	0x94, 0x89, 0x45, 0x60, 0x23, 0xfc, 0xe6, 0x17, 0x83, 0x7b, 0xbb, 0x0e,
-	0x9c, 0x3d, 0xe1, 0x99, 0x9a, 0x5f, 0x67, 0x5d, 0xc6, 0x4f, 0xc0, 0x2b,
-	0x3a, 0x8f, 0x8a, 0x7d, 0x99, 0x4b, 0x78, 0x88, 0xfa, 0xd1, 0x6d, 0x48,
-	0x0c, 0x6d, 0x89, 0x59, 0x59, 0x6f, 0x8d, 0x26, 0x23, 0xdd, 0x32, 0x0f,
-	0x79, 0x57, 0x81, 0xee, 0x2c, 0x5c, 0x89, 0xca, 0xac, 0xa7, 0xe3, 0xd9,
-	0xc9, 0x8f, 0x95, 0x2b, 0xb5, 0xfa, 0x71, 0xb9, 0x51, 0x77, 0xf4, 0x37,
-	0xea, 0xb5, 0xc2, 0xab, 0x86, 0x7c, 0xff, 0x88, 0xce, 0xa5, 0x73, 0x2a,
-	0xd2, 0xd9, 0x4f, 0xcc, 0xb3, 0xa2, 0xf3, 0xea, 0x20, 0x3b, 0x80, 0x39,
-	0xde, 0x06, 0xe6, 0x78, 0x0b, 0x98, 0xe3, 0x57, 0xc0, 0xd8, 0x37, 0x4b,
-	0x93, 0xa1, 0xfc, 0x9f, 0x86, 0x1c, 0xa2, 0xae, 0xb6, 0xce, 0xe0, 0x4e,
-	0xa7, 0xf3, 0xa0, 0xc1, 0xdb, 0xb0, 0x3f, 0xd6, 0x4b, 0x19, 0x59, 0x5d,
-	0x9a, 0x90, 0xb5, 0xa5, 0x20, 0x0f, 0xf9, 0x03, 0xe6, 0x7d, 0x8d, 0xf0,
-	0x9e, 0x1c, 0xc8, 0xa1, 0x3d, 0x32, 0x70, 0x94, 0xf2, 0xa3, 0x43, 0x96,
-	0x8b, 0xab, 0x5a, 0x0e, 0x2d, 0x17, 0x59, 0x8e, 0x88, 0xce, 0x21, 0x9b,
-	0xda, 0x90, 0x8a, 0x5b, 0x47, 0xfd, 0x3e, 0xed, 0x0f, 0x0a, 0xfc, 0xf3,
-	0x94, 0x97, 0x7f, 0x0a, 0xef, 0x5e, 0xe9, 0xdc, 0xba, 0x19, 0xb3, 0x1b,
-	0xed, 0x9a, 0xb2, 0x6b, 0x30, 0x88, 0xb9, 0xab, 0xdb, 0x68, 0x83, 0x39,
-	0x80, 0x19, 0xaf, 0x43, 0x87, 0x34, 0x9c, 0x6e, 0x8d, 0xfd, 0x1a, 0xce,
-	0x21, 0x9d, 0x77, 0xcb, 0x71, 0x0a, 0x45, 0x5b, 0xe6, 0x8a, 0x56, 0x32,
-	0x0f, 0xfa, 0xbb, 0x01, 0xbb, 0x6d, 0x15, 0x77, 0xb0, 0x86, 0x33, 0x58,
-	0xaf, 0x53, 0xcf, 0x6f, 0x6a, 0xd9, 0xbb, 0x5c, 0xff, 0x23, 0xc6, 0xb1,
-	0xce, 0xa4, 0xe5, 0x0f, 0x7d, 0x94, 0x81, 0xf4, 0x4d, 0x65, 0x75, 0xff,
-	0xa0, 0xdf, 0x2a, 0xda, 0xae, 0xd5, 0x29, 0x8f, 0x45, 0x2e, 0x79, 0x36,
-	0x74, 0xc9, 0xcb, 0x09, 0x62, 0x80, 0xb2, 0x6a, 0xf6, 0xf3, 0xc3, 0x35,
-	0xfb, 0xfe, 0x5e, 0x9b, 0xeb, 0x72, 0x42, 0xb9, 0x4d, 0xdd, 0xbf, 0xa1,
-	0xb1, 0x8d, 0x57, 0x7a, 0x56, 0xde, 0xc4, 0x7d, 0x07, 0x18, 0x27, 0x27,
-	0x6f, 0x00, 0xe3, 0xd5, 0x4b, 0xcd, 0xbc, 0xed, 0x93, 0x38, 0xa7, 0x92,
-	0x9a, 0xbb, 0xda, 0x29, 0x97, 0xaf, 0x15, 0xd4, 0x4b, 0xd7, 0x3c, 0xf5,
-	0xf3, 0xab, 0x45, 0x55, 0xb8, 0xea, 0xfb, 0xff, 0x70, 0x67, 0xe4, 0x9d,
-	0x25, 0x5f, 0x4e, 0xbb, 0x46, 0x7f, 0x44, 0x9a, 0xf9, 0x74, 0xbe, 0xdf,
-	0x01, 0xd9, 0xbc, 0x7e, 0xc0, 0xf7, 0x1f, 0x19, 0x19, 0x11, 0xe7, 0x00,
-	0x31, 0xca, 0x70, 0x82, 0x39, 0xae, 0x94, 0x39, 0x19, 0xdb, 0x3e, 0x5f,
-	0x51, 0x0a, 0xf2, 0xad, 0x3b, 0xc0, 0x2f, 0x8f, 0xee, 0x0b, 0xe3, 0x26,
-	0x3f, 0x7c, 0x9e, 0x7e, 0xe5, 0xc4, 0xe7, 0xfc, 0xca, 0xa6, 0x9c, 0x2d,
-	0xf6, 0xa2, 0x7f, 0x4c, 0x7e, 0x50, 0x8c, 0xee, 0x2a, 0x9b, 0x78, 0x3a,
-	0x46, 0xa1, 0x78, 0xcf, 0x1f, 0xd4, 0xf1, 0x03, 0x60, 0x12, 0xd3, 0xf7,
-	0x67, 0x5d, 0xce, 0xd7, 0x8d, 0xf9, 0x36, 0xcc, 0x7d, 0xd0, 0xff, 0xa7,
-	0xb5, 0x7e, 0x2e, 0x2b, 0xd8, 0xc1, 0xe0, 0xef, 0x98, 0x8c, 0x15, 0xa1,
-	0xe3, 0x15, 0xf3, 0x4c, 0x89, 0x15, 0xac, 0xc4, 0x2c, 0x64, 0xc7, 0x0c,
-	0xe4, 0xcd, 0x29, 0x1d, 0x67, 0xed, 0xd5, 0xb2, 0x67, 0x8e, 0xe5, 0x9c,
-	0xa4, 0x2b, 0x6e, 0x8f, 0x3e, 0xbf, 0xcd, 0x1b, 0x2f, 0x26, 0x82, 0x3b,
-	0x07, 0x1f, 0xe7, 0x94, 0xb4, 0xc1, 0x1e, 0xca, 0xae, 0x4c, 0x81, 0x27,
-	0x12, 0x38, 0xdb, 0x56, 0xcd, 0x0f, 0x0d, 0xe8, 0xef, 0x86, 0xf6, 0x29,
-	0x06, 0xb1, 0x8b, 0x86, 0xc9, 0x76, 0xa7, 0xd0, 0xaf, 0x5d, 0x32, 0x57,
-	0xdb, 0xb4, 0x5c, 0x7d, 0xb8, 0x2e, 0x0d, 0x1c, 0xf2, 0x04, 0xca, 0x11,
-	0xd4, 0x25, 0xc3, 0xb2, 0x81, 0xf2, 0x34, 0xca, 0x2d, 0x78, 0xb2, 0xcd,
-	0x61, 0xe0, 0x0a, 0x3c, 0x5f, 0xc3, 0x78, 0x23, 0x58, 0x73, 0xce, 0x94,
-	0x8f, 0x4e, 0x50, 0x97, 0x38, 0x06, 0x73, 0x91, 0x67, 0x6d, 0x3c, 0x6b,
-	0x45, 0x95, 0x5d, 0x60, 0x19, 0xcf, 0x72, 0xf0, 0xfd, 0x21, 0x99, 0x84,
-	0x3e, 0x99, 0x6b, 0x81, 0x4c, 0xfa, 0x68, 0x5b, 0x26, 0xb1, 0xae, 0x5d,
-	0xc6, 0xae, 0x92, 0xd7, 0x4d, 0xd0, 0x5b, 0xa7, 0x64, 0xaf, 0xc5, 0x34,
-	0x1e, 0xad, 0x80, 0x16, 0xaf, 0x83, 0xae, 0x96, 0x41, 0x53, 0x99, 0xa2,
-	0x35, 0x3a, 0xad, 0x92, 0xda, 0x2f, 0xf0, 0x38, 0xe8, 0xb5, 0xe3, 0x0a,
-	0xb1, 0x28, 0x79, 0xd9, 0x01, 0xed, 0x89, 0xdf, 0x61, 0xdb, 0x93, 0x8e,
-	0xb2, 0x41, 0x83, 0xa0, 0xcb, 0x62, 0xc0, 0xd3, 0xef, 0x29, 0x2d, 0x57,
-	0x47, 0xef, 0x48, 0x2a, 0x7d, 0x47, 0x2c, 0xc8, 0x02, 0xcb, 0xfd, 0x50,
-	0x5c, 0x8c, 0x79, 0x5c, 0x5e, 0xc7, 0x3c, 0x06, 0xf8, 0xfb, 0xc8, 0x90,
-	0xe6, 0xef, 0x51, 0x89, 0xec, 0xe6, 0x71, 0xd0, 0x1b, 0x64, 0x50, 0xc0,
-	0xd3, 0xe9, 0x90, 0x46, 0x9f, 0x06, 0xff, 0x5a, 0xb0, 0xca, 0x92, 0x32,
-	0x0f, 0xfe, 0xbf, 0x8e, 0xef, 0xb7, 0xea, 0x9f, 0xaa, 0xb9, 0x05, 0x15,
-	0xe6, 0xb2, 0x7c, 0x1b, 0x38, 0xf9, 0xf7, 0x38, 0xbb, 0x2e, 0x8d, 0xdd,
-	0x07, 0x46, 0x18, 0x4b, 0xfb, 0xb7, 0xba, 0x6c, 0x1f, 0x95, 0xcd, 0xe1,
-	0xe3, 0x28, 0xef, 0xc3, 0xd3, 0xc0, 0x39, 0x44, 0x75, 0x2c, 0x7c, 0xd9,
-	0x1b, 0x36, 0x0a, 0x3a, 0xef, 0xe0, 0x98, 0xce, 0xcf, 0x37, 0xec, 0x03,
-	0xf8, 0x4e, 0xbf, 0x0c, 0xf7, 0x06, 0xcc, 0xa4, 0x12, 0x3a, 0xc7, 0xb4,
-	0x02, 0x2c, 0xb1, 0x82, 0xf1, 0xde, 0xa7, 0x5f, 0xaf, 0x06, 0x1e, 0x1e,
-	0xfe, 0xa7, 0x9f, 0x8e, 0x31, 0x27, 0x7d, 0x33, 0x11, 0xe8, 0xbf, 0xcf,
-	0xfc, 0x4d, 0x7b, 0x6e, 0xd4, 0xc0, 0xcb, 0x6d, 0x33, 0x86, 0xb6, 0xd0,
-	0x65, 0xd0, 0x45, 0x65, 0x4d, 0xbf, 0x6c, 0x17, 0xf4, 0x2d, 0xd4, 0x52,
-	0xe6, 0x07, 0x12, 0xf4, 0x9d, 0xb7, 0xa9, 0x77, 0xda, 0x21, 0x5f, 0x92,
-	0x1a, 0x57, 0xbe, 0x6f, 0xe7, 0x21, 0x15, 0xac, 0xe4, 0x24, 0x68, 0xb4,
-	0x4d, 0x2c, 0x67, 0x5c, 0x1e, 0xcc, 0x3b, 0xab, 0xfb, 0xb2, 0x6d, 0xb3,
-	0x6f, 0x73, 0x5e, 0xae, 0x9f, 0x7b, 0xe1, 0x1e, 0xe8, 0xa7, 0x36, 0x35,
-	0x8d, 0x36, 0x6a, 0xed, 0xfd, 0x01, 0x8d, 0x36, 0xf7, 0x11, 0xfb, 0x3f,
-	0xfb, 0x20, 0x9d, 0x0c, 0x1b, 0x41, 0x0e, 0x06, 0x9e, 0x35, 0x9e, 0xe7,
-	0xa7, 0xc0, 0xf7, 0x3b, 0xe9, 0xa7, 0xe9, 0x67, 0x0c, 0xe8, 0xe7, 0x91,
-	0x6d, 0xfa, 0x21, 0xdd, 0x74, 0xca, 0xd8, 0x35, 0x5b, 0x26, 0x8a, 0xfa,
-	0xbe, 0x81, 0x35, 0xe9, 0x3f, 0x3a, 0x0e, 0xba, 0x21, 0xad, 0x93, 0xb7,
-	0x4c, 0x29, 0x83, 0x8e, 0xca, 0x90, 0x4f, 0x65, 0xd0, 0x14, 0x31, 0x50,
-	0x19, 0xf2, 0xad, 0x5c, 0xb7, 0x9c, 0x2a, 0xf6, 0x4c, 0x9d, 0xbd, 0x02,
-	0x3a, 0xba, 0x5e, 0xe7, 0xfd, 0xeb, 0x35, 0x9b, 0xd4, 0x83, 0xb7, 0xb6,
-	0xef, 0xfe, 0xef, 0xb8, 0xfb, 0x43, 0x72, 0x03, 0x76, 0xcb, 0x9b, 0xa5,
-	0x61, 0xc8, 0x24, 0x21, 0x5e, 0x04, 0x6d, 0x8c, 0xca, 0x6a, 0xe9, 0xa4,
-	0xac, 0x41, 0x3f, 0xad, 0x2f, 0x0d, 0x00, 0x4f, 0x43, 0x8e, 0xbe, 0x72,
-	0x44, 0xde, 0x58, 0x52, 0x32, 0x63, 0x43, 0xbf, 0x2c, 0xd3, 0x07, 0x0f,
-	0x7a, 0x2e, 0x77, 0xea, 0x98, 0xfd, 0x58, 0x35, 0xf0, 0xc5, 0x8f, 0x57,
-	0xbb, 0x64, 0xa2, 0x6a, 0xca, 0x63, 0xd5, 0x1e, 0x79, 0xa2, 0x1a, 0x93,
-	0xd3, 0xb5, 0x84, 0x7c, 0xa3, 0x7a, 0x50, 0x4e, 0x55, 0x0f, 0xc9, 0x93,
-	0xb5, 0xa4, 0x7c, 0x13, 0x76, 0x61, 0xae, 0xe6, 0xc8, 0x64, 0x6d, 0x58,
-	0x1e, 0xaf, 0xd1, 0xc7, 0x8e, 0xf9, 0xf0, 0xcb, 0x6e, 0xfb, 0x2e, 0xb8,
-	0xae, 0x0e, 0xac, 0xcb, 0x51, 0xe3, 0x3a, 0x66, 0x29, 0xb9, 0xc0, 0xff,
-	0x21, 0x72, 0x0e, 0x7d, 0x2f, 0xbe, 0xa2, 0xa4, 0xa2, 0xe7, 0x6f, 0xfe,
-	0xdf, 0x48, 0x54, 0xdb, 0x46, 0xe7, 0xca, 0x07, 0xd1, 0xc6, 0xa6, 0x4d,
-	0x12, 0xfa, 0x41, 0x9a, 0xfe, 0xff, 0xa6, 0xed, 0x65, 0x68, 0x1f, 0xf6,
-	0x2d, 0xda, 0x5e, 0xfa, 0xec, 0x29, 0x3f, 0x68, 0xe7, 0xd0, 0xd6, 0xda,
-	0x19, 0xe7, 0x68, 0xce, 0x7b, 0x31, 0xf7, 0xf0, 0xff, 0xa7, 0x04, 0xf1,
-	0xaa, 0xb3, 0xb5, 0x83, 0xfc, 0x3f, 0x15, 0xac, 0xe5, 0x8b, 0xf3, 0xc5,
-	0x27, 0x4a, 0x63, 0xea, 0xb1, 0x12, 0x11, 0x8d, 0x2f, 0x17, 0xb7, 0x73,
-	0xf2, 0xbe, 0x2e, 0xcb, 0x6e, 0x54, 0xaf, 0x21, 0xf0, 0xdb, 0xa7, 0x75,
-	0x7e, 0xde, 0xd8, 0x10, 0xe9, 0x8f, 0x71, 0xb8, 0xae, 0x30, 0xb6, 0x00,
-	0x6c, 0xeb, 0x9a, 0x72, 0xa9, 0x1a, 0xf8, 0xaf, 0xe6, 0x34, 0xbd, 0xbc,
-	0x05, 0x9a, 0x63, 0xfc, 0x21, 0x78, 0xe6, 0xcb, 0x41, 0xdf, 0xec, 0x90,
-	0x43, 0x7b, 0x1c, 0xfb, 0x35, 0x7a, 0x38, 0x17, 0xff, 0x4f, 0x07, 0xe5,
-	0x70, 0xbd, 0xcc, 0x2f, 0xb6, 0x35, 0x2d, 0x06, 0x31, 0x5e, 0x47, 0x9e,
-	0xc3, 0x5d, 0x54, 0x4c, 0xae, 0xbf, 0x43, 0x2a, 0x0e, 0x6d, 0x5b, 0xca,
-	0xef, 0x21, 0x29, 0x63, 0x9e, 0x8a, 0xd3, 0xf4, 0x8d, 0x05, 0x72, 0xb6,
-	0x62, 0x3e, 0x98, 0x77, 0xba, 0xbc, 0x1f, 0xef, 0xa8, 0x73, 0x80, 0x99,
-	0xa6, 0xf8, 0x7e, 0x11, 0x65, 0xfa, 0x46, 0xe6, 0xf0, 0x4c, 0x84, 0x75,
-	0xaf, 0xf5, 0x6b, 0xac, 0x7e, 0xf2, 0x41, 0xbf, 0x99, 0xb2, 0x95, 0xcf,
-	0x44, 0xb6, 0x94, 0xf1, 0x8b, 0xf5, 0x7e, 0xca, 0xdc, 0xfd, 0x36, 0x7f,
-	0x51, 0xf9, 0x8b, 0xa9, 0x7d, 0x0a, 0xe1, 0xb7, 0x3d, 0xf2, 0x94, 0xc9,
-	0xdc, 0xf5, 0xb4, 0x1a, 0x2b, 0xfd, 0x34, 0xcc, 0xd3, 0xdd, 0x52, 0xfb,
-	0x2b, 0x6f, 0xf7, 0x07, 0x79, 0xee, 0x1c, 0x7b, 0x67, 0x6e, 0xfb, 0x4e,
-	0x3a, 0x61, 0x8e, 0x7b, 0x3b, 0x70, 0xab, 0x56, 0x62, 0xe0, 0x41, 0xc8,
-	0x3b, 0xbb, 0x45, 0xf3, 0x63, 0xa1, 0xf6, 0x2f, 0x7f, 0x43, 0xf3, 0x73,
-	0xd3, 0xc7, 0xf0, 0xdb, 0x7e, 0xda, 0xb6, 0x94, 0x1b, 0x97, 0x02, 0xbf,
-	0x91, 0xb6, 0xa1, 0x21, 0x2b, 0x50, 0x47, 0x5e, 0x05, 0x9f, 0x6c, 0xb7,
-	0xe5, 0xdf, 0x7f, 0x01, 0x99, 0xe7, 0xd3, 0x46, 0x40, 0x67, 0x00, 0x00,
-	0x00 };
-static u32 bnx2_RXP_b09FwData[(0x0/4) + 1] = { 0x0 };
-static u32 bnx2_RXP_b09FwRodata[(0x278/4) + 1] = {
-	0x08003fa4, 0x08003ea4, 0x08003f48, 0x08003f60, 0x08003f78, 0x08003f98,
-	0x08003fa4, 0x08003fa4, 0x08003eac, 0x00000000, 0x080049d4, 0x08004a0c,
-	0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004a44, 0x08004c08,
-	0x08004b50, 0x08004b88, 0x08004c08, 0x08004ad8, 0x08004c08, 0x08004c08,
-	0x08004b88, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08,
-	0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004bc8,
-	0x08004c08, 0x08004bc8, 0x08004b50, 0x08004c08, 0x08004c08, 0x08004bc8,
-	0x08004bc8, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08,
-	0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08,
-	0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08,
-	0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08,
-	0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08,
-	0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08,
-	0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08,
-	0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08,
-	0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08,
-	0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08,
-	0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08,
-	0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08,
-	0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08,
-	0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08,
-	0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08,
-	0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08,
-	0x08004ab4, 0x00000000, 0x0800602c, 0x08006044, 0x08006044, 0x08006044,
-	0x0800602c, 0x08006044, 0x08006044, 0x08006044, 0x0800602c, 0x08006044,
-	0x08006044, 0x08006044, 0x0800602c, 0x08006044, 0x08006044, 0x08006044,
-	0x08006038, 0x00000000, 0x00000000 };
-static u32 bnx2_RXP_b09FwBss[(0x13dc/4) + 1] = { 0x0 };
-static u32 bnx2_RXP_b09FwSbss[(0x2c/4) + 1] = { 0x0 };
+	0x1f, 0x8b, 0x08, 0x00, 0x0e, 0x34, 0xe7, 0x45, 0x00, 0x03, 0xec, 0x5c,
+	0x5d, 0x6c, 0x1c, 0xd7, 0x75, 0x3e, 0xf3, 0x43, 0x6a, 0x49, 0xf1, 0x67,
+	0xb8, 0x5c, 0xb1, 0x2b, 0x99, 0x96, 0x77, 0xc9, 0x91, 0xc8, 0x58, 0x8a,
+	0x31, 0xa2, 0x09, 0x5b, 0x48, 0x17, 0xf6, 0x76, 0x76, 0x25, 0xb1, 0xb1,
+	0x03, 0x53, 0xb6, 0x62, 0x07, 0x45, 0x6a, 0xb0, 0x4b, 0xb9, 0x0e, 0x8c,
+	0x06, 0x90, 0xff, 0x52, 0xbf, 0xb0, 0xde, 0x2c, 0xa9, 0x58, 0x4d, 0x17,
+	0x9c, 0xb5, 0x4d, 0x9b, 0x0e, 0x60, 0xb7, 0x0b, 0x92, 0x12, 0xf5, 0xb0,
+	0xd0, 0xb2, 0xa9, 0xdb, 0xea, 0xc1, 0x8e, 0x09, 0x56, 0xb1, 0x53, 0xa0,
+	0x2d, 0x5c, 0x27, 0x69, 0xfc, 0x10, 0x14, 0xaa, 0xec, 0xc4, 0x42, 0xd1,
+	0xa2, 0x02, 0x12, 0xd8, 0x29, 0x22, 0x7b, 0xfa, 0x7d, 0x77, 0x66, 0xc8,
+	0x25, 0x2d, 0xdb, 0x41, 0x1f, 0xfa, 0xd2, 0xbd, 0xc0, 0x62, 0xee, 0xbd,
+	0x73, 0xee, 0xb9, 0xe7, 0x9e, 0xff, 0x73, 0x87, 0xd2, 0x1f, 0x74, 0x48,
+	0xbb, 0x84, 0xad, 0x13, 0xbf, 0xd4, 0x89, 0x27, 0x1e, 0xb9, 0x69, 0xf4,
+	0xa6, 0x9b, 0xd1, 0xbd, 0xd9, 0x30, 0x4c, 0x23, 0x9a, 0x6f, 0xb6, 0x66,
+	0x6b, 0xb6, 0x66, 0x6b, 0xb6, 0x66, 0x6b, 0xb6, 0x66, 0x6b, 0xb6, 0x66,
+	0x6b, 0xb6, 0x66, 0x6b, 0xb6, 0x66, 0x6b, 0xb6, 0x66, 0x6b, 0xb6, 0x66,
+	0x6b, 0xb6, 0x66, 0x6b, 0xb6, 0x66, 0x6b, 0xb6, 0x66, 0x6b, 0xb6, 0x66,
+	0x6b, 0xb6, 0x66, 0x6b, 0xb6, 0x66, 0x6b, 0xb6, 0x66, 0x6b, 0xb6, 0x66,
+	0x6b, 0xb6, 0x66, 0x6b, 0xb6, 0x66, 0x6b, 0xb6, 0x66, 0x6b, 0xb6, 0x66,
+	0x6b, 0xb6, 0x66, 0x6b, 0xb6, 0x66, 0x6b, 0xb6, 0x66, 0xfb, 0xff, 0xde,
+	0x0c, 0x11, 0x8b, 0xcf, 0xce, 0xf0, 0x27, 0x31, 0x3d, 0x23, 0x0f, 0xb9,
+	0xb6, 0xc4, 0x8c, 0xcc, 0xd5, 0xa9, 0x49, 0x5b, 0x24, 0x5b, 0xdb, 0x97,
+	0xca, 0xc9, 0x87, 0x7e, 0x31, 0x61, 0x0a, 0xe7, 0xaf, 0xcf, 0x5c, 0xfd,
+	0x8b, 0x57, 0x6f, 0x4d, 0x5f, 0xa9, 0x1a, 0x12, 0xb3, 0x32, 0x33, 0x07,
+	0xac, 0xbd, 0x12, 0xeb, 0xc7, 0x9a, 0x17, 0x87, 0xfe, 0xa9, 0x4b, 0xba,
+	0x22, 0x5c, 0x22, 0x0b, 0xe5, 0xb4, 0x73, 0x18, 0xcf, 0x33, 0xb5, 0x7d,
+	0xce, 0x9a, 0x98, 0xb2, 0x6a, 0x05, 0x3b, 0x96, 0xca, 0x1a, 0xf1, 0x48,
+	0xa9, 0x16, 0x93, 0x8b, 0xea, 0xdf, 0x79, 0x60, 0x4f, 0x9b, 0xfd, 0xf3,
+	0x9a, 0x5b, 0xf7, 0xfd, 0xd3, 0x8e, 0xef, 0xbf, 0x8e, 0xdf, 0x7b, 0x0e,
+	0xc6, 0xde, 0x47, 0x7e, 0xd6, 0x34, 0x44, 0xb7, 0xff, 0x4c, 0x73, 0x17,
+	0x5b, 0xa5, 0x34, 0x2f, 0x32, 0xed, 0xc5, 0xe4, 0x94, 0x57, 0xd4, 0xf2,
+	0xf5, 0xb2, 0x76, 0x68, 0x79, 0x56, 0x3b, 0xbc, 0x7c, 0x4a, 0x3b, 0xb2,
+	0x5c, 0xd1, 0xdc, 0x65, 0x29, 0xea, 0x07, 0x3a, 0x24, 0x6b, 0x9d, 0xd5,
+	0x72, 0xf5, 0x3e, 0xcd, 0x9d, 0xbf, 0xea, 0xbb, 0x4e, 0xda, 0xfa, 0x3d,
+	0x31, 0xb3, 0xdc, 0xcf, 0x2d, 0xfb, 0x18, 0x9b, 0x92, 0x4d, 0xf8, 0xbe,
+	0x9e, 0xf1, 0x9f, 0x74, 0x47, 0x6d, 0x4b, 0xd7, 0x62, 0x52, 0xaa, 0xb7,
+	0x03, 0x6f, 0x87, 0x96, 0x9b, 0x37, 0xb5, 0xbc, 0xe7, 0xbf, 0xe6, 0x3a,
+	0xd2, 0x6f, 0x88, 0xef, 0xcf, 0x38, 0x7b, 0x92, 0xc7, 0xe5, 0x0c, 0xf0,
+	0xd6, 0x80, 0x4f, 0x2c, 0x3d, 0x43, 0xfa, 0x22, 0x9a, 0x8b, 0x5a, 0x6e,
+	0x28, 0xa2, 0x4f, 0x52, 0xa4, 0xbf, 0xb0, 0xa4, 0x83, 0xce, 0xed, 0x52,
+	0xa8, 0x5a, 0x32, 0xb1, 0xb4, 0x15, 0xfe, 0xa2, 0xff, 0xea, 0x50, 0x42,
+	0xfe, 0xb2, 0x9e, 0x3e, 0x55, 0x04, 0x2f, 0x66, 0xbc, 0x94, 0x80, 0xcf,
+	0x59, 0x77, 0xb4, 0x5f, 0x5e, 0xab, 0x27, 0xe5, 0xbb, 0x75, 0x3b, 0x59,
+	0x92, 0x6d, 0x52, 0x48, 0x58, 0xb2, 0x82, 0x35, 0xd3, 0xa0, 0x43, 0xb7,
+	0x6d, 0xab, 0x04, 0xd8, 0x52, 0xfd, 0x27, 0xfc, 0xb7, 0x32, 0xd6, 0xe4,
+	0xa8, 0x5a, 0x53, 0x04, 0xdd, 0x21, 0x2c, 0xcf, 0xa1, 0x60, 0xd5, 0x59,
+	0x02, 0x58, 0x29, 0x4e, 0x8e, 0x62, 0xae, 0xfe, 0x85, 0x50, 0x16, 0xad,
+	0x38, 0x2f, 0x9f, 0xbb, 0x71, 0xbe, 0xdd, 0xe0, 0x89, 0x24, 0x74, 0xd9,
+	0x93, 0x2c, 0x60, 0x66, 0xba, 0xde, 0x81, 0x31, 0x69, 0xf1, 0xfd, 0x23,
+	0x8e, 0x58, 0x25, 0xa7, 0x1b, 0xbc, 0x4b, 0x49, 0xc9, 0xe9, 0xc2, 0x9a,
+	0x16, 0xb1, 0x6c, 0x9e, 0x81, 0x78, 0xdb, 0x30, 0xef, 0x77, 0x1a, 0x19,
+	0xdf, 0x9f, 0x1c, 0x95, 0xae, 0x60, 0x6e, 0x1f, 0x70, 0x98, 0x32, 0x31,
+	0xae, 0x01, 0xee, 0x03, 0xd2, 0x17, 0x8b, 0x67, 0xd8, 0xe7, 0x73, 0x54,
+	0xdc, 0xd9, 0x54, 0xb8, 0x6f, 0x87, 0x94, 0xbc, 0xeb, 0xc3, 0x3e, 0x78,
+	0xed, 0xe1, 0xcc, 0xce, 0x4e, 0x8c, 0xb5, 0x1b, 0x80, 0xc7, 0x29, 0x09,
+	0xf7, 0xd8, 0x21, 0x6b, 0x09, 0xd1, 0x2f, 0x39, 0xbd, 0x21, 0x5c, 0x17,
+	0x68, 0x8d, 0x64, 0xde, 0x2e, 0x33, 0xf3, 0xad, 0x72, 0x72, 0x9e, 0xbc,
+	0x2d, 0x43, 0x16, 0x78, 0xde, 0x52, 0xd4, 0xb2, 0xf5, 0x53, 0xe8, 0x9b,
+	0x32, 0x69, 0xfb, 0xaf, 0xcd, 0x38, 0xb3, 0x5a, 0x6e, 0xf9, 0x8c, 0x96,
+	0x87, 0x0e, 0x1c, 0x5a, 0x3e, 0xaf, 0x1d, 0xae, 0xaf, 0x76, 0x4a, 0x7b,
+	0x1a, 0xda, 0x66, 0xca, 0x49, 0x4f, 0x13, 0xd2, 0xbb, 0x00, 0x7e, 0x65,
+	0x2d, 0x70, 0xde, 0xee, 0xd2, 0x0e, 0x03, 0x57, 0x8b, 0xfd, 0xad, 0x0e,
+	0xe9, 0x32, 0x64, 0x9b, 0x1d, 0xc1, 0xc6, 0xe4, 0x5b, 0xa0, 0x6d, 0xcd,
+	0x49, 0x00, 0x4e, 0xba, 0x83, 0x35, 0x3d, 0x21, 0x3d, 0xd4, 0x25, 0xea,
+	0x91, 0x9e, 0xcd, 0xcf, 0xfd, 0x69, 0x6f, 0x69, 0xff, 0x76, 0xc2, 0xc0,
+	0x3e, 0x52, 0x0f, 0x4d, 0xda, 0x6e, 0x8f, 0x29, 0x45, 0x4b, 0x97, 0xb4,
+	0x95, 0x93, 0x1b, 0x64, 0xc6, 0x11, 0xc9, 0x41, 0xbf, 0x75, 0xdb, 0x04,
+	0x8f, 0x6c, 0xf0, 0x68, 0xcf, 0xa9, 0x41, 0xfd, 0x0e, 0x49, 0xf5, 0x15,
+	0x35, 0x33, 0xe4, 0xe7, 0x82, 0xdc, 0xa6, 0xd6, 0xeb, 0x19, 0x07, 0x3a,
+	0xd9, 0xce, 0x3e, 0xf6, 0x8d, 0xa9, 0x7d, 0x8d, 0x8c, 0x9d, 0x5c, 0x14,
+	0xd1, 0xf4, 0xcc, 0x3e, 0xe0, 0xa3, 0xae, 0x12, 0xee, 0x29, 0xd0, 0x48,
+	0xda, 0xd9, 0xb7, 0xb1, 0x26, 0x26, 0xae, 0xd3, 0xd9, 0x40, 0x27, 0xe8,
+	0x49, 0x90, 0xe7, 0xe4, 0xa1, 0x3a, 0xa7, 0xb6, 0x71, 0xce, 0x5f, 0xfb,
+	0xdb, 0x46, 0x4c, 0x79, 0x5d, 0x9d, 0x97, 0x76, 0x45, 0x38, 0x75, 0x46,
+	0x21, 0x7f, 0xa6, 0x3d, 0xd1, 0x0a, 0x8e, 0xb5, 0x8e, 0x0b, 0x7a, 0xa1,
+	0x1b, 0x99, 0x0e, 0xc9, 0x29, 0xfa, 0x0e, 0x62, 0x2f, 0xda, 0x1b, 0xec,
+	0xc6, 0xe6, 0x59, 0x38, 0x97, 0x81, 0xed, 0xa6, 0x95, 0xfe, 0x14, 0x2a,
+	0xf4, 0x07, 0xa4, 0x6d, 0x35, 0xad, 0x4b, 0x80, 0xaf, 0xf4, 0x6c, 0x37,
+	0x68, 0xe3, 0x18, 0xb6, 0x67, 0xe3, 0xfd, 0x7e, 0xd8, 0xfa, 0xc1, 0x41,
+	0xf0, 0x87, 0x70, 0x76, 0x0a, 0xf2, 0xce, 0xba, 0xd8, 0xd3, 0x75, 0x6e,
+	0x56, 0x3c, 0xe8, 0xc1, 0x79, 0x06, 0x67, 0xc9, 0xaf, 0x76, 0xe8, 0xb3,
+	0x26, 0x05, 0x27, 0x9d, 0xa2, 0xfc, 0x03, 0xda, 0x75, 0xd9, 0x76, 0x4b,
+	0x23, 0xed, 0x91, 0xac, 0xa8, 0x8f, 0xa6, 0xc4, 0x47, 0x08, 0x4b, 0x38,
+	0xc2, 0xa7, 0x0f, 0x8a, 0xfe, 0x6b, 0xdf, 0xda, 0x74, 0x56, 0x5b, 0x06,
+	0x66, 0x41, 0x43, 0xc0, 0x5b, 0xf0, 0xe4, 0xb3, 0x60, 0xc9, 0xd7, 0xad,
+	0xfc, 0x23, 0x6c, 0x23, 0x1c, 0x74, 0xa2, 0x8f, 0x34, 0xac, 0x74, 0x04,
+	0xf6, 0x15, 0xd1, 0x14, 0xc9, 0x46, 0x0b, 0x71, 0x7c, 0xda, 0x39, 0x08,
+	0x0f, 0xbb, 0xf7, 0x60, 0xf7, 0x1e, 0x7c, 0x82, 0x07, 0x9b, 0xf7, 0xe8,
+	0x27, 0x52, 0xf2, 0xea, 0x10, 0xfc, 0xda, 0x86, 0x5f, 0x41, 0x1b, 0x43,
+	0x5f, 0x17, 0x03, 0x7e, 0x65, 0xba, 0xaa, 0xc3, 0x76, 0x61, 0x43, 0x4b,
+	0x9c, 0xb3, 0xf0, 0xcc, 0xe3, 0x69, 0xc3, 0x8f, 0x52, 0xaf, 0x22, 0xff,
+	0x49, 0x3f, 0x93, 0x84, 0x4f, 0xa1, 0xaf, 0xa1, 0x2f, 0x21, 0xac, 0xef,
+	0xe7, 0x1d, 0xae, 0xf5, 0x65, 0xdc, 0xa1, 0x1d, 0x75, 0x88, 0x1e, 0x2f,
+	0x6a, 0x47, 0x87, 0x60, 0x63, 0x37, 0xb6, 0x80, 0x56, 0xda, 0xda, 0x75,
+	0x74, 0x15, 0x68, 0xbf, 0xe8, 0x0c, 0xfe, 0x5d, 0xde, 0x36, 0xc0, 0x28,
+	0xa1, 0x76, 0x05, 0xe3, 0xb6, 0xd0, 0x9f, 0xf0, 0x7d, 0x3a, 0x95, 0x95,
+	0xdd, 0xe1, 0x98, 0xfd, 0x75, 0x7a, 0x1d, 0xfd, 0x96, 0x98, 0x0c, 0x9c,
+	0x09, 0xfc, 0xe0, 0xc0, 0x82, 0x25, 0xf6, 0x99, 0x80, 0xc6, 0x81, 0x73,
+	0x91, 0x3f, 0x6c, 0x01, 0x3e, 0xd0, 0xe7, 0x6d, 0xc4, 0x09, 0x91, 0xf7,
+	0x34, 0x98, 0x0a, 0xe6, 0xb6, 0xf2, 0x82, 0x3e, 0x98, 0xf6, 0x66, 0x35,
+	0xda, 0xdb, 0x01, 0xd8, 0x9b, 0xd3, 0x2a, 0x69, 0xe7, 0xef, 0x60, 0x6f,
+	0x4f, 0x39, 0x1a, 0x78, 0x23, 0x72, 0xa1, 0xdc, 0x01, 0x5b, 0x37, 0x93,
+	0xef, 0xc8, 0x9e, 0xd4, 0xb4, 0x68, 0x72, 0x9a, 0x73, 0x35, 0xcc, 0x29,
+	0xff, 0x1b, 0xd8, 0xf7, 0x45, 0xe3, 0x69, 0xd0, 0xe5, 0xfb, 0xd3, 0xc0,
+	0x59, 0xd8, 0x6f, 0x84, 0xb6, 0x15, 0xcd, 0xa7, 0x10, 0xf3, 0xdc, 0xcf,
+	0x19, 0x52, 0x1c, 0x6e, 0x91, 0xf4, 0xf0, 0x02, 0x70, 0x4f, 0x3a, 0x81,
+	0x1d, 0x53, 0xd7, 0x17, 0x81, 0x7f, 0xc6, 0x1b, 0x82, 0x1e, 0xd3, 0x0e,
+	0x40, 0x17, 0xf0, 0x2f, 0x02, 0xff, 0x4c, 0xbd, 0x45, 0xbe, 0x69, 0x46,
+	0xb1, 0x34, 0x3a, 0x4f, 0x1b, 0xc0, 0xa2, 0x7d, 0x4f, 0xc8, 0x17, 0xbd,
+	0xb8, 0xe6, 0x3e, 0x4b, 0x3f, 0x5b, 0x1a, 0x86, 0x9d, 0x68, 0x25, 0x87,
+	0x7b, 0x1b, 0xb2, 0xb8, 0x0e, 0x23, 0xd9, 0x52, 0x60, 0x83, 0x59, 0x77,
+	0xa8, 0x98, 0x34, 0x94, 0x2f, 0x11, 0x39, 0x5c, 0x36, 0x01, 0xc3, 0x31,
+	0xe7, 0x83, 0xb9, 0xb1, 0x72, 0x1f, 0x7c, 0x23, 0xc7, 0x57, 0xfd, 0x49,
+	0x27, 0x98, 0xfb, 0xdd, 0x72, 0x81, 0x32, 0x62, 0xdc, 0x4e, 0x95, 0x9c,
+	0x7f, 0xf7, 0xa1, 0xbf, 0x9b, 0xd6, 0x5c, 0x1b, 0x4f, 0x7a, 0x2c, 0x8c,
+	0xf5, 0xda, 0x11, 0x5b, 0xef, 0x6b, 0x0d, 0x7d, 0xd8, 0x11, 0x4c, 0x1e,
+	0x2a, 0x97, 0x7a, 0x5b, 0xe5, 0xaa, 0xc1, 0xd8, 0x79, 0x09, 0x46, 0xed,
+	0x96, 0xf7, 0x82, 0x1f, 0xa5, 0x9e, 0x86, 0xb9, 0x58, 0xbe, 0xec, 0xcb,
+	0x9a, 0x13, 0xac, 0xc1, 0xb8, 0x23, 0x57, 0xd6, 0xfb, 0x62, 0xb2, 0x3e,
+	0xb6, 0xb8, 0x66, 0x49, 0xf6, 0x0e, 0x2f, 0x8a, 0x5a, 0xdb, 0x1b, 0xdb,
+	0x58, 0x9b, 0xc8, 0x97, 0x4b, 0x3d, 0x0d, 0xe3, 0x64, 0x0e, 0xb8, 0xf4,
+	0x03, 0xeb, 0x6b, 0xfb, 0x37, 0xd6, 0xee, 0x90, 0x54, 0x0f, 0xd7, 0xeb,
+	0x7d, 0x6d, 0x1b, 0xb8, 0x53, 0x21, 0x3d, 0xbd, 0x6d, 0x1b, 0x38, 0x6c,
+	0xe2, 0x6c, 0x18, 0x0f, 0x13, 0xe7, 0xc0, 0x06, 0xce, 0xfd, 0x9b, 0xe9,
+	0x39, 0x21, 0xf0, 0x41, 0xb1, 0xd6, 0x8c, 0x1c, 0xb8, 0x50, 0x1e, 0x1c,
+	0xff, 0xa2, 0x20, 0xe6, 0xed, 0xdf, 0x16, 0xfa, 0x64, 0xf3, 0x80, 0x0b,
+	0x5e, 0x99, 0x42, 0x1f, 0xa7, 0x49, 0x09, 0x72, 0x7e, 0xa8, 0x26, 0x07,
+	0xd6, 0x6a, 0x12, 0xea, 0x12, 0x75, 0xe2, 0x32, 0x6c, 0x4c, 0x8a, 0xbb,
+	0x32, 0x1d, 0x13, 0x66, 0xc6, 0x82, 0xad, 0xc9, 0x78, 0x09, 0x3e, 0xd9,
+	0xc8, 0xec, 0x79, 0x3b, 0x67, 0x3c, 0xe9, 0x1b, 0x88, 0xdb, 0x39, 0xe9,
+	0x38, 0xe8, 0x8e, 0x62, 0xbe, 0x46, 0xdb, 0x82, 0x5f, 0xa9, 0x13, 0xf7,
+	0x7c, 0xb7, 0x74, 0x21, 0x2e, 0xd6, 0x5e, 0xda, 0x11, 0xd8, 0x8e, 0x98,
+	0x26, 0x7c, 0xed, 0xcc, 0x28, 0xe3, 0x78, 0x6b, 0x0c, 0xf0, 0x13, 0x46,
+	0x66, 0x6c, 0xe7, 0xf1, 0xda, 0x9d, 0x3b, 0x0b, 0xb5, 0xe2, 0xce, 0x42,
+	0xd9, 0xa2, 0x9d, 0xe8, 0xee, 0x28, 0xfa, 0x2a, 0x57, 0x4a, 0xc2, 0x26,
+	0x2e, 0xab, 0x3c, 0xe2, 0xb5, 0x7a, 0x1d, 0xf6, 0x47, 0xfb, 0x16, 0x19,
+	0xf7, 0xb0, 0xc7, 0xc8, 0x87, 0x90, 0x3b, 0x68, 0x83, 0x4f, 0xcb, 0xe2,
+	0xd4, 0xfa, 0xc8, 0xbf, 0x85, 0xf6, 0xc9, 0xfe, 0xfb, 0x7e, 0xe0, 0xef,
+	0xef, 0xe8, 0x0e, 0xe6, 0xde, 0x0a, 0x6d, 0x3a, 0xc2, 0x45, 0x3c, 0xc3,
+	0xda, 0x38, 0x72, 0x92, 0xf1, 0xba, 0xa9, 0xd1, 0x3f, 0xe7, 0x3c, 0xe6,
+	0x12, 0xcc, 0x23, 0xa6, 0x43, 0x3f, 0x27, 0xd9, 0x1c, 0xfc, 0x88, 0x8e,
+	0xdc, 0xa2, 0x00, 0xbb, 0x31, 0x33, 0x57, 0x64, 0x46, 0xf9, 0x48, 0x89,
+	0xb5, 0x64, 0x9e, 0x00, 0xcc, 0x7f, 0xc0, 0xe6, 0xda, 0xba, 0x43, 0x3d,
+	0x0c, 0x7d, 0xbc, 0xf2, 0xbb, 0x80, 0xbd, 0xbc, 0x05, 0xf6, 0xdd, 0x46,
+	0x58, 0xbc, 0xbf, 0xb8, 0xe5, 0xfd, 0x4f, 0x69, 0xbf, 0x78, 0xb7, 0x0a,
+	0x7f, 0xda, 0x1a, 0xda, 0xfe, 0x05, 0x29, 0xc0, 0xb7, 0x9a, 0x36, 0x73,
+	0xc7, 0xdb, 0xb0, 0x16, 0xe3, 0x1a, 0x68, 0x84, 0xbf, 0x40, 0xcc, 0x04,
+	0xbf, 0x11, 0x13, 0x12, 0x37, 0x30, 0x3f, 0xa2, 0x9f, 0x00, 0x2c, 0xfd,
+	0x2f, 0x61, 0x5f, 0xe9, 0x20, 0xcf, 0x0b, 0x35, 0xae, 0xa1, 0xaf, 0x12,
+	0xdf, 0x1d, 0x6d, 0x83, 0x46, 0xf9, 0xaf, 0x19, 0x76, 0x04, 0x1b, 0xe1,
+	0xdd, 0x0a, 0xcb, 0x7c, 0x85, 0xb8, 0xbb, 0xc3, 0x3c, 0x60, 0x4c, 0xb2,
+	0xf5, 0x2c, 0x7e, 0x45, 0x99, 0x7c, 0x16, 0xb9, 0x98, 0xdd, 0x42, 0x5e,
+	0x90, 0x35, 0x56, 0xc0, 0xa3, 0x68, 0xdd, 0x13, 0xbd, 0x9b, 0xc7, 0xf7,
+	0xc5, 0x37, 0x7c, 0x25, 0x2d, 0x4d, 0xb2, 0x88, 0x15, 0xe0, 0x71, 0x6a,
+	0x42, 0xcf, 0x24, 0x24, 0x57, 0x0b, 0xf8, 0x8b, 0x78, 0x0b, 0xff, 0xc8,
+	0x2e, 0x64, 0xb2, 0xee, 0x07, 0x23, 0x99, 0x53, 0xcf, 0xb2, 0x90, 0x4d,
+	0x0a, 0xba, 0x34, 0x86, 0xb5, 0x72, 0x02, 0x38, 0x18, 0x87, 0x1d, 0x3d,
+	0x13, 0x97, 0x82, 0xc5, 0x7c, 0x41, 0xe5, 0x7a, 0x59, 0xfa, 0x01, 0x3d,
+	0xd3, 0x86, 0x39, 0xf6, 0x1f, 0xee, 0x0e, 0x64, 0xdd, 0xc9, 0xf1, 0xb8,
+	0x9e, 0xe9, 0xde, 0x32, 0xff, 0x7a, 0x67, 0x40, 0x9b, 0x1a, 0x63, 0xfe,
+	0x5f, 0xb6, 0x8c, 0xbf, 0x1e, 0xdf, 0x3c, 0x7e, 0x60, 0x67, 0xa4, 0x0f,
+	0x7a, 0xe6, 0x89, 0x90, 0x5e, 0xea, 0xe9, 0x56, 0x5a, 0x7f, 0x13, 0x7d,
+	0x79, 0x0e, 0x38, 0x95, 0x8e, 0xff, 0x06, 0xfa, 0xb2, 0x0e, 0xfb, 0x09,
+	0xfa, 0xd2, 0x48, 0xc3, 0x7a, 0x5d, 0x51, 0xd1, 0x91, 0x93, 0xba, 0xa3,
+	0x7b, 0x90, 0x77, 0xa4, 0x24, 0x5f, 0x07, 0xef, 0xd6, 0xe3, 0xea, 0x3a,
+	0x4c, 0x71, 0x03, 0x26, 0x88, 0x3b, 0xf9, 0xba, 0x8f, 0x3c, 0xae, 0x31,
+	0x06, 0x0f, 0xa3, 0x5f, 0xc4, 0x59, 0x57, 0x64, 0xd2, 0x5b, 0xcb, 0xea,
+	0xf6, 0xa9, 0x20, 0x0f, 0xb5, 0xbf, 0xad, 0xe5, 0x17, 0x99, 0xa3, 0xc6,
+	0xd0, 0x57, 0xf5, 0x07, 0x62, 0xdc, 0x33, 0x5a, 0x76, 0x79, 0x0e, 0xf9,
+	0xe9, 0x12, 0x7e, 0x67, 0xf1, 0xab, 0xe1, 0x17, 0xd5, 0x01, 0x2f, 0xa0,
+	0x8e, 0x50, 0xfe, 0x1e, 0xb1, 0x29, 0xd8, 0xff, 0x67, 0x4b, 0xc8, 0x8f,
+	0xe7, 0x12, 0xf2, 0x94, 0xad, 0xf7, 0xea, 0x81, 0x8f, 0xcb, 0x22, 0xb7,
+	0xb6, 0x2e, 0xcb, 0x97, 0xc2, 0x1c, 0x4d, 0xe4, 0x9d, 0x0a, 0x64, 0xb9,
+	0xff, 0x48, 0xe8, 0x9f, 0xbe, 0xf6, 0xa0, 0xab, 0x7c, 0x79, 0x98, 0x83,
+	0xc1, 0xef, 0x64, 0x15, 0xd4, 0x1b, 0xe0, 0x8f, 0x26, 0xef, 0x41, 0x8f,
+	0xdf, 0xa9, 0xb4, 0x83, 0x1e, 0x5b, 0x0a, 0xc7, 0x90, 0xbb, 0x68, 0x83,
+	0xd6, 0x36, 0xad, 0x1d, 0x79, 0x18, 0xfc, 0x8e, 0x1a, 0x93, 0x67, 0x17,
+	0xa7, 0x16, 0xca, 0x3a, 0x60, 0xc1, 0xf3, 0x51, 0xf4, 0xa1, 0x7f, 0x97,
+	0x2a, 0x5c, 0xa7, 0xcb, 0xbb, 0x15, 0x43, 0x7e, 0x8e, 0xbc, 0xee, 0x3d,
+	0xfb, 0xe2, 0x14, 0x6c, 0xb0, 0x0f, 0xf1, 0x0a, 0xb5, 0xd0, 0x1e, 0xc6,
+	0x8c, 0x01, 0x13, 0xcf, 0x3c, 0x7e, 0x87, 0x91, 0xe7, 0x5d, 0x7b, 0xcd,
+	0x27, 0xc1, 0x93, 0xb6, 0x18, 0xd6, 0x10, 0xde, 0x04, 0x6d, 0x5d, 0xd0,
+	0xc1, 0xb4, 0x35, 0x21, 0xdd, 0x96, 0xca, 0x9d, 0x34, 0xce, 0x07, 0x7e,
+	0xf2, 0xe3, 0xf3, 0xe4, 0xb3, 0x01, 0x1d, 0xe2, 0x98, 0xef, 0xe8, 0xcf,
+	0x89, 0x2f, 0x7d, 0x30, 0x8b, 0xc3, 0x5c, 0xaa, 0x04, 0xfd, 0x68, 0x4e,
+	0xb4, 0x28, 0xa6, 0xd2, 0x4f, 0xe7, 0x61, 0xab, 0x1c, 0x8f, 0x8b, 0x92,
+	0xc1, 0x26, 0x79, 0x52, 0x8f, 0x56, 0xa7, 0x66, 0x6c, 0xca, 0xd5, 0x92,
+	0xe9, 0x72, 0x24, 0x57, 0xca, 0x08, 0x75, 0x66, 0xe5, 0xdb, 0x90, 0xab,
+	0x1e, 0xd6, 0x20, 0xf0, 0x03, 0x73, 0x94, 0x2f, 0xea, 0xc4, 0x0a, 0xf2,
+	0xb0, 0x8a, 0xc4, 0x83, 0x1a, 0xea, 0x19, 0xd4, 0x1d, 0x90, 0x5f, 0x79,
+	0x0e, 0x38, 0x12, 0x78, 0x2e, 0xe1, 0x99, 0xc4, 0xf3, 0x2c, 0x9e, 0xfd,
+	0x78, 0xd6, 0x68, 0x1f, 0x61, 0xde, 0xf3, 0x31, 0x7a, 0x60, 0x27, 0x79,
+	0xda, 0xb4, 0x7c, 0xaf, 0x9e, 0x91, 0xbf, 0xad, 0x1f, 0x94, 0xbf, 0xa9,
+	0x8f, 0xca, 0x5f, 0xd7, 0x1d, 0x79, 0xb9, 0xbe, 0x5f, 0xfe, 0xaa, 0x3e,
+	0xcc, 0x9a, 0x10, 0x39, 0x5c, 0x0a, 0xbe, 0xf9, 0xbc, 0x3c, 0xe8, 0xd5,
+	0xe1, 0x73, 0x28, 0xff, 0x8b, 0x53, 0xd9, 0xda, 0x75, 0x52, 0x78, 0xd6,
+	0x42, 0x9e, 0x69, 0xb0, 0x2e, 0x93, 0xc7, 0x9c, 0x3b, 0xe2, 0x94, 0xbd,
+	0x6e, 0xb3, 0x4e, 0x39, 0x49, 0x38, 0xd4, 0xbb, 0x1a, 0xf2, 0x97, 0x16,
+	0x99, 0x48, 0xa4, 0x57, 0x5c, 0x23, 0x19, 0xfa, 0xa3, 0x3b, 0x01, 0x87,
+	0x3d, 0xbd, 0x0e, 0x59, 0x7b, 0x1e, 0xb6, 0xe0, 0xa0, 0x56, 0x4e, 0xc4,
+	0xe0, 0xfb, 0x54, 0x7e, 0xa2, 0x7c, 0x4b, 0xe0, 0x4b, 0xa3, 0x9a, 0x91,
+	0x73, 0xd9, 0x70, 0x8e, 0xf1, 0xd1, 0x02, 0xec, 0x72, 0x18, 0x43, 0xb6,
+	0xe2, 0xa4, 0x6f, 0x3c, 0x16, 0xfa, 0xc7, 0x15, 0x39, 0xe1, 0x0d, 0x66,
+	0xaf, 0x20, 0xf6, 0x68, 0x2d, 0x51, 0x5e, 0xb4, 0x0b, 0xb4, 0xf9, 0xfe,
+	0xdd, 0xac, 0xbf, 0xe3, 0xa6, 0xfc, 0x70, 0x36, 0x6d, 0x3d, 0xa2, 0xcf,
+	0x40, 0xce, 0xbe, 0x7f, 0xd4, 0x4e, 0x9f, 0x9a, 0xd0, 0x3b, 0xe5, 0x27,
+	0xcf, 0x30, 0x26, 0xaf, 0x4e, 0x7d, 0x1f, 0x7a, 0x50, 0x5d, 0x6a, 0x95,
+	0x6a, 0xd5, 0x94, 0x4b, 0x23, 0x83, 0x6a, 0xdf, 0x6a, 0x2d, 0x8e, 0x3c,
+	0xaf, 0x4d, 0xa6, 0xfb, 0x94, 0xb2, 0xc3, 0x6f, 0x0f, 0x2b, 0xbf, 0xed,
+	0xda, 0x78, 0xd6, 0x92, 0xd6, 0x66, 0x5a, 0x5e, 0x96, 0x82, 0x07, 0x1d,
+	0x8b, 0xef, 0x02, 0x4f, 0xd8, 0x1f, 0xb4, 0x0a, 0x3a, 0x62, 0xa0, 0x39,
+	0x68, 0x3d, 0xa8, 0xff, 0xd2, 0xff, 0x1d, 0x93, 0x7c, 0x7c, 0x1b, 0xb1,
+	0x85, 0xb1, 0x52, 0x53, 0x7a, 0xb7, 0xb0, 0xf4, 0x53, 0x8b, 0xfe, 0x65,
+	0xa5, 0xb6, 0x2b, 0x1c, 0xd3, 0xbf, 0x73, 0xdc, 0x2e, 0x2f, 0x57, 0xb7,
+	0xcb, 0x62, 0x95, 0xef, 0x5b, 0x65, 0xa1, 0x3a, 0x78, 0xa5, 0x57, 0xef,
+	0x93, 0xd5, 0xeb, 0x6e, 0xb4, 0xee, 0xd7, 0xc1, 0x93, 0x63, 0x1f, 0xc9,
+	0x07, 0x23, 0xdd, 0xf2, 0xd6, 0x7d, 0xe9, 0x17, 0xfe, 0x44, 0x87, 0x3e,
+	0x8e, 0x74, 0xd0, 0xce, 0xd0, 0xe7, 0x7c, 0xfa, 0x4a, 0x56, 0xa7, 0x9e,
+	0xfd, 0x00, 0xfa, 0x95, 0xae, 0x04, 0x3a, 0x49, 0xdc, 0xc4, 0x0b, 0xf9,
+	0xd8, 0x6f, 0x00, 0x27, 0xde, 0xd5, 0x06, 0x81, 0xeb, 0x0d, 0xc5, 0x8b,
+	0xbb, 0x9d, 0xf4, 0x15, 0x84, 0x28, 0xff, 0x92, 0x3d, 0x38, 0x3c, 0xa0,
+	0xef, 0x92, 0x6a, 0xf2, 0x46, 0xeb, 0xbb, 0x88, 0x07, 0xd9, 0x44, 0xfa,
+	0xd4, 0x45, 0x59, 0x9d, 0xba, 0x60, 0x53, 0x17, 0x69, 0xc3, 0xff, 0x80,
+	0x9c, 0xd4, 0x92, 0x4a, 0x8d, 0xbe, 0x8b, 0xb8, 0x58, 0x17, 0xec, 0xb5,
+	0x4e, 0x80, 0x06, 0x77, 0x3f, 0xde, 0x61, 0xde, 0xf8, 0x3c, 0xe5, 0xd6,
+	0xc2, 0xb5, 0xc3, 0x59, 0xbd, 0x7f, 0x0b, 0x8f, 0x06, 0xad, 0x43, 0x3a,
+	0xf7, 0xfb, 0x2f, 0xec, 0xfb, 0x3e, 0x68, 0x1d, 0xc4, 0x5a, 0xc4, 0xd0,
+	0x64, 0xe3, 0x1e, 0x3f, 0x52, 0x7b, 0x3c, 0x5b, 0x43, 0x0e, 0xb8, 0xbe,
+	0x07, 0xe6, 0x6a, 0x3a, 0xce, 0x69, 0x2a, 0xb9, 0x5c, 0x1a, 0x21, 0x7f,
+	0x6f, 0xef, 0x61, 0x2c, 0x37, 0x32, 0x2f, 0x85, 0x79, 0x46, 0x4c, 0x7e,
+	0x8c, 0xba, 0x6b, 0x12, 0xfe, 0x7f, 0x61, 0xef, 0x20, 0x68, 0x40, 0x7d,
+	0x9a, 0x54, 0xf1, 0x7c, 0xca, 0x05, 0x8e, 0x9c, 0xc2, 0xfd, 0xa6, 0x2c,
+	0x01, 0xf7, 0x38, 0xf9, 0x00, 0xdc, 0x33, 0x9c, 0x57, 0x32, 0xc0, 0x7c,
+	0x2d, 0x05, 0xbc, 0xbd, 0xa1, 0xff, 0x8b, 0x43, 0x57, 0xf7, 0x59, 0x77,
+	0x4b, 0x2c, 0xf4, 0x7f, 0x71, 0x79, 0xeb, 0x79, 0xe8, 0x7d, 0x9c, 0xfa,
+	0x93, 0xe8, 0xd9, 0xd0, 0x9f, 0x46, 0xfc, 0xad, 0x92, 0xaf, 0xc4, 0x80,
+	0x17, 0x39, 0xf7, 0x28, 0xf1, 0x62, 0x5c, 0xa5, 0x2e, 0x17, 0x43, 0x5d,
+	0xee, 0x08, 0x71, 0xaf, 0x41, 0x97, 0xd3, 0xa9, 0x55, 0x9d, 0xf5, 0xd5,
+	0x4e, 0x55, 0xf3, 0x1a, 0xb0, 0xaf, 0x42, 0x99, 0xb1, 0x88, 0xb6, 0x75,
+	0x71, 0x6a, 0x12, 0x35, 0x6c, 0xa1, 0x7c, 0x50, 0x2f, 0xd4, 0x47, 0xf5,
+	0x82, 0x47, 0x7d, 0xdb, 0x6b, 0x2d, 0x28, 0x1e, 0x27, 0x65, 0xa1, 0xfe,
+	0x81, 0x5f, 0xda, 0xbb, 0x0d, 0x7d, 0xe8, 0xfe, 0x38, 0xe5, 0x7b, 0x3d,
+	0xe9, 0x42, 0x50, 0x27, 0xbf, 0x13, 0x72, 0x66, 0xe8, 0x7b, 0xdd, 0xcc,
+	0xd1, 0x96, 0x87, 0x88, 0x1f, 0x74, 0x24, 0x12, 0xb2, 0xe8, 0x71, 0x8f,
+	0xd5, 0x29, 0xf2, 0xb2, 0x30, 0x67, 0xc9, 0x09, 0x25, 0x3f, 0x9e, 0x9b,
+	0xf7, 0x47, 0x86, 0x4c, 0xc6, 0x07, 0xad, 0x47, 0x25, 0x7d, 0x65, 0xcd,
+	0x48, 0xbf, 0x30, 0x81, 0xb8, 0xba, 0x30, 0x6f, 0x88, 0xab, 0xea, 0x30,
+	0xca, 0x28, 0x5d, 0x81, 0x35, 0x86, 0x67, 0xbf, 0xa7, 0xe1, 0xec, 0x5d,
+	0x72, 0xe1, 0xf9, 0xcf, 0xc3, 0xee, 0x5f, 0x81, 0x2c, 0xcc, 0xd4, 0x71,
+	0xe4, 0x19, 0xcf, 0xc9, 0xa0, 0x55, 0x42, 0xfe, 0x0c, 0xbe, 0xa3, 0xbd,
+	0xa2, 0x6c, 0x60, 0x41, 0xc7, 0xb8, 0x9f, 0x7c, 0xe2, 0x78, 0xb7, 0x2c,
+	0xf4, 0x05, 0x36, 0xce, 0x77, 0x03, 0xc0, 0x11, 0xbc, 0xe3, 0xf8, 0xb7,
+	0x64, 0x40, 0xbd, 0xab, 0xaa, 0x75, 0x25, 0xe9, 0x0d, 0xe5, 0xf7, 0x18,
+	0xf6, 0x24, 0x8f, 0xa3, 0xf9, 0x4e, 0x09, 0x6c, 0x29, 0xe2, 0xbb, 0x25,
+	0x47, 0x6b, 0x09, 0xb9, 0xa7, 0x96, 0x94, 0x2f, 0xd7, 0xfa, 0x25, 0x0f,
+	0x39, 0x4e, 0x8e, 0x3e, 0xd9, 0xc3, 0xb3, 0xe5, 0x96, 0xd2, 0x2f, 0x88,
+	0x4e, 0x5a, 0xab, 0x72, 0xdc, 0x8b, 0xe8, 0xe9, 0x08, 0xe9, 0x33, 0xc3,
+	0x71, 0x2c, 0xa4, 0xa1, 0x11, 0x5f, 0x07, 0x70, 0x65, 0x81, 0xe7, 0xa5,
+	0x10, 0x0f, 0xfd, 0x08, 0x68, 0x3d, 0x96, 0x94, 0x25, 0x8f, 0x74, 0x6c,
+	0x97, 0x52, 0x82, 0xfd, 0x57, 0xa0, 0x6f, 0xc4, 0xb3, 0x8d, 0xf9, 0xcd,
+	0x26, 0x1e, 0x3f, 0x5c, 0x2b, 0x82, 0xc7, 0xe4, 0x2f, 0xe1, 0xe0, 0xaf,
+	0xbf, 0x40, 0xf9, 0xed, 0x43, 0x8e, 0x6f, 0x07, 0xba, 0x69, 0x6d, 0xec,
+	0x99, 0x9f, 0xeb, 0x82, 0xac, 0xb8, 0x6f, 0xbb, 0x1c, 0x83, 0xdd, 0xe7,
+	0xaa, 0xdc, 0xff, 0x18, 0xf4, 0xe8, 0x2d, 0xb5, 0x7f, 0x7e, 0xa9, 0x2f,
+	0x5c, 0xcf, 0xb5, 0x5d, 0x5b, 0xd6, 0xb6, 0xca, 0xa1, 0x8a, 0x75, 0x8d,
+	0xf5, 0xbf, 0x8f, 0xf5, 0xba, 0x9c, 0x1e, 0xe5, 0x7a, 0xe2, 0x01, 0x5c,
+	0x35, 0xf1, 0x29, 0x78, 0xe2, 0xaa, 0xde, 0xcf, 0x55, 0x5b, 0x25, 0x57,
+	0x89, 0x70, 0x11, 0xcf, 0x47, 0xa8, 0x87, 0xbf, 0xaa, 0x70, 0x4d, 0x2a,
+	0x5c, 0x78, 0x5f, 0xa5, 0xcf, 0xb9, 0x15, 0xeb, 0x3b, 0xe8, 0xff, 0xa5,
+	0x14, 0xef, 0x94, 0x92, 0xaa, 0xe9, 0xdb, 0x95, 0xaf, 0x29, 0xc5, 0xdb,
+	0xf0, 0xbe, 0x13, 0x36, 0xbf, 0x0f, 0xb9, 0x45, 0x17, 0xeb, 0xdc, 0x2d,
+	0x73, 0x5b, 0xe9, 0x8f, 0x6d, 0xa1, 0x3f, 0x06, 0xb8, 0x5e, 0xec, 0x19,
+	0xc0, 0xe5, 0x01, 0x37, 0x3d, 0x07, 0x3e, 0x3b, 0xf4, 0x2b, 0x8c, 0x93,
+	0xd7, 0x29, 0x5a, 0xa6, 0x97, 0xfe, 0x1b, 0xe7, 0xea, 0xc3, 0xda, 0x68,
+	0x1c, 0xf0, 0xe1, 0x69, 0xe0, 0x99, 0xab, 0xaa, 0xbb, 0x0b, 0xc8, 0x60,
+	0x7b, 0x9c, 0x67, 0x2f, 0x55, 0x3f, 0x8b, 0x67, 0xd7, 0x35, 0xf0, 0x8b,
+	0xbc, 0x22, 0xbd, 0xa4, 0x95, 0xf7, 0x48, 0xb0, 0x37, 0x07, 0x7a, 0x1c,
+	0x37, 0x24, 0x3f, 0x6a, 0x21, 0x3f, 0xe7, 0x3d, 0x2c, 0xed, 0xd2, 0xe2,
+	0xdd, 0x67, 0x4c, 0xb7, 0x19, 0x6b, 0x4d, 0x75, 0xf6, 0xe3, 0x4b, 0xbc,
+	0x8b, 0x4d, 0xf1, 0xee, 0x6e, 0x98, 0xd7, 0x18, 0x8f, 0x2c, 0xd9, 0xf2,
+	0x78, 0x6d, 0x58, 0x1e, 0xad, 0xa5, 0xad, 0xfb, 0xe1, 0x03, 0x0a, 0xeb,
+	0x77, 0xb4, 0x43, 0x71, 0xfa, 0x2f, 0x13, 0x79, 0x60, 0x8b, 0x1d, 0xe4,
+	0x05, 0x25, 0xd6, 0x6c, 0x73, 0x69, 0xde, 0xe3, 0x58, 0x55, 0xd9, 0x9a,
+	0x3b, 0xfc, 0x5f, 0xe6, 0x0d, 0xdc, 0x9f, 0xfe, 0x1a, 0x79, 0x82, 0x87,
+	0x3c, 0xc1, 0x43, 0x9e, 0xe0, 0x21, 0x4f, 0xf0, 0x90, 0x27, 0x78, 0xc8,
+	0x13, 0x3c, 0xe4, 0x09, 0x1e, 0xf2, 0x04, 0xc4, 0xee, 0xa0, 0x5e, 0x18,
+	0x43, 0xfe, 0x0b, 0xff, 0xe5, 0xdd, 0x06, 0x3e, 0xf1, 0xfe, 0x92, 0x31,
+	0x87, 0xb1, 0x99, 0x73, 0xab, 0xdb, 0x5c, 0xca, 0x4d, 0xf9, 0xbe, 0x3b,
+	0x31, 0x37, 0x1e, 0xe6, 0x23, 0x84, 0x89, 0x62, 0x37, 0xe1, 0xe4, 0xa0,
+	0xeb, 0x68, 0xb0, 0x31, 0xe6, 0x2b, 0x41, 0xcc, 0x0a, 0x72, 0xe5, 0xb7,
+	0x91, 0xb3, 0xa4, 0x90, 0xb3, 0xf4, 0x23, 0x3f, 0xe1, 0x9d, 0x75, 0x74,
+	0xc7, 0x94, 0xd5, 0x8e, 0x7a, 0x63, 0xda, 0x3d, 0x1e, 0x73, 0x69, 0x3b,
+	0x55, 0xd0, 0xf5, 0xb9, 0x5e, 0xf1, 0x25, 0x37, 0xf2, 0x4d, 0xe4, 0xad,
+	0xcf, 0xa9, 0xfb, 0xb4, 0xf1, 0x21, 0xca, 0xbc, 0xf2, 0x09, 0xb9, 0x6b,
+	0xc4, 0xdf, 0xe0, 0x1e, 0x50, 0x5f, 0x20, 0xff, 0x44, 0x7a, 0xce, 0x81,
+	0xe1, 0xe7, 0x62, 0x12, 0x3f, 0xb3, 0x1d, 0x73, 0x96, 0xf4, 0xaa, 0xbb,
+	0x24, 0x88, 0xf2, 0xdc, 0x55, 0xc8, 0xcb, 0x16, 0xfd, 0x1c, 0x6f, 0x1c,
+	0x88, 0x97, 0xfe, 0x75, 0x65, 0x2a, 0x57, 0x5d, 0x51, 0x3a, 0x75, 0xb4,
+	0x96, 0x47, 0x7d, 0xd4, 0xd3, 0x2b, 0xed, 0x26, 0x6a, 0xab, 0x08, 0x37,
+	0x71, 0xfe, 0x32, 0xae, 0x6a, 0x9e, 0x73, 0xeb, 0xf2, 0x84, 0xac, 0xb9,
+	0xcf, 0xca, 0x54, 0xa9, 0x92, 0x4e, 0xb2, 0x56, 0xce, 0x5a, 0x2b, 0x53,
+	0x27, 0x81, 0x63, 0x11, 0xb9, 0x81, 0xa1, 0xf6, 0x5e, 0x99, 0x9a, 0xae,
+	0x04, 0xf7, 0x59, 0x01, 0x0d, 0x8c, 0x57, 0xed, 0x62, 0x2c, 0x04, 0xf7,
+	0x5a, 0xba, 0x5a, 0xcb, 0x75, 0x5c, 0x6f, 0x62, 0x1d, 0xe5, 0x36, 0x8c,
+	0xb5, 0x94, 0x1d, 0x69, 0x58, 0x99, 0x2a, 0x56, 0x1b, 0x69, 0x20, 0x1e,
+	0xe2, 0x8d, 0xce, 0xc3, 0xb3, 0xc4, 0x45, 0x3f, 0xe3, 0xfb, 0x85, 0x91,
+	0xfe, 0x30, 0xef, 0x3a, 0x89, 0xfc, 0xce, 0x0c, 0xf4, 0x5c, 0x8d, 0xbf,
+	0xa3, 0xe2, 0x54, 0x4a, 0xe7, 0x3c, 0x9f, 0x78, 0x37, 0xba, 0x80, 0x39,
+	0x8c, 0x17, 0x23, 0x58, 0x3d, 0x84, 0xed, 0x6c, 0xe0, 0x67, 0x4b, 0xb8,
+	0x1f, 0x69, 0xe2, 0x39, 0x2f, 0x61, 0x2f, 0xd2, 0x45, 0x98, 0x38, 0x68,
+	0x83, 0x2c, 0xbd, 0xff, 0x2d, 0xef, 0x1b, 0xcf, 0x44, 0x9e, 0x9a, 0x58,
+	0x43, 0x78, 0xe2, 0x88, 0xd6, 0xe0, 0xc5, 0xb9, 0x60, 0x9d, 0xbe, 0x7e,
+	0xff, 0xf7, 0x69, 0xfb, 0x36, 0xd2, 0x1a, 0xed, 0x1f, 0xe1, 0x19, 0x0e,
+	0xe4, 0xb6, 0xbe, 0x5e, 0xfd, 0x9f, 0x61, 0x78, 0x42, 0x17, 0x3f, 0x76,
+	0x8f, 0x3a, 0xdc, 0x50, 0x87, 0x46, 0xf7, 0x17, 0xbc, 0x0f, 0x60, 0x7d,
+	0xcf, 0x6f, 0x07, 0x8d, 0xb5, 0xe2, 0xcb, 0x61, 0x2c, 0xdb, 0x29, 0x59,
+	0x93, 0x75, 0xc3, 0xf9, 0x70, 0xbc, 0x03, 0xb1, 0x8d, 0xe3, 0x3a, 0xf8,
+	0x0b, 0x5d, 0x76, 0xda, 0xc3, 0xba, 0x25, 0x1e, 0x7c, 0xe3, 0x19, 0xa6,
+	0x1d, 0xb1, 0xee, 0x6b, 0x0b, 0xe7, 0x22, 0x3b, 0xa2, 0x1f, 0x36, 0xc3,
+	0x39, 0xfa, 0x5b, 0x1d, 0xb5, 0x0b, 0xfb, 0xc0, 0xb3, 0xd8, 0x68, 0x4b,
+	0xd1, 0x33, 0x2e, 0x67, 0xe7, 0x23, 0xbf, 0x05, 0x9f, 0x32, 0x64, 0x86,
+	0xbe, 0xbf, 0x03, 0xbe, 0xaf, 0x4b, 0x0e, 0xc1, 0x67, 0x1d, 0x86, 0xcf,
+	0x3a, 0x82, 0x7a, 0x71, 0x6c, 0xa9, 0xf1, 0x9e, 0x97, 0x35, 0x6a, 0x97,
+	0x76, 0x5c, 0xc9, 0xbf, 0xe8, 0x1b, 0xf6, 0x47, 0xd0, 0x01, 0xd6, 0x5d,
+	0x91, 0x4e, 0xc0, 0xdf, 0x3a, 0x71, 0xe8, 0xc4, 0xd6, 0xfb, 0xe4, 0x61,
+	0xd8, 0x46, 0x7b, 0x56, 0xc5, 0x86, 0xa5, 0x80, 0xf7, 0xa5, 0x6a, 0xc0,
+	0x7b, 0xf8, 0x65, 0xe0, 0x37, 0xa5, 0x58, 0xb3, 0xa4, 0x88, 0x7d, 0x8b,
+	0xd8, 0xb7, 0x88, 0x3a, 0x6f, 0xba, 0xd6, 0xf8, 0x1d, 0xab, 0x33, 0xa4,
+	0x9d, 0x6b, 0xa3, 0xbe, 0xd5, 0x70, 0xfe, 0xe8, 0x79, 0x0a, 0xfc, 0x7f,
+	0x0c, 0xfc, 0x3f, 0x81, 0xfa, 0xe6, 0x8f, 0x50, 0xdf, 0x7c, 0x0d, 0xf5,
+	0xcd, 0x71, 0xd4, 0x37, 0x13, 0xa8, 0x6f, 0xbe, 0x0a, 0xff, 0xf1, 0x15,
+	0xf8, 0x8f, 0x63, 0xf0, 0x1f, 0xe3, 0xea, 0xee, 0xe9, 0xa8, 0xb7, 0xf5,
+	0x4e, 0x25, 0xda, 0x8b, 0xed, 0x67, 0x22, 0x76, 0x11, 0x67, 0x1a, 0x93,
+	0x6a, 0x9d, 0xf5, 0x8d, 0x23, 0xee, 0x41, 0xd6, 0x37, 0xc7, 0xb4, 0x09,
+	0xe4, 0xef, 0xf7, 0xef, 0x67, 0xdd, 0x13, 0xd7, 0x72, 0xaa, 0xee, 0x49,
+	0x9f, 0x77, 0x91, 0x22, 0x21, 0xf7, 0xc3, 0x99, 0xd3, 0x67, 0x73, 0xa0,
+	0x25, 0xc8, 0xf9, 0x7a, 0x42, 0xbf, 0xd7, 0x21, 0x8b, 0xb3, 0xa8, 0x19,
+	0xbc, 0x1f, 0x6b, 0x05, 0xe5, 0x1b, 0x2d, 0x8c, 0x51, 0x2b, 0x7b, 0xff,
+	0x1c, 0x8e, 0x47, 0x64, 0x72, 0x1e, 0xb5, 0xed, 0xf3, 0xff, 0xa8, 0xe5,
+	0xd4, 0xd8, 0xc1, 0x18, 0xf9, 0xee, 0xf3, 0x7f, 0x1f, 0x8e, 0x8b, 0xa1,
+	0x3e, 0x84, 0xb4, 0x5a, 0x0e, 0x9e, 0xdd, 0x61, 0xce, 0xf1, 0x6a, 0xef,
+	0xe6, 0xff, 0xd3, 0x8e, 0xad, 0x45, 0x13, 0xfb, 0x1b, 0x3b, 0x82, 0xfa,
+	0xac, 0x71, 0xbe, 0xab, 0x61, 0xfe, 0x8a, 0xfa, 0xce, 0x5a, 0x28, 0xb7,
+	0xfd, 0x0a, 0x1e, 0x58, 0x96, 0x86, 0x98, 0xe7, 0x7d, 0xe4, 0xf3, 0xfb,
+	0x9f, 0xab, 0xb7, 0xab, 0x6f, 0x72, 0xae, 0xca, 0xb7, 0x61, 0xe7, 0x23,
+	0xa5, 0x1d, 0x81, 0x2f, 0x60, 0x3f, 0xa1, 0x05, 0xfe, 0xfd, 0x8f, 0x81,
+	0x07, 0xbc, 0xf6, 0x1a, 0x6b, 0x38, 0x2b, 0xbc, 0x4b, 0xb9, 0x32, 0xc5,
+	0xdc, 0xba, 0xa4, 0x70, 0xb3, 0xd6, 0x63, 0xdd, 0x17, 0xc5, 0x80, 0x08,
+	0xd7, 0xcf, 0x13, 0x01, 0xdd, 0xe3, 0xa8, 0xe9, 0x08, 0x13, 0x8d, 0x1b,
+	0xeb, 0xbf, 0x8e, 0xf0, 0x1e, 0xee, 0x4a, 0x90, 0x57, 0x29, 0x7c, 0x66,
+	0x88, 0xef, 0x3f, 0xfd, 0xc0, 0xf7, 0x70, 0xbd, 0xd5, 0xb0, 0xfe, 0x3c,
+	0x72, 0x3d, 0xde, 0x99, 0xec, 0x52, 0xdf, 0x19, 0xdf, 0x9f, 0xed, 0x94,
+	0x5f, 0x3c, 0xe3, 0xfb, 0xe3, 0x4e, 0x7a, 0xf8, 0x4d, 0xd4, 0x1e, 0x67,
+	0x68, 0x27, 0x23, 0xa4, 0x73, 0x30, 0x35, 0x2d, 0x03, 0xbd, 0x41, 0x2e,
+	0xfe, 0x75, 0xed, 0xe3, 0x74, 0xeb, 0xe1, 0x3e, 0x3f, 0x6c, 0xd8, 0x27,
+	0xd5, 0xb0, 0xcf, 0x0a, 0x6d, 0xb6, 0x7a, 0x2f, 0xce, 0x5c, 0xdc, 0x75,
+	0xa3, 0x95, 0x08, 0xeb, 0xb2, 0x47, 0x47, 0xda, 0xa4, 0xd2, 0x97, 0x5e,
+	0xf9, 0x11, 0xf2, 0xf5, 0xc2, 0x08, 0xe6, 0x12, 0x83, 0x78, 0xc7, 0xf9,
+	0x74, 0x15, 0xb9, 0xe8, 0x4a, 0x55, 0x86, 0xb0, 0x3e, 0x5d, 0x14, 0xe1,
+	0x3c, 0xfb, 0x8a, 0xb6, 0x6a, 0xe8, 0x03, 0x92, 0x6b, 0x38, 0xf3, 0x04,
+	0xea, 0xaf, 0x13, 0xeb, 0xf5, 0x30, 0xf7, 0xb9, 0x59, 0x5b, 0x53, 0xb9,
+	0xf1, 0x01, 0xad, 0x98, 0x08, 0xce, 0xf8, 0x87, 0xf0, 0x17, 0x86, 0xce,
+	0xb5, 0xef, 0x03, 0xb7, 0x26, 0x0b, 0xcf, 0x18, 0xea, 0x0e, 0xb6, 0x30,
+	0x42, 0x59, 0xf3, 0x79, 0x2d, 0xde, 0x45, 0x67, 0xfa, 0xf3, 0xf0, 0x4c,
+	0xd9, 0xb0, 0x9e, 0x8e, 0xce, 0x14, 0x93, 0x77, 0x67, 0x2d, 0xac, 0xfd,
+	0x1c, 0xf8, 0x91, 0x97, 0xa5, 0x7a, 0xea, 0x33, 0xf0, 0x94, 0x1b, 0x78,
+	0x63, 0x6e, 0x91, 0x61, 0x71, 0xa3, 0x86, 0x1f, 0x4f, 0xc2, 0x0e, 0xbf,
+	0xd1, 0x1b, 0xdd, 0x0d, 0x1b, 0xb6, 0xcf, 0xba, 0x07, 0x8d, 0xf3, 0xfd,
+	0xb0, 0xc5, 0x14, 0xec, 0x93, 0x39, 0x53, 0x9e, 0xb5, 0x0a, 0xed, 0xc9,
+	0x72, 0x8d, 0xb4, 0x75, 0x4c, 0x86, 0x51, 0xef, 0xf0, 0xfc, 0x19, 0x59,
+	0xac, 0x47, 0x34, 0x8c, 0xc2, 0x1e, 0x0f, 0xe2, 0xb7, 0x1f, 0xef, 0x1c,
+	0xfc, 0x58, 0x2b, 0xad, 0xc8, 0xe3, 0x2a, 0x17, 0x47, 0xae, 0x3d, 0x44,
+	0xfa, 0xee, 0x04, 0x3c, 0xf5, 0x99, 0x7a, 0x7a, 0xa7, 0xb8, 0x7d, 0xf4,
+	0x15, 0x49, 0xe0, 0xc6, 0x1a, 0xef, 0x22, 0x6c, 0xbd, 0x1f, 0xcf, 0xb4,
+	0x55, 0x20, 0x6f, 0x15, 0x7e, 0xdf, 0x37, 0x46, 0xf9, 0x8d, 0xe2, 0x7c,
+	0x38, 0x1e, 0xb4, 0xbe, 0x4c, 0xdd, 0x4b, 0xee, 0x96, 0x95, 0xf9, 0x28,
+	0x0e, 0x9e, 0x86, 0x0d, 0xf2, 0xce, 0x76, 0x0c, 0x7c, 0xe1, 0x58, 0x0b,
+	0xe3, 0x21, 0xe6, 0x17, 0x97, 0x71, 0xee, 0x8c, 0x9c, 0x41, 0xfd, 0x2f,
+	0x7d, 0x7c, 0xa6, 0x80, 0x7f, 0x7b, 0xa8, 0xef, 0x9b, 0xd7, 0x1b, 0x36,
+	0xfb, 0x63, 0xa0, 0xcf, 0x6c, 0x58, 0xcf, 0x35, 0x41, 0x7d, 0xb2, 0x26,
+	0x88, 0xc7, 0x49, 0xff, 0x76, 0x3d, 0xf3, 0xa2, 0x3c, 0xa0, 0xce, 0x54,
+	0x93, 0xe3, 0xf3, 0xbe, 0xef, 0x8e, 0x0e, 0x0e, 0x2f, 0x4a, 0x7a, 0xf8,
+	0xa4, 0xec, 0xb3, 0x0e, 0xb1, 0x1e, 0xb3, 0x88, 0xc7, 0xbf, 0xbd, 0x25,
+	0xe3, 0xfb, 0xa7, 0x41, 0xfb, 0xf7, 0xd5, 0x3e, 0x2f, 0x82, 0x7e, 0xf0,
+	0x4a, 0xd5, 0x24, 0xa4, 0x15, 0xcf, 0x04, 0xe9, 0x2d, 0xcb, 0xf1, 0xfa,
+	0x85, 0x50, 0x36, 0x8f, 0x89, 0xeb, 0x5d, 0x36, 0x5c, 0xbb, 0x0c, 0xd8,
+	0x85, 0x90, 0xb6, 0x0c, 0xe8, 0xc5, 0xfe, 0xf5, 0xb7, 0x13, 0xf4, 0x0d,
+	0x94, 0xb9, 0x8b, 0xac, 0xd1, 0x1d, 0x41, 0x1e, 0x95, 0xf8, 0x24, 0x3f,
+	0x10, 0x97, 0xcd, 0x7e, 0x80, 0xeb, 0xe2, 0xd7, 0xd0, 0x15, 0xd2, 0x51,
+	0x54, 0xfe, 0x53, 0xc5, 0x2d, 0x85, 0xcf, 0xd8, 0xe2, 0x0b, 0x2a, 0xea,
+	0xb9, 0x6a, 0xd0, 0x37, 0x31, 0xfe, 0x51, 0x87, 0xbb, 0xe0, 0xff, 0xa0,
+	0x83, 0xb0, 0xe3, 0xdc, 0x3c, 0xef, 0x27, 0x86, 0x78, 0xaf, 0x74, 0x36,
+	0x0f, 0xd9, 0x2e, 0xf0, 0xfb, 0x63, 0x22, 0xa8, 0x31, 0x83, 0xfa, 0x2b,
+	0x45, 0x5f, 0x88, 0xb6, 0xa4, 0xfc, 0x64, 0x5e, 0x7d, 0x6f, 0x8c, 0x03,
+	0xc6, 0xa7, 0xef, 0x6c, 0xf8, 0x9b, 0x89, 0x1f, 0x64, 0x83, 0xbf, 0x99,
+	0x08, 0xbf, 0xfd, 0x56, 0x83, 0x3c, 0xe2, 0xe1, 0x9a, 0x29, 0x13, 0xb5,
+	0xe8, 0x6f, 0x28, 0x28, 0x07, 0xf8, 0xe6, 0x5a, 0x94, 0x3b, 0xf8, 0x41,
+	0x4d, 0xb3, 0x49, 0x96, 0x4b, 0x61, 0x4e, 0xc4, 0x1a, 0x80, 0x3c, 0xc4,
+	0x78, 0x31, 0xaa, 0x2f, 0x07, 0x20, 0x3f, 0xf0, 0x1c, 0x74, 0xbd, 0x3b,
+	0x1b, 0xd4, 0xb9, 0x25, 0xfa, 0xc5, 0xfe, 0xa8, 0xee, 0xdd, 0x25, 0xa5,
+	0x63, 0x7c, 0x1f, 0x93, 0x77, 0x66, 0x63, 0xea, 0x7d, 0x41, 0x62, 0xe1,
+	0x7b, 0x8e, 0xe3, 0x52, 0x50, 0xef, 0xab, 0x21, 0x3e, 0xd4, 0x69, 0x5f,
+	0x89, 0xc6, 0xa6, 0x76, 0xbc, 0x1e, 0xac, 0x9b, 0xac, 0x57, 0xe5, 0xf1,
+	0xfa, 0x2a, 0xce, 0xaf, 0x49, 0x6e, 0xbc, 0x28, 0xbb, 0x6d, 0x4b, 0xc5,
+	0x7d, 0x37, 0x4e, 0x1d, 0xa3, 0x7e, 0x8d, 0xa9, 0xba, 0xb3, 0x88, 0x7c,
+	0xa1, 0x30, 0xc2, 0x6f, 0x3c, 0xbf, 0xba, 0xab, 0x50, 0x4e, 0x5b, 0x59,
+	0xf9, 0xd0, 0x77, 0x4d, 0x8e, 0x45, 0x47, 0x3d, 0x74, 0xd7, 0xc3, 0xb5,
+	0x0b, 0x77, 0x05, 0x67, 0xc5, 0xfb, 0x1a, 0x61, 0x0d, 0xf5, 0x6d, 0xf6,
+	0x5f, 0x6f, 0x35, 0x65, 0xed, 0x56, 0xdf, 0xbf, 0xdf, 0xb1, 0xc4, 0x0d,
+	0x6b, 0x57, 0x4b, 0xd5, 0xae, 0xed, 0x2a, 0x07, 0x71, 0x47, 0x52, 0x5a,
+	0x1e, 0xf6, 0x7a, 0xc6, 0x43, 0x9d, 0xa3, 0xa7, 0x0f, 0xae, 0xea, 0x16,
+	0x62, 0x6e, 0x3a, 0x35, 0x27, 0x6e, 0x2f, 0xbf, 0x37, 0xcf, 0x38, 0x84,
+	0xd9, 0x19, 0xdc, 0x75, 0xdd, 0x34, 0xae, 0xfc, 0xac, 0x48, 0x18, 0x7b,
+	0x6e, 0x6a, 0xb4, 0x89, 0xc6, 0xdc, 0x92, 0xb6, 0x20, 0x13, 0x26, 0x68,
+	0x29, 0x95, 0xa3, 0x3c, 0x8d, 0x7f, 0x1b, 0xb0, 0x7a, 0xd7, 0xd3, 0xa0,
+	0x73, 0x1a, 0x74, 0xf2, 0x1c, 0xd3, 0xb5, 0x48, 0xe7, 0xa2, 0x5a, 0x81,
+	0x7d, 0xc4, 0x7c, 0x0f, 0x31, 0xdf, 0x43, 0xcc, 0xf7, 0x10, 0xf3, 0x3d,
+	0xc4, 0x7c, 0x0f, 0x31, 0xdf, 0x43, 0xcc, 0xf7, 0x10, 0xf3, 0xbd, 0xf1,
+	0x30, 0x4f, 0x7b, 0x62, 0x3d, 0x4f, 0x5b, 0xa9, 0xf3, 0x3b, 0x94, 0xa2,
+	0xa5, 0x58, 0x94, 0x20, 0xcf, 0x15, 0x9d, 0x39, 0x4d, 0x94, 0xe7, 0x5e,
+	0xfb, 0x9b, 0x48, 0xb0, 0x8e, 0x39, 0x1e, 0xd7, 0x15, 0x35, 0xdd, 0xe6,
+	0xba, 0x20, 0xcf, 0x63, 0x6d, 0xb5, 0x79, 0x0d, 0xf2, 0xb5, 0x0c, 0xfd,
+	0x19, 0xed, 0x22, 0x11, 0xd4, 0x8b, 0x99, 0xf3, 0xf7, 0xba, 0x88, 0xbf,
+	0x85, 0x9a, 0x8a, 0xc1, 0xbc, 0x17, 0xbc, 0x97, 0x7f, 0xb7, 0x00, 0x39,
+	0xf0, 0xdd, 0x7d, 0xac, 0x27, 0x0a, 0xb5, 0xa4, 0x14, 0x17, 0xa3, 0xfc,
+	0x07, 0xeb, 0xbc, 0x7d, 0x5a, 0xbe, 0x42, 0xd9, 0xea, 0x32, 0x9d, 0x00,
+	0x53, 0xec, 0xc6, 0xbc, 0xee, 0x4d, 0x55, 0x23, 0xad, 0xd4, 0x49, 0xcf,
+	0x7e, 0xd0, 0x16, 0xdd, 0xe3, 0x8a, 0x18, 0xb3, 0x09, 0xd1, 0x67, 0x91,
+	0xd3, 0xda, 0x43, 0xea, 0x6f, 0x1d, 0x7a, 0xb0, 0x8f, 0x3e, 0x3b, 0x10,
+	0xfd, 0x2d, 0x06, 0xeb, 0xae, 0xec, 0xc6, 0xfd, 0x2b, 0xcf, 0x91, 0x80,
+	0xbd, 0x7e, 0x69, 0x27, 0xce, 0x06, 0xb9, 0x5e, 0xde, 0xa1, 0xf2, 0x6e,
+	0xf8, 0xce, 0xd3, 0x43, 0xe9, 0x3e, 0xe9, 0xda, 0x25, 0x67, 0x86, 0x58,
+	0xa3, 0xb5, 0x01, 0x1f, 0x61, 0x79, 0xe7, 0xb4, 0x4b, 0x96, 0xe7, 0xe1,
+	0x5b, 0xe7, 0xd3, 0x0e, 0xff, 0xbe, 0x60, 0x01, 0x21, 0x6d, 0xa1, 0x3e,
+	0xd6, 0xc7, 0x98, 0xbc, 0x58, 0xa7, 0xae, 0xf4, 0x60, 0x7d, 0x3f, 0x74,
+	0x71, 0x1b, 0x6c, 0x48, 0xc7, 0xfe, 0x11, 0xee, 0xf7, 0x14, 0xee, 0x1e,
+	0xfb, 0xb7, 0x77, 0x2a, 0xdd, 0xd0, 0xd3, 0x56, 0x4a, 0x07, 0xed, 0x1f,
+	0xab, 0x2d, 0x1d, 0xe1, 0xf7, 0xc2, 0x69, 0xaf, 0xf1, 0xbb, 0xe1, 0x3e,
+	0xad, 0x50, 0xe1, 0xdf, 0x38, 0x0c, 0xc9, 0x21, 0x8b, 0x7f, 0xff, 0xb3,
+	0x4f, 0x7b, 0xa0, 0x4a, 0x18, 0x1b, 0x7d, 0xd6, 0xe1, 0xcb, 0xb0, 0xe5,
+	0xff, 0x29, 0xdc, 0xea, 0x62, 0xdb, 0x3a, 0xcb, 0xf0, 0xfb, 0x1d, 0xe7,
+	0xc7, 0x4d, 0xdd, 0xe4, 0x34, 0x71, 0x12, 0x27, 0xca, 0xc0, 0xc7, 0x39,
+	0x49, 0x3d, 0x39, 0xd5, 0x4e, 0xa2, 0x14, 0x22, 0x88, 0x84, 0xe5, 0xfc,
+	0xcc, 0x63, 0x14, 0x3c, 0xc8, 0xa6, 0x4e, 0x42, 0x55, 0x94, 0x74, 0x5b,
+	0x27, 0xee, 0xb8, 0x40, 0x5c, 0x80, 0x6a, 0x39, 0x69, 0xe9, 0x86, 0x3d,
+	0xa7, 0x5b, 0xba, 0x00, 0x57, 0x9e, 0xe3, 0xa4, 0x4d, 0xe7, 0xcc, 0x1a,
+	0x03, 0x69, 0x70, 0x41, 0x23, 0x33, 0x6d, 0xe3, 0x66, 0x37, 0x48, 0x5c,
+	0x57, 0x29, 0x83, 0x02, 0x6b, 0x2b, 0xb8, 0xe1, 0xef, 0xe2, 0xf0, 0x3c,
+	0xdf, 0x39, 0x76, 0xd3, 0xc0, 0x44, 0x24, 0xeb, 0x7c, 0xe7, 0x3b, 0xdf,
+	0xff, 0xf7, 0xbe, 0xcf, 0xfb, 0x9b, 0x6e, 0xb9, 0x08, 0x3a, 0xce, 0x8d,
+	0xb5, 0xfa, 0xfe, 0xd6, 0x0e, 0x9f, 0x87, 0x07, 0xfb, 0x7c, 0x19, 0xa5,
+	0x75, 0xc9, 0x9c, 0xd6, 0xa7, 0xbb, 0x0e, 0x7d, 0x7b, 0x16, 0x6b, 0x8a,
+	0xe0, 0x1c, 0x1e, 0xe9, 0xd3, 0x78, 0x64, 0xf0, 0xbd, 0xff, 0xd0, 0x7b,
+	0xdf, 0xa1, 0xf7, 0xde, 0xff, 0xd1, 0x9e, 0xe5, 0xc3, 0xf4, 0xc0, 0x75,
+	0x5a, 0x53, 0x1a, 0xfd, 0xf2, 0x93, 0x6a, 0x39, 0x6f, 0x25, 0xa9, 0x0b,
+	0xcc, 0x88, 0xab, 0x66, 0x9c, 0x36, 0x60, 0x5c, 0x9b, 0xac, 0xae, 0x83,
+	0xe6, 0xb1, 0x8f, 0x76, 0x9b, 0xf1, 0xf2, 0x89, 0x3e, 0xf2, 0x4c, 0x10,
+	0xd7, 0x60, 0xd8, 0xc3, 0x11, 0xb4, 0x73, 0x5f, 0x74, 0x12, 0xe6, 0x39,
+	0xed, 0xbf, 0xa1, 0x0e, 0xe3, 0xaa, 0x9c, 0xce, 0xfd, 0x60, 0x9b, 0x16,
+	0xb9, 0x6d, 0xa7, 0xba, 0xfd, 0xdc, 0x20, 0xd8, 0xbb, 0xa9, 0x3e, 0xea,
+	0x17, 0x2f, 0x38, 0xcd, 0x3a, 0x73, 0x5f, 0x98, 0x77, 0x05, 0xa2, 0x79,
+	0x4a, 0xa4, 0x54, 0x11, 0xb9, 0x86, 0xdf, 0x6f, 0x2a, 0x7e, 0xfc, 0x42,
+	0xd1, 0xd6, 0x9e, 0x96, 0x1b, 0xc5, 0x2f, 0x48, 0x15, 0x32, 0x67, 0xc7,
+	0x71, 0xdd, 0x3b, 0x4e, 0x54, 0x9f, 0xf9, 0x0f, 0xf2, 0x4a, 0x62, 0xe3,
+	0x94, 0x69, 0x6d, 0xf2, 0xc3, 0x75, 0xe6, 0xd5, 0x59, 0xe6, 0x1d, 0x61,
+	0x7e, 0x5b, 0x44, 0xd2, 0xe1, 0x80, 0xd6, 0x4b, 0xe5, 0x69, 0x68, 0x12,
+	0xf8, 0xf6, 0x87, 0xf5, 0xb3, 0x7d, 0xf4, 0xb9, 0x7c, 0xbc, 0xce, 0x77,
+	0x03, 0x4f, 0x43, 0xea, 0x76, 0x00, 0xfa, 0x2b, 0x80, 0xc7, 0xe4, 0xb9,
+	0x73, 0xbf, 0xcf, 0x73, 0x6d, 0xa8, 0xa3, 0x0d, 0xdb, 0x26, 0xb9, 0x11,
+	0xe0, 0xa0, 0x1a, 0xd6, 0xf9, 0x47, 0xf5, 0xb0, 0xc6, 0xe5, 0x40, 0x99,
+	0x7e, 0x7b, 0xf3, 0xa8, 0xc6, 0xe8, 0xd4, 0xee, 0xf7, 0xf4, 0x5e, 0x50,
+	0xce, 0x96, 0x1d, 0xd2, 0xaa, 0x29, 0x3b, 0xe0, 0xb5, 0xeb, 0xb5, 0x37,
+	0xfa, 0x79, 0x57, 0x37, 0x6a, 0xdf, 0xef, 0xf3, 0x6c, 0x34, 0xd6, 0x5d,
+	0xe8, 0xf3, 0xea, 0xa2, 0xbe, 0xcd, 0x45, 0xdb, 0xac, 0x84, 0xbd, 0x7d,
+	0x5b, 0x6a, 0x1b, 0xdf, 0x95, 0x77, 0x8b, 0xdf, 0x91, 0x5f, 0x6c, 0x9c,
+	0x81, 0xce, 0x61, 0x95, 0xb2, 0x90, 0x27, 0x6f, 0xd7, 0x5c, 0xf7, 0x6d,
+	0x67, 0x01, 0xf6, 0x81, 0xeb, 0xfe, 0xd6, 0xd9, 0x93, 0xd8, 0xc4, 0x37,
+	0xb1, 0xe7, 0x0c, 0x78, 0x88, 0x58, 0x98, 0x06, 0xbd, 0x7d, 0xb1, 0x5f,
+	0x3a, 0x42, 0x9a, 0x4e, 0x86, 0x27, 0x5a, 0xb1, 0x07, 0xc3, 0xd7, 0xc3,
+	0xb9, 0x97, 0xe9, 0x7e, 0xd2, 0x8c, 0x51, 0xfb, 0x09, 0xe6, 0x6f, 0x05,
+	0x5f, 0x1c, 0xc5, 0x4f, 0xc9, 0x9d, 0x71, 0xac, 0x75, 0x9c, 0xb4, 0xd7,
+	0x2a, 0xb1, 0xc7, 0xb0, 0x8f, 0x4c, 0x8b, 0xdc, 0xcb, 0x6f, 0xf6, 0xd1,
+	0x9f, 0x77, 0x2f, 0xcf, 0xb2, 0xf1, 0xb9, 0x4e, 0x71, 0xa5, 0x05, 0xf2,
+	0x7b, 0x75, 0xd2, 0xd3, 0x95, 0x7e, 0xad, 0x4e, 0xa0, 0xbd, 0x9d, 0x7d,
+	0x4f, 0x51, 0xb7, 0xcb, 0xba, 0xad, 0xd0, 0xc5, 0xe7, 0xa0, 0x03, 0xa5,
+	0x6a, 0x17, 0xa4, 0x3e, 0x1e, 0x42, 0x1b, 0xea, 0x28, 0x1a, 0x4b, 0x64,
+	0x26, 0xcf, 0x7c, 0x2d, 0xe6, 0x4e, 0x61, 0x8d, 0x0b, 0xc4, 0x0d, 0xae,
+	0xb1, 0x8d, 0x31, 0x38, 0xbf, 0xce, 0x06, 0x8d, 0xb0, 0x8e, 0xf4, 0x9d,
+	0x04, 0x4f, 0x26, 0x29, 0x37, 0x31, 0xde, 0x18, 0xc6, 0x63, 0xb9, 0x13,
+	0xe3, 0x5d, 0x90, 0x94, 0xd3, 0x18, 0x73, 0x0a, 0x6d, 0x88, 0x33, 0x53,
+	0xd0, 0x1f, 0x86, 0xd4, 0xec, 0x7a, 0x18, 0xf2, 0xbb, 0x4f, 0x66, 0xcd,
+	0x23, 0x07, 0xf6, 0x98, 0xd5, 0xf6, 0x81, 0x61, 0x8c, 0xf9, 0x6b, 0xea,
+	0x3c, 0xb0, 0x26, 0xf6, 0xc7, 0x0f, 0xb6, 0x71, 0x6a, 0x7d, 0x0d, 0x38,
+	0xb5, 0xf6, 0x61, 0xca, 0x39, 0x2b, 0x33, 0x61, 0xae, 0x89, 0xf5, 0x61,
+	0xac, 0x99, 0x7e, 0xac, 0x67, 0x81, 0x43, 0x47, 0xfc, 0x3a, 0xb6, 0x15,
+	0x23, 0x85, 0xb3, 0xf7, 0xec, 0x5a, 0xd6, 0x7d, 0x56, 0x52, 0x6b, 0x19,
+	0x99, 0xd7, 0xfd, 0x78, 0x86, 0x83, 0x5a, 0xf7, 0x20, 0xaf, 0xc6, 0x7a,
+	0x70, 0x96, 0x89, 0x07, 0x36, 0x70, 0xb4, 0x47, 0xcb, 0xcc, 0x7e, 0x8f,
+	0x67, 0xf1, 0xad, 0x87, 0x77, 0xd4, 0x26, 0xb1, 0x6f, 0x40, 0x46, 0xe6,
+	0x1b, 0xf5, 0x21, 0xf9, 0x24, 0xdf, 0xd1, 0xcf, 0x38, 0xcb, 0xdd, 0xbc,
+	0x29, 0x1f, 0xe7, 0x75, 0x2c, 0x74, 0x31, 0x20, 0xd6, 0x79, 0xcf, 0x3e,
+	0x1f, 0x59, 0x5c, 0x55, 0xfc, 0x3e, 0x72, 0x7e, 0x4b, 0x05, 0xd1, 0x36,
+	0x84, 0x76, 0x5c, 0x87, 0x29, 0x73, 0xf9, 0xbf, 0xb9, 0x4b, 0xa3, 0xae,
+	0x3b, 0xaf, 0xf3, 0xc3, 0x12, 0xe6, 0xaa, 0x6a, 0xe8, 0xe4, 0x71, 0xc9,
+	0x87, 0xdb, 0x31, 0x57, 0xc2, 0xdc, 0x52, 0x23, 0x58, 0x0f, 0xcb, 0x3d,
+	0xe4, 0x89, 0xc8, 0x9e, 0x70, 0x7c, 0x2b, 0xbd, 0xa9, 0x12, 0xd1, 0x61,
+	0x65, 0x25, 0x73, 0xf8, 0xb5, 0x28, 0x1d, 0x47, 0x8c, 0x44, 0x15, 0x78,
+	0x17, 0x7b, 0xb2, 0x4f, 0xba, 0x6e, 0xda, 0x66, 0x7d, 0xc2, 0x0c, 0x29,
+	0xfa, 0x5b, 0x3a, 0x74, 0xbc, 0xf1, 0x72, 0x6f, 0xc2, 0x3c, 0xa9, 0x8e,
+	0xfb, 0xef, 0x53, 0xc0, 0xcc, 0xe6, 0x78, 0x67, 0x36, 0x95, 0x29, 0x2f,
+	0xe5, 0x13, 0xd1, 0x65, 0x65, 0x65, 0x30, 0x66, 0x66, 0x56, 0x11, 0x37,
+	0x12, 0x66, 0x87, 0xa2, 0x4f, 0xb4, 0x5d, 0xef, 0x3b, 0x8d, 0xfe, 0x09,
+	0xd5, 0xe2, 0xaf, 0x87, 0xf7, 0xf5, 0xe3, 0x7e, 0x8f, 0x67, 0x88, 0x39,
+	0xa3, 0xc0, 0x4c, 0xe6, 0x9a, 0xe9, 0xdc, 0x86, 0x64, 0x6c, 0x62, 0x54,
+	0x63, 0xe8, 0xfd, 0x53, 0x7f, 0x47, 0x1d, 0xca, 0x25, 0xd6, 0xc5, 0x7d,
+	0x7e, 0x1b, 0xd5, 0x3a, 0xf3, 0xfd, 0x53, 0x59, 0x9d, 0xc7, 0x58, 0x57,
+	0x31, 0x7f, 0xdf, 0xcd, 0x3b, 0x8b, 0xa6, 0x9c, 0x47, 0x38, 0xce, 0x5a,
+	0x60, 0xba, 0x5d, 0x98, 0x23, 0x3a, 0x57, 0x6c, 0xd0, 0x06, 0xfd, 0x01,
+	0xcc, 0x17, 0x68, 0xc4, 0xbd, 0x2f, 0x88, 0x31, 0x11, 0x3c, 0x40, 0x27,
+	0xd0, 0x35, 0xa1, 0xa3, 0x56, 0x30, 0x4e, 0x6e, 0x5d, 0xb2, 0x5e, 0x7f,
+	0x09, 0x32, 0x27, 0x35, 0x57, 0xf9, 0xb4, 0x31, 0x38, 0x37, 0xe6, 0xc0,
+	0xfb, 0xfd, 0x53, 0xa4, 0x4f, 0x9e, 0x4d, 0x54, 0xcd, 0x6d, 0x70, 0x3d,
+	0x83, 0x32, 0xbf, 0x3e, 0x24, 0xcb, 0xf8, 0xad, 0xae, 0x7b, 0xf7, 0xb6,
+	0x0d, 0xdd, 0x7a, 0x3e, 0x6f, 0x6a, 0x7e, 0x5d, 0x76, 0x18, 0x33, 0x01,
+	0xaf, 0xe8, 0x9c, 0x2a, 0xf6, 0x65, 0x5e, 0xe1, 0x10, 0xe5, 0xa3, 0x53,
+	0x87, 0x5c, 0xdd, 0xae, 0x51, 0x4f, 0x65, 0xbd, 0x35, 0x15, 0x0d, 0x74,
+	0xc9, 0x2a, 0xf0, 0xae, 0x0c, 0xd9, 0x99, 0x7b, 0x25, 0x24, 0xcb, 0x79,
+	0x1d, 0x4f, 0x8e, 0xfe, 0x5e, 0x39, 0x52, 0xad, 0x4d, 0xca, 0x6e, 0x2d,
+	0xae, 0xbf, 0x51, 0xae, 0xe5, 0x5e, 0x37, 0xe4, 0xf9, 0x51, 0x9d, 0x57,
+	0x17, 0x2f, 0x4b, 0xef, 0x00, 0x75, 0x9e, 0x2d, 0x9d, 0x63, 0x07, 0xec,
+	0x80, 0xce, 0xf1, 0x33, 0xe8, 0x1c, 0xef, 0x40, 0xe7, 0xf8, 0x69, 0x11,
+	0xf8, 0x52, 0x4c, 0xfb, 0xf8, 0xbf, 0x08, 0x1c, 0xa2, 0xac, 0xb6, 0xce,
+	0xe0, 0x4e, 0x17, 0xb3, 0xa0, 0xc1, 0x5b, 0x92, 0x06, 0xde, 0xa6, 0xe4,
+	0xfa, 0xc6, 0xbc, 0xec, 0x6c, 0x78, 0x79, 0xc8, 0x1f, 0x30, 0x07, 0x6c,
+	0x9c, 0xf7, 0x14, 0x07, 0x0e, 0x1d, 0x91, 0xd8, 0x49, 0xe2, 0x47, 0x50,
+	0x36, 0x0b, 0xef, 0x68, 0x1c, 0xda, 0x2c, 0xb0, 0x1c, 0x10, 0x9d, 0x4f,
+	0xb6, 0xb0, 0x27, 0x65, 0xe7, 0x97, 0xa8, 0x3f, 0xa6, 0x7d, 0x40, 0x9e,
+	0x4f, 0x9e, 0x78, 0xf9, 0x67, 0xff, 0xee, 0x95, 0xce, 0xb3, 0x5b, 0x32,
+	0xbb, 0xd0, 0xae, 0x81, 0x5d, 0xc3, 0x5e, 0xcc, 0x5b, 0xfd, 0x05, 0x6d,
+	0x30, 0x47, 0xb1, 0x4b, 0xb6, 0x21, 0x43, 0xea, 0xf1, 0x2e, 0xad, 0xfb,
+	0xd5, 0xe3, 0x43, 0x3a, 0x17, 0x97, 0xe3, 0xe4, 0x0a, 0xb6, 0xac, 0x14,
+	0xac, 0x68, 0x16, 0xf4, 0xb7, 0x0b, 0x5b, 0xed, 0x3a, 0xee, 0x60, 0x07,
+	0x67, 0x70, 0xa3, 0x46, 0x39, 0x7f, 0x57, 0x63, 0xef, 0x66, 0xed, 0x4f,
+	0x18, 0xc7, 0x3a, 0x93, 0x94, 0x3f, 0xf6, 0x13, 0x03, 0xe9, 0x8f, 0x9a,
+	0xd1, 0xfd, 0xbd, 0x7e, 0xd7, 0xd1, 0x76, 0xa7, 0x46, 0x3c, 0x16, 0xb9,
+	0x94, 0xb7, 0x21, 0x4b, 0x5e, 0x8f, 0x50, 0x07, 0x28, 0xa9, 0x46, 0x3f,
+	0xd7, 0x5f, 0xb3, 0xeb, 0x1e, 0xb5, 0xb9, 0xae, 0xb8, 0x8f, 0xdb, 0x94,
+	0xfd, 0x7b, 0x5a, 0xee, 0xe7, 0x8b, 0x67, 0xe5, 0x2d, 0xdc, 0xb7, 0xa7,
+	0xe3, 0x64, 0xe4, 0x4d, 0xe8, 0x78, 0xb5, 0x62, 0x23, 0x6f, 0x7b, 0x1a,
+	0xe7, 0x64, 0xa9, 0x95, 0x2b, 0x2f, 0xcb, 0xe5, 0xab, 0xfb, 0xea, 0xa5,
+	0xab, 0x31, 0xf5, 0xf2, 0x95, 0x61, 0x95, 0xbb, 0xe2, 0xba, 0xff, 0x74,
+	0x96, 0xe4, 0xdd, 0x0d, 0x57, 0x4e, 0x3b, 0xc6, 0x40, 0x40, 0x1a, 0xb9,
+	0x75, 0xae, 0x1b, 0x04, 0x36, 0xdf, 0xe8, 0x75, 0xdd, 0x47, 0xc7, 0xc7,
+	0x25, 0xde, 0x4b, 0x1d, 0xe5, 0xf3, 0x11, 0xe6, 0xbb, 0x12, 0x73, 0x52,
+	0xb6, 0x7d, 0xbe, 0xac, 0x14, 0xf0, 0xad, 0xcb, 0xd3, 0x5f, 0x1e, 0x3b,
+	0xe6, 0xc7, 0x4a, 0x7e, 0xf4, 0x22, 0x7d, 0xc9, 0x91, 0xff, 0xf2, 0x25,
+	0x9b, 0x72, 0xae, 0xf0, 0x19, 0xf4, 0x0f, 0xcb, 0xb7, 0x0a, 0xa1, 0x43,
+	0x65, 0x13, 0xcf, 0x31, 0x95, 0x2b, 0xdc, 0x73, 0x87, 0x75, 0xcc, 0x00,
+	0x3a, 0x89, 0xe9, 0xba, 0xcb, 0x0e, 0xe7, 0xeb, 0xc2, 0x7c, 0x7b, 0xe6,
+	0x31, 0xc8, 0xff, 0xd3, 0x5a, 0x3e, 0x9f, 0x53, 0xb0, 0x7d, 0xc1, 0xdf,
+	0x61, 0x99, 0x2d, 0x40, 0xc6, 0x2b, 0xe6, 0x9c, 0x52, 0x57, 0xb0, 0x22,
+	0xcb, 0xc0, 0x8e, 0x25, 0xe0, 0xcd, 0x93, 0x3a, 0xb6, 0xda, 0xa3, 0xb1,
+	0x67, 0x85, 0xe5, 0x8c, 0x24, 0xcb, 0x4e, 0xb7, 0x3e, 0xbf, 0xfd, 0xdd,
+	0x57, 0x23, 0xde, 0x9d, 0x83, 0x8f, 0x33, 0x4a, 0xda, 0x60, 0x03, 0xcd,
+	0x6c, 0x2d, 0x80, 0x27, 0x22, 0x38, 0xdb, 0x56, 0xcd, 0x0f, 0x75, 0xc8,
+	0xef, 0xba, 0xf6, 0x23, 0x7a, 0xf1, 0x8a, 0xba, 0xc9, 0x76, 0xcf, 0xa0,
+	0x5f, 0xbb, 0xa4, 0xae, 0xb4, 0x69, 0x5c, 0x7d, 0xb8, 0x2e, 0x09, 0x3d,
+	0xe4, 0x69, 0x94, 0x03, 0xa8, 0x8b, 0xfa, 0x65, 0x03, 0xe5, 0x45, 0x94,
+	0x5b, 0xf0, 0x64, 0x9b, 0x11, 0xe8, 0x15, 0x78, 0xbe, 0x81, 0xf1, 0xc6,
+	0xb1, 0xe6, 0x8c, 0x29, 0x1f, 0x9d, 0xa2, 0x2c, 0x19, 0x53, 0xcc, 0x4b,
+	0x5e, 0xb6, 0xf1, 0xac, 0x0e, 0xab, 0x99, 0x35, 0x96, 0xf1, 0x2c, 0x79,
+	0xdf, 0x1f, 0xc2, 0x24, 0xf4, 0x49, 0x5d, 0xf5, 0x30, 0xe9, 0xa3, 0x26,
+	0x26, 0xb1, 0xae, 0x5d, 0x66, 0xaf, 0x90, 0xd7, 0x4d, 0xd0, 0x5b, 0x87,
+	0xcc, 0x5c, 0x0d, 0x6b, 0x7d, 0xb4, 0x0c, 0x5a, 0xdc, 0x06, 0x5d, 0x6d,
+	0x82, 0xa6, 0x52, 0x05, 0x6b, 0x6a, 0x51, 0x45, 0xb5, 0x2f, 0xe0, 0x09,
+	0xd0, 0x6b, 0xf0, 0x15, 0xea, 0xa2, 0xe4, 0xe5, 0x38, 0x68, 0x4f, 0xdc,
+	0xa0, 0x6d, 0xa7, 0xe3, 0xca, 0x06, 0x0d, 0x82, 0x2e, 0x0b, 0x1e, 0x4f,
+	0xbf, 0xa7, 0x34, 0xae, 0x4e, 0xdd, 0x96, 0x44, 0xf2, 0xb6, 0x58, 0xc0,
+	0x02, 0xcb, 0xf9, 0x50, 0x1c, 0x8c, 0x39, 0x29, 0xd7, 0x30, 0x8f, 0x01,
+	0xfe, 0x1e, 0x3d, 0xa1, 0xf9, 0x7b, 0x4a, 0x02, 0x87, 0x79, 0x1c, 0xf4,
+	0x06, 0x0c, 0xf2, 0x78, 0x3a, 0xe9, 0xd3, 0xe8, 0xd7, 0xc1, 0xbf, 0x16,
+	0x2c, 0xb1, 0xb0, 0xac, 0x82, 0xff, 0xb7, 0xf1, 0xfd, 0x66, 0x6d, 0x44,
+	0xad, 0xac, 0x29, 0x3f, 0x97, 0xe4, 0x19, 0xe8, 0xc9, 0xb7, 0x70, 0x76,
+	0x9d, 0x5a, 0x77, 0x8f, 0x8d, 0x33, 0x7e, 0x96, 0x56, 0x97, 0xed, 0x93,
+	0xb2, 0x3f, 0x36, 0x89, 0xf2, 0x31, 0x3c, 0x0d, 0x9c, 0x43, 0x48, 0xc7,
+	0xbf, 0x37, 0xf3, 0x8e, 0xf2, 0xfe, 0x67, 0x61, 0x42, 0xe7, 0xe7, 0x1b,
+	0x76, 0x2f, 0xbe, 0xd3, 0x17, 0xc3, 0xbd, 0x41, 0x67, 0x52, 0x11, 0x9d,
+	0x6f, 0x5a, 0x86, 0x2e, 0xb1, 0x85, 0xf1, 0xde, 0xa7, 0x2f, 0xaf, 0x0a,
+	0x1e, 0x1e, 0xfb, 0x97, 0x9b, 0x0c, 0x33, 0x47, 0xfd, 0x6e, 0xc4, 0x93,
+	0x7f, 0x9f, 0xb8, 0xfb, 0xf6, 0xca, 0x94, 0x81, 0x97, 0x5b, 0x66, 0x18,
+	0x6d, 0x21, 0xcb, 0x20, 0x8b, 0x4a, 0x9a, 0x7e, 0xd9, 0xce, 0xeb, 0x9b,
+	0xab, 0x26, 0xcc, 0x0f, 0xc4, 0xeb, 0xbb, 0x6a, 0x53, 0xee, 0xb4, 0x03,
+	0x5f, 0xa2, 0x5a, 0xaf, 0x7c, 0xdf, 0xce, 0x02, 0x15, 0xac, 0x68, 0x1a,
+	0x34, 0xda, 0x26, 0x56, 0x7c, 0x4e, 0x1e, 0xcc, 0xbb, 0xac, 0xfb, 0xb2,
+	0x6d, 0xa3, 0x6f, 0x63, 0x5e, 0xae, 0x9f, 0x7b, 0xe1, 0x1e, 0xe8, 0x9b,
+	0x36, 0x35, 0x8d, 0xd6, 0xab, 0xdd, 0x03, 0x1e, 0x8d, 0x36, 0xf6, 0x11,
+	0xfe, 0x3f, 0xfb, 0x20, 0x9d, 0x38, 0xca, 0xcb, 0xbb, 0xc0, 0xb3, 0xca,
+	0xf3, 0x1c, 0x01, 0x6d, 0x1c, 0xa4, 0x9f, 0x86, 0x6f, 0xd1, 0xa3, 0x9f,
+	0x47, 0x9b, 0xf4, 0x43, 0xba, 0xe9, 0x90, 0xd9, 0xab, 0xb6, 0xcc, 0x17,
+	0xf4, 0x7d, 0x43, 0xd7, 0xa4, 0xcf, 0x68, 0x12, 0x74, 0x43, 0x5a, 0x27,
+	0x6f, 0x99, 0x52, 0x02, 0x1d, 0x95, 0x80, 0x4f, 0x25, 0xd0, 0x54, 0x19,
+	0xf8, 0x56, 0x02, 0xbe, 0x95, 0x6a, 0x56, 0xbc, 0x82, 0x3d, 0x53, 0x66,
+	0x6f, 0x81, 0x8e, 0xb6, 0x6b, 0xbc, 0x7f, 0xbd, 0x66, 0x93, 0x72, 0xf0,
+	0x66, 0xf3, 0xee, 0xff, 0x81, 0xbb, 0x1f, 0x92, 0x5d, 0xd8, 0x2d, 0x6f,
+	0x15, 0xc7, 0x80, 0x49, 0x02, 0x8c, 0x72, 0x40, 0x1b, 0x53, 0x72, 0xbd,
+	0x38, 0x2d, 0x3b, 0x90, 0x4f, 0x37, 0x36, 0x62, 0xd0, 0xa7, 0x23, 0xb2,
+	0xf2, 0xda, 0xa8, 0xbc, 0xb9, 0xa1, 0x64, 0x09, 0xf4, 0x9b, 0xdb, 0xa4,
+	0xdf, 0x1d, 0xf4, 0x5c, 0xea, 0xd0, 0x71, 0xfa, 0xd9, 0x8a, 0xe7, 0x7f,
+	0x9f, 0xab, 0x74, 0xca, 0x7c, 0xc5, 0x94, 0xc7, 0x2b, 0xdd, 0xf2, 0xe5,
+	0x4a, 0x58, 0x4e, 0xc3, 0x0e, 0xfc, 0x4a, 0x65, 0x50, 0x9e, 0xac, 0x0c,
+	0xc9, 0x57, 0xab, 0x51, 0xf9, 0x5a, 0xd5, 0x96, 0x4c, 0x35, 0x2e, 0xe9,
+	0xea, 0x98, 0x3c, 0x51, 0xa5, 0x5f, 0x1d, 0xf3, 0xe1, 0x37, 0xd3, 0xf4,
+	0x57, 0x70, 0x5d, 0x41, 0xac, 0x2b, 0xae, 0xe6, 0x74, 0x9c, 0x52, 0x32,
+	0x9e, 0xcf, 0x43, 0xe4, 0x39, 0x8c, 0x75, 0xf1, 0x35, 0x25, 0x65, 0x3d,
+	0x7f, 0xe3, 0xff, 0x46, 0x42, 0xda, 0x36, 0x7a, 0xae, 0x34, 0x88, 0x36,
+	0x90, 0x7b, 0xf9, 0x86, 0xef, 0xa3, 0xe1, 0xf3, 0x6f, 0xd8, 0x5e, 0x86,
+	0xf6, 0x5b, 0xdf, 0xa4, 0xed, 0xa5, 0xcf, 0x9e, 0xf8, 0x41, 0x3b, 0xe7,
+	0x9a, 0xf6, 0x9b, 0x3c, 0x88, 0x6d, 0x34, 0xe6, 0xbd, 0x98, 0x79, 0xf8,
+	0xff, 0x53, 0xbc, 0x18, 0xd5, 0xb9, 0xea, 0x20, 0xff, 0x4f, 0x05, 0x6b,
+	0xf9, 0xf4, 0xdc, 0xf1, 0xf9, 0xe2, 0xac, 0x7a, 0xbc, 0x48, 0x8d, 0xc6,
+	0x95, 0x8b, 0xcd, 0x9c, 0xb8, 0x2f, 0xc9, 0xa6, 0x13, 0xd2, 0x6b, 0xf0,
+	0xf3, 0x1f, 0x75, 0x7e, 0xdc, 0xec, 0x09, 0xd2, 0x1f, 0x63, 0x6f, 0x9d,
+	0x7e, 0x3c, 0x01, 0xba, 0xad, 0x63, 0xca, 0xa5, 0x8a, 0xe7, 0xb3, 0x5a,
+	0xd1, 0xf4, 0xf2, 0x2b, 0xd0, 0x1c, 0x63, 0x0e, 0xde, 0x33, 0x5b, 0xf2,
+	0xfa, 0xce, 0xe0, 0xde, 0x60, 0x8f, 0x63, 0xbf, 0x46, 0x37, 0xe7, 0xe2,
+	0xff, 0xe9, 0xa0, 0xec, 0xaf, 0x97, 0xb9, 0xc6, 0xb6, 0xa6, 0x45, 0x2f,
+	0xae, 0x1b, 0x97, 0x17, 0x70, 0x7e, 0x65, 0x93, 0xeb, 0x0f, 0x4a, 0x39,
+	0x4e, 0xdb, 0x96, 0xf8, 0x7d, 0x42, 0x4a, 0x98, 0xa7, 0x1c, 0x6f, 0xf8,
+	0xc3, 0x3c, 0x9c, 0x2d, 0x9b, 0x0f, 0xe6, 0x5d, 0x2c, 0x1d, 0xc7, 0x3b,
+	0xea, 0xe2, 0xd0, 0x99, 0x16, 0xf8, 0x7e, 0x11, 0x65, 0xfa, 0x46, 0x56,
+	0xf0, 0x8c, 0xf8, 0x75, 0xd5, 0x01, 0xad, 0xab, 0x4f, 0x3f, 0xe8, 0xb7,
+	0x54, 0xb2, 0xb2, 0xa9, 0x40, 0x42, 0x19, 0xaf, 0xfe, 0x7c, 0x80, 0x98,
+	0x7b, 0xdc, 0xe6, 0x2f, 0x24, 0x7f, 0x35, 0xb5, 0x4f, 0xc1, 0xff, 0x76,
+	0x44, 0x9e, 0x32, 0x99, 0xc7, 0x9e, 0x54, 0xb3, 0xc5, 0x9c, 0x9f, 0xe3,
+	0x9b, 0x50, 0xc7, 0xcb, 0x37, 0x07, 0xbc, 0x9c, 0x77, 0x8e, 0x7d, 0x30,
+	0xcf, 0xfd, 0x20, 0x9d, 0x30, 0xdf, 0xbd, 0xbd, 0xf9, 0x3f, 0x52, 0xe5,
+	0x3c, 0xf0, 0xce, 0x6e, 0xd1, 0xfc, 0x98, 0xab, 0xfe, 0xdb, 0xdd, 0xd3,
+	0xfc, 0xdc, 0xf0, 0x31, 0xfc, 0x6e, 0x80, 0xb6, 0x2d, 0x71, 0xe3, 0x92,
+	0x97, 0x3b, 0xaa, 0x6d, 0x68, 0x60, 0x05, 0xea, 0xc8, 0xab, 0xe0, 0x93,
+	0x66, 0x5b, 0xfe, 0xfd, 0x07, 0x69, 0x3f, 0x51, 0x42, 0x6c, 0x67, 0x00,
+	0x00, 0x00 };
+
+static const u32 bnx2_RXP_b09FwData[(0x0/4) + 1] = { 0x0 };
+static const u32 bnx2_RXP_b09FwRodata[(0x278/4) + 1] = {
+	0x08004050, 0x08003f50, 0x08003ff4, 0x0800400c, 0x08004024, 0x08004044,
+	0x08004050, 0x08004050, 0x08003f58, 0x00000000, 0x08004a0c, 0x08004a44,
+	0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004a7c, 0x08004c40,
+	0x08004b88, 0x08004bc0, 0x08004c40, 0x08004b10, 0x08004c40, 0x08004c40,
+	0x08004bc0, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40,
+	0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c00,
+	0x08004c40, 0x08004c00, 0x08004b88, 0x08004c40, 0x08004c40, 0x08004c00,
+	0x08004c00, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40,
+	0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40,
+	0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40,
+	0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40,
+	0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40,
+	0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40,
+	0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40,
+	0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40,
+	0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40,
+	0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40,
+	0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40,
+	0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40,
+	0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40,
+	0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40,
+	0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40,
+	0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40,
+	0x08004aec, 0x00000000, 0x08006058, 0x08006070, 0x08006070, 0x08006070,
+	0x08006058, 0x08006070, 0x08006070, 0x08006070, 0x08006058, 0x08006070,
+	0x08006070, 0x08006070, 0x08006058, 0x08006070, 0x08006070, 0x08006070,
+	0x08006064, 0x00000000, 0x00000000 };
+static const u32 bnx2_RXP_b09FwBss[(0x13dc/4) + 1] = { 0x0 };
+static const u32 bnx2_RXP_b09FwSbss[(0x20/4) + 1] = { 0x0 };
 
 static struct fw_info bnx2_rxp_fw_09 = {
-	.ver_major			= 0x1,
-	.ver_minor			= 0x0,
-	.ver_fix			= 0x0,
+	.ver_major			= 0x3,
+	.ver_minor			= 0x4,
+	.ver_fix			= 0x3,
 
 	.start_addr			= 0x08003184,
 
 	.text_addr			= 0x08000000,
-	.text_len			= 0x673c,
+	.text_len			= 0x6768,
 	.text_index			= 0x0,
 	.gz_text			= bnx2_RXP_b09FwText,
 	.gz_text_len			= sizeof(bnx2_RXP_b09FwText),
 
-	.data_addr			= 0x080069e0,
+	.data_addr			= 0x08006a00,
 	.data_len			= 0x0,
 	.data_index			= 0x0,
 	.data				= bnx2_RXP_b09FwData,
 
-	.sbss_addr			= 0x080069e0,
-	.sbss_len			= 0x2c,
+	.sbss_addr			= 0x08006a00,
+	.sbss_len			= 0x20,
 	.sbss_index			= 0x0,
 	.sbss				= bnx2_RXP_b09FwSbss,
 
-	.bss_addr			= 0x08006a10,
+	.bss_addr			= 0x08006a20,
 	.bss_len			= 0x13dc,
 	.bss_index			= 0x0,
 	.bss				= bnx2_RXP_b09FwBss,
 
-	.rodata_addr			= 0x08006740,
+	.rodata_addr			= 0x08006768,
 	.rodata_len			= 0x278,
 	.rodata_index			= 0x0,
 	.rodata				= bnx2_RXP_b09FwRodata,
 };
 
 static u8 bnx2_TPAT_b09FwText[] = {
-	0x1f, 0x8b, 0x08, 0x08, 0xdb, 0xfd, 0x2f, 0x45, 0x00, 0x03, 0x74, 0x65,
-	0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, 0xc5, 0x58, 0x5d, 0x6c,
-	0x1c, 0x57, 0x15, 0x3e, 0xf3, 0xbb, 0x13, 0x77, 0xed, 0xbd, 0x49, 0x97,
-	0x6a, 0x13, 0xb9, 0x74, 0xc6, 0x1e, 0x3b, 0x8b, 0x1c, 0x35, 0x93, 0xb0,
-	0x24, 0x16, 0x5a, 0xd1, 0xc9, 0xcc, 0xae, 0x6b, 0xe5, 0x29, 0x86, 0xbc,
-	0xf1, 0xb2, 0xac, 0xed, 0x46, 0x54, 0x48, 0x4d, 0x51, 0x84, 0x22, 0x81,
-	0x94, 0x65, 0x76, 0x53, 0x40, 0x5a, 0x65, 0xc1, 0xa0, 0x04, 0x21, 0x84,
-	0x22, 0x9b, 0x66, 0x91, 0x58, 0x3c, 0x4d, 0xe9, 0x6b, 0x94, 0xbc, 0x90,
-	0x96, 0x17, 0x9e, 0x4b, 0x9e, 0xac, 0x02, 0x12, 0x0f, 0xa8, 0x8a, 0x78,
-	0x40, 0x15, 0x0d, 0x1e, 0xbe, 0x33, 0x3f, 0x9b, 0x5d, 0xd7, 0x29, 0x79,
-	0xa8, 0x84, 0xa5, 0xf1, 0xcc, 0xfd, 0x39, 0xf7, 0xe7, 0x7c, 0xdf, 0x77,
-	0xee, 0xb9, 0x5b, 0x92, 0x69, 0x82, 0xd2, 0xbf, 0x49, 0x3c, 0x97, 0xbe,
-	0x71, 0xf1, 0xd2, 0xe2, 0x8b, 0x27, 0x4d, 0x3a, 0x71, 0xe2, 0x45, 0xe9,
-	0x19, 0x43, 0xa6, 0xcf, 0xe0, 0x4f, 0x21, 0x12, 0xd9, 0xf8, 0xfc, 0x90,
-	0x21, 0x57, 0x6f, 0x4e, 0x7b, 0x36, 0x19, 0x4a, 0xd5, 0x79, 0x61, 0xd5,
-	0x26, 0x72, 0x07, 0x0b, 0xa6, 0x4f, 0xff, 0x89, 0x5a, 0x45, 0x95, 0xb8,
-	0xfe, 0xf9, 0xea, 0xa3, 0xe3, 0x77, 0x4e, 0x5b, 0x0f, 0x6f, 0x2a, 0x64,
-	0x88, 0x6a, 0xc3, 0x10, 0xf3, 0x64, 0x4c, 0xc3, 0xe6, 0x97, 0x47, 0x57,
-	0x34, 0x9a, 0xca, 0xc6, 0x12, 0x14, 0xf4, 0x0c, 0xaa, 0x77, 0x31, 0x8e,
-	0x7d, 0x59, 0xf2, 0x43, 0x55, 0xf2, 0x6f, 0x18, 0x24, 0x57, 0x5d, 0xc9,
-	0x0b, 0x6d, 0xb4, 0x49, 0xe4, 0x39, 0x39, 0x72, 0x45, 0x14, 0x7d, 0xd3,
-	0x91, 0x49, 0xb6, 0x77, 0xa3, 0xd9, 0xb9, 0x25, 0xc9, 0xeb, 0x2f, 0x4b,
-	0x7e, 0xdf, 0xe3, 0x7d, 0x63, 0x1d, 0x4b, 0x92, 0xdb, 0xe7, 0x77, 0xd5,
-	0xf0, 0xbb, 0x53, 0xd4, 0x28, 0x52, 0x41, 0xb6, 0xd9, 0xd6, 0x24, 0xdf,
-	0x59, 0x28, 0x29, 0x34, 0x8b, 0xe7, 0x00, 0xad, 0x3b, 0x94, 0xf7, 0x1c,
-	0x52, 0x15, 0x5b, 0x26, 0xbf, 0x28, 0xd1, 0xaf, 0x2b, 0x1a, 0x9e, 0xb3,
-	0x52, 0xad, 0xbf, 0x96, 0x8e, 0x53, 0xa4, 0x36, 0xd6, 0xd2, 0x2c, 0xf2,
-	0xda, 0x12, 0x7b, 0xcf, 0x59, 0x10, 0x32, 0xcd, 0xe2, 0x99, 0xc4, 0x77,
-	0x13, 0xfd, 0x34, 0xf2, 0x2a, 0x7b, 0xdb, 0x0e, 0xe0, 0x1b, 0xeb, 0xc4,
-	0x58, 0x5e, 0xbc, 0x0e, 0x13, 0xeb, 0xb0, 0xa9, 0xd3, 0x5b, 0xc6, 0x3e,
-	0xe6, 0x4a, 0x4d, 0xd2, 0xa9, 0x13, 0xaf, 0x7d, 0x92, 0x02, 0xa1, 0x50,
-	0x70, 0x4c, 0x23, 0xf7, 0x9c, 0x8a, 0xf2, 0x21, 0x6a, 0x09, 0x09, 0x7d,
-	0x3a, 0x29, 0x7e, 0x39, 0xb4, 0xeb, 0xa8, 0x2f, 0x50, 0x50, 0x3c, 0x28,
-	0xc9, 0xd5, 0xef, 0xa1, 0x7e, 0x4e, 0x34, 0xe9, 0xbb, 0x78, 0x4b, 0x28,
-	0x1f, 0xe4, 0xf1, 0x50, 0x96, 0x48, 0xb1, 0x49, 0x78, 0xa1, 0x49, 0xed,
-	0x30, 0xb3, 0xe5, 0xfa, 0xa4, 0xae, 0x15, 0xee, 0xc5, 0x0e, 0xfd, 0x7a,
-	0x75, 0x6a, 0x08, 0x6a, 0xa9, 0x55, 0xf4, 0xe9, 0xd9, 0xa2, 0x06, 0x9c,
-	0xdc, 0x18, 0xcf, 0x97, 0xb8, 0x9e, 0xff, 0x50, 0x6f, 0x92, 0x52, 0xb5,
-	0x85, 0x4f, 0x5f, 0xa6, 0xa4, 0x8d, 0xf7, 0x29, 0x63, 0x6f, 0xa7, 0xd2,
-	0x72, 0x51, 0x78, 0x37, 0xbe, 0x48, 0x6e, 0xec, 0x1f, 0x03, 0xdf, 0x02,
-	0x7b, 0xd4, 0x81, 0x75, 0xe0, 0xca, 0xd4, 0x2a, 0x19, 0x64, 0x2d, 0xae,
-	0xa1, 0xe5, 0x6f, 0x5d, 0x05, 0x7e, 0x67, 0xdc, 0xd4, 0xd4, 0x8e, 0x71,
-	0xfe, 0x23, 0xd6, 0xd9, 0x12, 0x06, 0xf0, 0x6e, 0x9c, 0x8f, 0xa2, 0x37,
-	0x9d, 0x28, 0xd2, 0xab, 0x76, 0xf9, 0x16, 0x2d, 0x94, 0x34, 0x9a, 0x17,
-	0x78, 0xc3, 0x8f, 0x36, 0x7c, 0xa5, 0x65, 0xeb, 0xc9, 0x78, 0x86, 0xbf,
-	0xcb, 0x12, 0x96, 0x42, 0x1f, 0x74, 0xdf, 0x63, 0x7f, 0x94, 0x97, 0x62,
-	0x9b, 0x28, 0xda, 0x5c, 0xfc, 0x34, 0x9b, 0xef, 0xa7, 0x36, 0x51, 0x54,
-	0xaf, 0xf0, 0xbc, 0x16, 0xf6, 0xcc, 0x5c, 0x25, 0xaa, 0x0f, 0x1c, 0xa3,
-	0xd9, 0xc5, 0xfa, 0x6c, 0xbc, 0x07, 0x25, 0xec, 0xc1, 0x2a, 0x9b, 0x92,
-	0x41, 0x81, 0x1d, 0xbd, 0x00, 0x7e, 0xb8, 0xbe, 0x6d, 0xbd, 0xef, 0x2b,
-	0x05, 0xda, 0x72, 0xf2, 0xd4, 0x09, 0x4b, 0x14, 0x84, 0x1d, 0xf2, 0x42,
-	0x19, 0x73, 0x14, 0x68, 0xd3, 0x7e, 0x18, 0xd5, 0x1d, 0x07, 0x7e, 0x21,
-	0xb6, 0x2b, 0xd5, 0x69, 0x1a, 0xed, 0x0b, 0x62, 0x8d, 0x1c, 0x60, 0x21,
-	0xc3, 0x37, 0xb3, 0xf1, 0x77, 0x10, 0x3a, 0x68, 0xa7, 0x96, 0x5c, 0xb1,
-	0x44, 0x40, 0x56, 0xc9, 0x53, 0x48, 0xc8, 0x55, 0x81, 0x3e, 0x2d, 0xaa,
-	0x85, 0x06, 0xed, 0x28, 0x97, 0x63, 0x7e, 0xb7, 0x7b, 0x3b, 0xd1, 0x9d,
-	0xa3, 0x25, 0xba, 0x1b, 0x16, 0xe9, 0x76, 0x48, 0x72, 0xd3, 0x01, 0x37,
-	0x8a, 0x82, 0xde, 0x0a, 0x47, 0xf7, 0xf2, 0x1b, 0xec, 0x25, 0x38, 0xa2,
-	0x40, 0x83, 0xab, 0xce, 0x3d, 0x30, 0xc8, 0x02, 0x46, 0x2d, 0xec, 0x3d,
-	0x7b, 0xf3, 0xbe, 0x76, 0xa6, 0x57, 0x6d, 0xeb, 0x87, 0x3e, 0xa3, 0x76,
-	0x4d, 0x43, 0xed, 0x5e, 0x7f, 0x0c, 0x30, 0x86, 0xa0, 0xab, 0xd0, 0x93,
-	0x0c, 0xbf, 0xcc, 0x6c, 0x1b, 0xd4, 0xef, 0xe6, 0xc8, 0xdc, 0x54, 0xa9,
-	0xd9, 0x2b, 0x92, 0x33, 0x6f, 0x99, 0x24, 0xcb, 0x45, 0x99, 0x54, 0x9a,
-	0xd9, 0x8c, 0x68, 0x09, 0xeb, 0xb8, 0x6f, 0xff, 0x48, 0xa7, 0xa9, 0xc0,
-	0xd1, 0x89, 0xfb, 0x18, 0x34, 0x73, 0xcb, 0x90, 0xfc, 0x1e, 0xef, 0x83,
-	0x7d, 0x6e, 0xa4, 0x3e, 0x57, 0x25, 0xef, 0x46, 0x8e, 0x66, 0x37, 0xfe,
-	0x11, 0x79, 0x36, 0x7c, 0x0d, 0x9e, 0xaf, 0x56, 0xbe, 0xa0, 0xd0, 0x04,
-	0xea, 0x36, 0xb9, 0xed, 0x61, 0x5a, 0xcf, 0x63, 0x44, 0x91, 0xe7, 0x3c,
-	0x4b, 0x1e, 0xf3, 0xff, 0x3c, 0xdb, 0xe4, 0x68, 0x66, 0x83, 0x75, 0x83,
-	0xf7, 0x26, 0x97, 0x79, 0x6d, 0x07, 0xa8, 0x89, 0x1d, 0x35, 0xcb, 0x45,
-	0xf8, 0x41, 0x8e, 0x35, 0xd2, 0xc4, 0x8e, 0x65, 0x7b, 0x02, 0x6f, 0x9e,
-	0xef, 0xac, 0x92, 0xf0, 0x9d, 0xe3, 0x46, 0x9e, 0x7c, 0xe0, 0xab, 0x62,
-	0x3d, 0x6b, 0x34, 0x57, 0x5a, 0x8f, 0xdb, 0x50, 0x37, 0xe0, 0x36, 0xb1,
-	0xa7, 0x0d, 0xe5, 0x41, 0xb6, 0x06, 0x70, 0xda, 0x6e, 0x63, 0x16, 0x2d,
-	0xde, 0x6b, 0xdd, 0xe1, 0xfe, 0xdc, 0xb7, 0x55, 0xd6, 0xc8, 0x2a, 0x6f,
-	0x62, 0xf4, 0x7e, 0x17, 0xfb, 0xbd, 0xce, 0xb1, 0xc8, 0x36, 0xff, 0x4a,
-	0xdc, 0x7f, 0x16, 0x7b, 0x9e, 0x5b, 0x6c, 0x73, 0xdb, 0x40, 0x23, 0x7b,
-	0xa3, 0x25, 0x54, 0xf8, 0x5f, 0x86, 0xf3, 0xfd, 0x1f, 0xff, 0x2b, 0xd2,
-	0xaa, 0xe0, 0x74, 0xa5, 0x00, 0x7c, 0x2c, 0xb3, 0x0d, 0xbd, 0xdb, 0x18,
-	0x37, 0x70, 0x14, 0xd8, 0x25, 0x38, 0x71, 0xbf, 0xa5, 0x6e, 0x44, 0xed,
-	0x78, 0xae, 0x2b, 0x3c, 0x17, 0x62, 0x92, 0xbd, 0xf8, 0x07, 0x70, 0xa3,
-	0x49, 0x79, 0x9a, 0xdf, 0xce, 0xd3, 0x85, 0x41, 0x9e, 0x66, 0xae, 0xe9,
-	0xf0, 0x43, 0x14, 0x75, 0x2a, 0xac, 0x51, 0xe0, 0x6d, 0x73, 0x3f, 0xab,
-	0xa4, 0xc8, 0xbc, 0x0e, 0xb4, 0x6f, 0x13, 0xad, 0x0d, 0x74, 0xf8, 0x4d,
-	0x1d, 0x19, 0x5b, 0xa6, 0x97, 0x7f, 0x46, 0xf4, 0xf2, 0x80, 0x6d, 0x79,
-	0xfc, 0xc4, 0xa6, 0x89, 0x3d, 0xcb, 0xc0, 0xfc, 0xc2, 0x40, 0x46, 0xbc,
-	0x40, 0x3c, 0xed, 0x7b, 0x88, 0x93, 0x35, 0x3c, 0x4b, 0x88, 0x9d, 0x8c,
-	0x0d, 0xc7, 0x91, 0x5d, 0xe0, 0xb3, 0x8c, 0xb6, 0xb3, 0xa8, 0x4b, 0xf4,
-	0xae, 0xd8, 0x3a, 0xd5, 0x9c, 0x49, 0x6a, 0x67, 0xb1, 0x4a, 0x70, 0xac,
-	0x3a, 0x08, 0x4e, 0x1d, 0x40, 0xfc, 0xf9, 0x9d, 0x32, 0x1e, 0xab, 0x10,
-	0xd3, 0x8a, 0x87, 0x11, 0x9b, 0xfa, 0xa8, 0xe7, 0xf1, 0x6e, 0xe1, 0x7d,
-	0x00, 0xe5, 0xc3, 0xe8, 0x3b, 0x1a, 0xa7, 0x32, 0xbb, 0x27, 0xc5, 0x28,
-	0xf0, 0x6e, 0xc3, 0x40, 0x7f, 0x13, 0xba, 0x61, 0x7f, 0xe7, 0x10, 0x3f,
-	0xd8, 0xe7, 0x39, 0xf8, 0x54, 0xc7, 0xdc, 0x82, 0x66, 0xb7, 0xa9, 0xa5,
-	0xa4, 0xf1, 0xcb, 0x1f, 0xc6, 0xaf, 0x52, 0xcc, 0x83, 0x20, 0x14, 0xb0,
-	0x61, 0xfd, 0x66, 0x7a, 0x65, 0xec, 0xc8, 0xf5, 0xa0, 0x65, 0x4f, 0x89,
-	0xa2, 0x55, 0xa7, 0x40, 0x4d, 0xe0, 0xee, 0x42, 0xc3, 0x4d, 0x68, 0xd8,
-	0x1f, 0xd1, 0xb0, 0xff, 0x3f, 0x35, 0x0c, 0x7d, 0x42, 0x23, 0xb7, 0xc1,
-	0xa9, 0xb7, 0x7a, 0xfb, 0xe9, 0x99, 0xb5, 0xcc, 0x9a, 0x36, 0xe9, 0xce,
-	0xd1, 0xa7, 0xd5, 0x74, 0x49, 0x7e, 0x4a, 0x4d, 0xb7, 0x58, 0xd3, 0x2a,
-	0x6b, 0xba, 0xb8, 0x57, 0xd3, 0xd3, 0x18, 0x23, 0xd1, 0xe6, 0x19, 0xb5,
-	0x48, 0xda, 0x3c, 0xf0, 0xd8, 0xc8, 0x93, 0x72, 0xed, 0x31, 0xef, 0x98,
-	0xcb, 0xfe, 0x00, 0xff, 0xb6, 0x35, 0xb4, 0x49, 0xe3, 0xf5, 0x88, 0x81,
-	0x6a, 0xd5, 0x2a, 0xad, 0xc5, 0x7d, 0x54, 0xd2, 0xe1, 0xff, 0xd7, 0x8f,
-	0x5a, 0xa6, 0x29, 0x8f, 0x6a, 0x1f, 0xea, 0xdf, 0x88, 0xae, 0x68, 0x55,
-	0x9e, 0xa7, 0x65, 0x82, 0xf3, 0xe6, 0x4f, 0x80, 0x55, 0xbb, 0xcb, 0x7c,
-	0xb7, 0x45, 0x3d, 0xe6, 0x19, 0xca, 0xd0, 0x84, 0x06, 0xde, 0xe6, 0xd0,
-	0x4f, 0xdd, 0x48, 0x74, 0x74, 0x1b, 0xe3, 0x6e, 0x75, 0x99, 0x67, 0x06,
-	0xe9, 0xd7, 0xed, 0xd2, 0x85, 0x38, 0x06, 0xcf, 0x8a, 0x25, 0x62, 0x0d,
-	0xf2, 0xb9, 0x88, 0xf6, 0x41, 0x8e, 0x94, 0x58, 0xf7, 0x13, 0xa9, 0xee,
-	0x9f, 0x87, 0xaf, 0x26, 0x50, 0x66, 0xed, 0x1f, 0x4e, 0xb5, 0x3f, 0x85,
-	0x37, 0xd7, 0xad, 0xa8, 0x09, 0x87, 0xc0, 0xc7, 0x0d, 0xc6, 0x37, 0x8f,
-	0x58, 0xc7, 0xf3, 0xff, 0x33, 0x5a, 0xb5, 0x19, 0x63, 0xdb, 0xfc, 0x01,
-	0xcd, 0x41, 0x7f, 0xa8, 0xdf, 0xe6, 0xbe, 0x6c, 0x93, 0xf5, 0x15, 0x69,
-	0xdf, 0x0f, 0xf7, 0xf4, 0x45, 0xfd, 0x36, 0xf7, 0x63, 0x7d, 0x1c, 0x22,
-	0xe5, 0x3a, 0x9f, 0xdb, 0x1e, 0xeb, 0x03, 0x76, 0x35, 0xd4, 0x71, 0x6e,
-	0xc1, 0xf6, 0x7c, 0x86, 0xf3, 0x3a, 0x39, 0xef, 0xe0, 0x73, 0x7e, 0xcf,
-	0x79, 0x3e, 0xd4, 0xc8, 0x19, 0xf0, 0xfe, 0x3b, 0xea, 0x27, 0x35, 0xb2,
-	0x02, 0x4d, 0x5c, 0x54, 0x13, 0x8d, 0xbc, 0x86, 0xf7, 0x19, 0x94, 0x57,
-	0xf6, 0x68, 0x24, 0xb3, 0x7b, 0xf2, 0x39, 0x1e, 0xf4, 0x4a, 0xf1, 0x99,
-	0xcb, 0xf3, 0x29, 0x1b, 0xd4, 0xd2, 0x52, 0x3d, 0xd4, 0x87, 0x7a, 0x98,
-	0x40, 0xcc, 0xc8, 0xa5, 0x5c, 0xc7, 0xdb, 0xfe, 0x48, 0xf1, 0x1d, 0x4b,
-	0xb4, 0x89, 0xb5, 0x31, 0x7a, 0x9e, 0xfd, 0xbf, 0xf4, 0x41, 0xe0, 0x51,
-	0x3c, 0x37, 0x72, 0x11, 0x3e, 0x17, 0xa2, 0xe8, 0x15, 0x07, 0xed, 0x59,
-	0x4e, 0x12, 0x63, 0x9f, 0xc3, 0xd9, 0xcb, 0x78, 0x20, 0x0f, 0xb4, 0x67,
-	0xa1, 0x07, 0x8e, 0x05, 0xbb, 0xd1, 0x96, 0xed, 0xa1, 0xae, 0x06, 0xff,
-	0x33, 0x26, 0xcb, 0xd2, 0x52, 0xdf, 0x60, 0x3b, 0xe8, 0x6d, 0xbf, 0x5c,
-	0x4c, 0x87, 0xae, 0x1e, 0xe3, 0xc4, 0x3c, 0x6a, 0x8e, 0xe0, 0xd4, 0x88,
-	0x71, 0xda, 0x19, 0xe2, 0xd4, 0x4c, 0x71, 0x6a, 0xc6, 0x38, 0x3d, 0x48,
-	0x71, 0xfa, 0xf3, 0x13, 0x70, 0xda, 0x79, 0x0a, 0x9c, 0x0c, 0xda, 0xb2,
-	0x4b, 0x38, 0x6f, 0xf5, 0x38, 0x77, 0xbd, 0xef, 0xec, 0x97, 0x7b, 0xb1,
-	0xdf, 0xc7, 0xb0, 0x8a, 0x18, 0xab, 0x2d, 0x1a, 0xcd, 0x43, 0x2c, 0xf3,
-	0x1e, 0x15, 0x70, 0x6e, 0xe4, 0xe9, 0xea, 0x9e, 0x5c, 0x24, 0x00, 0x4e,
-	0xb5, 0x14, 0xa7, 0xab, 0xc0, 0xa9, 0x96, 0xe2, 0xb4, 0x3e, 0x82, 0xd3,
-	0xfa, 0x18, 0x4e, 0x1c, 0x53, 0x2a, 0xc6, 0x7a, 0x37, 0xc3, 0x28, 0xc3,
-	0x47, 0xa7, 0x9b, 0x62, 0x0a, 0xfb, 0x3f, 0x4e, 0xed, 0x9f, 0xaa, 0x9c,
-	0xff, 0x02, 0xbb, 0x97, 0x54, 0x39, 0x3e, 0x17, 0xf8, 0xfb, 0x71, 0xbe,
-	0x82, 0xb9, 0x5c, 0xcf, 0xe1, 0x3d, 0x21, 0xcf, 0xb5, 0x47, 0x63, 0xd1,
-	0x07, 0x88, 0x45, 0x5c, 0xc7, 0xfd, 0x54, 0xa9, 0x06, 0xcd, 0x2b, 0xc8,
-	0xe1, 0xfd, 0x61, 0x0e, 0x9f, 0xf8, 0xe1, 0x6a, 0x9a, 0xc3, 0x6f, 0xd9,
-	0x9c, 0xc3, 0x9f, 0xd0, 0x68, 0x62, 0x39, 0xc5, 0x93, 0x79, 0x3d, 0x89,
-	0xb6, 0xb3, 0x31, 0xee, 0x6d, 0xc4, 0xf2, 0x55, 0xf8, 0xa0, 0x19, 0xf3,
-	0x13, 0x79, 0x57, 0xca, 0x5d, 0xe4, 0xbb, 0xe4, 0x87, 0x09, 0x4f, 0x3f,
-	0xdb, 0x5c, 0xec, 0xef, 0x88, 0xd9, 0x46, 0x43, 0xc5, 0x1d, 0xe0, 0x6e,
-	0x18, 0xc7, 0xea, 0x73, 0x41, 0x97, 0x5a, 0x47, 0xaa, 0x57, 0x22, 0xe0,
-	0xee, 0x7e, 0xfd, 0x34, 0x9f, 0x39, 0xf9, 0x45, 0xaf, 0x82, 0xfa, 0x81,
-	0x41, 0xc8, 0x83, 0x70, 0xa7, 0xa1, 0x96, 0x77, 0x5a, 0x42, 0xbe, 0x83,
-	0x32, 0x6c, 0x82, 0x70, 0xba, 0x21, 0x57, 0x4b, 0xe0, 0x43, 0x8b, 0x5c,
-	0xac, 0xd3, 0x0d, 0xe3, 0x7b, 0x4d, 0x43, 0xa9, 0x1a, 0xc8, 0x37, 0xc9,
-	0xc0, 0x99, 0x0f, 0x9f, 0x98, 0x46, 0x7b, 0x80, 0x9c, 0x08, 0x79, 0x80,
-	0xb7, 0x08, 0xbf, 0x1c, 0x03, 0x76, 0xa1, 0x0a, 0xdb, 0x6f, 0xe9, 0xc9,
-	0x9d, 0x88, 0xc8, 0x8b, 0xfd, 0xf5, 0x71, 0xca, 0x91, 0x38, 0xe7, 0x92,
-	0x6a, 0x3d, 0x32, 0x9b, 0x0e, 0xb8, 0x8e, 0x33, 0xa5, 0x13, 0x72, 0x5e,
-	0x7d, 0xcc, 0x90, 0xaf, 0x71, 0x3c, 0x7f, 0x00, 0x1f, 0xe2, 0x7b, 0x9b,
-	0xcf, 0x19, 0x85, 0x73, 0x73, 0xdc, 0x7d, 0xca, 0x88, 0x37, 0x34, 0x89,
-	0xd8, 0x87, 0xd8, 0x3b, 0xcd, 0x58, 0xb9, 0xc9, 0x19, 0xc4, 0xe3, 0x1d,
-	0x97, 0x93, 0x79, 0xfe, 0xa4, 0x25, 0x1c, 0xc6, 0x7d, 0x07, 0xfe, 0x5b,
-	0xed, 0x39, 0x1c, 0x73, 0x3f, 0xaf, 0xd0, 0x43, 0x8a, 0x39, 0x29, 0x4e,
-	0x20, 0x16, 0x9f, 0x86, 0x8d, 0x1b, 0xeb, 0x31, 0xc9, 0xbd, 0x32, 0x9b,
-	0x0f, 0xf7, 0x8c, 0xf1, 0x17, 0x65, 0xbc, 0xec, 0x82, 0xd3, 0x95, 0x74,
-	0xbe, 0x51, 0x8e, 0x2c, 0x20, 0xe5, 0x79, 0xa0, 0x0d, 0xf3, 0xb7, 0xa2,
-	0x8e, 0x7e, 0xbc, 0x46, 0xd6, 0x25, 0xdb, 0x1c, 0xd1, 0xc6, 0xc7, 0x99,
-	0xdd, 0x67, 0x8c, 0xea, 0xc8, 0x18, 0x45, 0xde, 0x9b, 0x68, 0x3a, 0xcf,
-	0xa4, 0xf7, 0x0c, 0x8e, 0x2d, 0x02, 0x3a, 0x95, 0x9f, 0x93, 0xb1, 0x0f,
-	0x0f, 0x7b, 0xf6, 0xe3, 0xfa, 0x5f, 0xe9, 0xe3, 0xe3, 0xfe, 0x56, 0x4d,
-	0xca, 0xc7, 0x12, 0x6e, 0xda, 0x78, 0x87, 0x0f, 0x46, 0xd6, 0xae, 0xed,
-	0x33, 0xef, 0xd7, 0x38, 0x5d, 0x43, 0xbc, 0x21, 0x57, 0xc1, 0x1d, 0xcc,
-	0x27, 0x7c, 0x87, 0xaf, 0x67, 0x3e, 0x04, 0x6f, 0xe8, 0x5c, 0x3b, 0xe5,
-	0x8b, 0x9c, 0xf0, 0x85, 0xf3, 0xba, 0xc5, 0x55, 0xf0, 0xa5, 0x0d, 0xbe,
-	0xc0, 0xae, 0xa1, 0x55, 0xa7, 0xc1, 0x05, 0x8e, 0x4d, 0x28, 0x87, 0xcc,
-	0x1d, 0xe6, 0x0a, 0xf3, 0xe6, 0x31, 0x5f, 0x5e, 0xe9, 0x1a, 0xc6, 0xe6,
-	0xa7, 0x70, 0xe5, 0x8d, 0x98, 0x2b, 0xcc, 0xd9, 0x24, 0x7e, 0x74, 0x80,
-	0x55, 0x90, 0xc6, 0x8f, 0x00, 0xf1, 0xa3, 0xc6, 0xf9, 0x4f, 0x1c, 0x0b,
-	0x12, 0xfd, 0xac, 0x41, 0x3f, 0x35, 0x85, 0xf3, 0x23, 0xd6, 0x0e, 0xdb,
-	0xb1, 0x7e, 0xd8, 0xae, 0x90, 0xda, 0x8d, 0xc7, 0x91, 0x76, 0xcf, 0x32,
-	0xb3, 0x38, 0xd2, 0x86, 0x76, 0x3a, 0xa9, 0x8e, 0xda, 0xa9, 0x8e, 0xd0,
-	0xa7, 0xa5, 0x54, 0xf8, 0x4c, 0xb0, 0x4c, 0x1f, 0xf1, 0xa3, 0x13, 0x8f,
-	0xd9, 0xa2, 0xe4, 0x2e, 0xc3, 0xda, 0xe6, 0xb8, 0x3b, 0x12, 0x6f, 0xd3,
-	0x7b, 0x6e, 0x23, 0xbe, 0xe7, 0x7e, 0x45, 0x1f, 0x8f, 0xb7, 0x38, 0x6b,
-	0xe2, 0x7b, 0xee, 0x29, 0x9d, 0xef, 0xb9, 0x01, 0x7d, 0x49, 0x1f, 0xbd,
-	0xe7, 0x06, 0x63, 0xf7, 0xdc, 0xcc, 0x96, 0xeb, 0xf7, 0x8b, 0xbb, 0x99,
-	0x4f, 0x38, 0xf6, 0x32, 0x9f, 0xf6, 0xcb, 0x15, 0xb3, 0x3e, 0x1c, 0x93,
-	0x58, 0xef, 0x1c, 0xcb, 0x92, 0xdc, 0xec, 0x6e, 0x98, 0xe9, 0xe2, 0x55,
-	0xcc, 0x83, 0x72, 0x6f, 0x3f, 0x5d, 0x18, 0xa9, 0x2e, 0x26, 0x13, 0x9b,
-	0xde, 0xa8, 0x36, 0x5e, 0xd5, 0xc7, 0xb5, 0x91, 0x8d, 0x93, 0x69, 0x23,
-	0x19, 0x73, 0x47, 0x29, 0xe1, 0x0c, 0x2c, 0x23, 0x1e, 0x09, 0xbe, 0xa3,
-	0x21, 0x5e, 0x54, 0xf3, 0xb8, 0xa7, 0x14, 0x78, 0xec, 0x76, 0xf8, 0x2c,
-	0x35, 0x8a, 0x8c, 0x0b, 0xaf, 0xff, 0x61, 0x7c, 0x7f, 0xc0, 0xba, 0x0b,
-	0x01, 0xff, 0xfe, 0xf1, 0x09, 0x3e, 0xbe, 0x06, 0x3e, 0x66, 0xfb, 0x19,
-	0xad, 0xbf, 0x34, 0x52, 0x5f, 0x4e, 0x31, 0x4f, 0x7c, 0x7e, 0x2f, 0xd5,
-	0xc8, 0x26, 0x72, 0xb7, 0xfb, 0xc8, 0x8b, 0xde, 0x44, 0xfc, 0x0e, 0x06,
-	0x1f, 0x47, 0xf7, 0x8a, 0x2a, 0x75, 0x86, 0x36, 0xbf, 0xc0, 0xba, 0x2d,
-	0x71, 0x13, 0x5f, 0x6f, 0x0c, 0xb2, 0xb1, 0xb9, 0x9d, 0xeb, 0xfe, 0x8d,
-	0xf3, 0x19, 0x79, 0xdf, 0xb0, 0xef, 0xfb, 0x11, 0xe7, 0xbb, 0x77, 0x81,
-	0xc5, 0x3b, 0xe1, 0x34, 0xfd, 0x1e, 0x1c, 0x7b, 0x3b, 0xce, 0x79, 0x93,
-	0x5c, 0x17, 0xfe, 0xc3, 0x99, 0xc7, 0x67, 0xbd, 0xf7, 0x39, 0x99, 0x2e,
-	0xd3, 0x57, 0x1d, 0xae, 0x93, 0xa9, 0x7e, 0x2a, 0x8a, 0x2e, 0xe2, 0xdc,
-	0x5f, 0x19, 0x3b, 0xf7, 0x71, 0x07, 0x3c, 0xc9, 0xf9, 0x7f, 0x96, 0xf3,
-	0xef, 0x46, 0x33, 0xf3, 0xd6, 0x4d, 0x97, 0x5c, 0xa9, 0xde, 0xe7, 0x7c,
-	0x6c, 0x98, 0x8b, 0x11, 0x1d, 0x7a, 0x14, 0xc9, 0xf3, 0x7c, 0x36, 0xbd,
-	0x9b, 0xfa, 0x1c, 0x6d, 0x37, 0x1e, 0xe1, 0x1e, 0x53, 0x8b, 0x7f, 0x17,
-	0x72, 0xfb, 0x3c, 0x0f, 0x97, 0xf1, 0x0e, 0x39, 0x47, 0x78, 0xd2, 0x6f,
-	0x35, 0x2a, 0xf0, 0xb5, 0xcc, 0x75, 0x85, 0xe2, 0x7b, 0x21, 0xee, 0x6e,
-	0x3f, 0x6f, 0x53, 0x12, 0x3b, 0x6a, 0xce, 0x39, 0xac, 0x05, 0x98, 0x88,
-	0x06, 0x30, 0x9e, 0x47, 0xac, 0xb2, 0xcc, 0x93, 0x72, 0xf2, 0x5b, 0xd5,
-	0x1a, 0xc6, 0x56, 0x4e, 0x72, 0x2e, 0xf9, 0x51, 0xb4, 0x36, 0x88, 0xcf,
-	0x44, 0x87, 0xb9, 0xe6, 0x87, 0x07, 0x65, 0x7e, 0xbb, 0x21, 0x7f, 0xeb,
-	0x98, 0xc7, 0x7c, 0x02, 0x0f, 0x8b, 0xa2, 0x76, 0xc3, 0x14, 0xf5, 0x9e,
-	0x29, 0x96, 0x7a, 0x32, 0x54, 0x52, 0xc8, 0xd1, 0x14, 0xe7, 0x08, 0x3a,
-	0xd1, 0x73, 0x58, 0xcb, 0x2d, 0x53, 0xf8, 0xc8, 0xa3, 0xbe, 0xad, 0x58,
-	0x62, 0x85, 0x76, 0xb1, 0xc7, 0x47, 0x51, 0x72, 0xa7, 0x35, 0x45, 0x6d,
-	0x38, 0xf7, 0x23, 0xcc, 0xcd, 0x6b, 0x62, 0x2d, 0xf3, 0x79, 0xb6, 0x2c,
-	0x9d, 0x83, 0x8f, 0xce, 0xf7, 0x77, 0x11, 0x43, 0xf9, 0x3c, 0xcb, 0x23,
-	0xe6, 0x59, 0x26, 0x5f, 0xf6, 0xef, 0x62, 0xff, 0xef, 0xf4, 0x80, 0x0f,
-	0x72, 0xc7, 0xb7, 0x87, 0x79, 0x1a, 0x63, 0x58, 0x06, 0x17, 0xd9, 0x3e,
-	0x8a, 0x82, 0xc5, 0x38, 0x47, 0xc1, 0x5a, 0xe6, 0xca, 0xb7, 0x90, 0xa7,
-	0xd7, 0x69, 0xa1, 0x5c, 0x8f, 0xdf, 0x11, 0x72, 0x12, 0xfe, 0x5d, 0xc0,
-	0x12, 0x4d, 0x7c, 0xd7, 0xd2, 0xef, 0x80, 0x73, 0xf8, 0x45, 0x1e, 0x83,
-	0x73, 0x79, 0xd6, 0xe1, 0x7f, 0x01, 0x17, 0xc6, 0xf1, 0xb2, 0x84, 0x14,
-	0x00, 0x00, 0x00 };
-static u32 bnx2_TPAT_b09FwData[(0x0/4) + 1] = { 0x0 };
-static u32 bnx2_TPAT_b09FwRodata[(0x0/4) + 1] = { 0x0 };
-static u32 bnx2_TPAT_b09FwBss[(0x250/4) + 1] = { 0x0 };
-static u32 bnx2_TPAT_b09FwSbss[(0x34/4) + 1] = { 0x0 };
+	0x1f, 0x8b, 0x08, 0x00, 0x0e, 0x34, 0xe7, 0x45, 0x00, 0x03, 0xcd, 0x58,
+	0x5d, 0x68, 0x1c, 0xd7, 0x15, 0x3e, 0xf3, 0xb7, 0x3b, 0x52, 0x24, 0xeb,
+	0x5a, 0xd9, 0xa6, 0xeb, 0xa0, 0x34, 0x33, 0xda, 0x91, 0xac, 0x22, 0x13,
+	0x4f, 0x9d, 0x25, 0x16, 0x65, 0x21, 0x93, 0xd9, 0x91, 0xac, 0x98, 0x3c,
+	0x28, 0xc5, 0x90, 0x87, 0x52, 0x50, 0x57, 0x32, 0x09, 0x79, 0x69, 0xda,
+	0xc6, 0x90, 0x3e, 0x79, 0x3b, 0x2b, 0xc7, 0x0e, 0x6c, 0xbc, 0x8d, 0x52,
+	0xe4, 0x52, 0xfa, 0x60, 0xd6, 0xb1, 0x05, 0xcd, 0x46, 0x93, 0xd4, 0x7e,
+	0x35, 0x36, 0x4e, 0x93, 0xa7, 0x42, 0x9f, 0x52, 0xf4, 0x18, 0xd2, 0x12,
+	0xda, 0x52, 0x8a, 0x69, 0xa1, 0x09, 0x8d, 0xeb, 0xdb, 0xef, 0xdc, 0x99,
+	0x91, 0x57, 0xb6, 0xec, 0xa4, 0x25, 0x85, 0x0a, 0x56, 0x77, 0xe6, 0xce,
+	0x3d, 0xe7, 0x9e, 0x7b, 0xee, 0x77, 0xbe, 0x73, 0xee, 0x2d, 0xeb, 0x34,
+	0x48, 0xd9, 0xdf, 0x30, 0x7e, 0x2f, 0x7e, 0xf7, 0x85, 0x17, 0xab, 0x8f,
+	0x3c, 0xea, 0x10, 0x3d, 0xfa, 0x88, 0x66, 0x98, 0x06, 0x7d, 0x09, 0x7f,
+	0x50, 0x22, 0x72, 0xfd, 0xfc, 0x23, 0x5b, 0xaf, 0x9d, 0x72, 0x42, 0x8f,
+	0x6c, 0xa3, 0x26, 0xbe, 0xbe, 0xe4, 0x11, 0x05, 0xbd, 0x69, 0xa7, 0x4e,
+	0xff, 0x92, 0xcd, 0x92, 0x49, 0xdc, 0xff, 0x50, 0xed, 0xc6, 0xfe, 0xcb,
+	0x07, 0xdd, 0xeb, 0x67, 0x0d, 0xb2, 0x45, 0x6d, 0xd1, 0x16, 0x93, 0x64,
+	0x8f, 0xd5, 0x9a, 0xce, 0x2f, 0xf6, 0x1e, 0x28, 0xd0, 0xae, 0x5c, 0x97,
+	0xa0, 0xb8, 0x43, 0x4d, 0xab, 0x66, 0x53, 0xd4, 0x7e, 0x49, 0x0b, 0x3b,
+	0x9e, 0x98, 0x85, 0x8e, 0xa0, 0x04, 0xfd, 0x1e, 0xde, 0x13, 0x53, 0x8b,
+	0xce, 0xd8, 0xa4, 0xd7, 0x02, 0x3c, 0x4f, 0x51, 0xab, 0x23, 0xe5, 0x2b,
+	0xbe, 0x46, 0x4b, 0xbe, 0x4d, 0x8b, 0xc2, 0x0d, 0x1c, 0xed, 0xa6, 0xac,
+	0x4c, 0x48, 0xf9, 0x9c, 0xaf, 0x93, 0xee, 0xcd, 0x69, 0xe1, 0xfa, 0xbc,
+	0x56, 0x5f, 0x9f, 0x67, 0x7f, 0xc0, 0xbe, 0x39, 0x2d, 0x58, 0xe7, 0xb6,
+	0x66, 0xd7, 0xdb, 0xbb, 0x68, 0xb1, 0x44, 0x23, 0xba, 0x37, 0x85, 0xf9,
+	0x4a, 0xd0, 0xe3, 0x50, 0xe8, 0x4f, 0x0b, 0x9d, 0x2a, 0xf8, 0x0d, 0xd0,
+	0xac, 0x4f, 0x03, 0xba, 0xa7, 0x53, 0xa3, 0xa4, 0xd1, 0x1b, 0x55, 0x0b,
+	0xbf, 0xc3, 0x5a, 0xb4, 0xfe, 0x7c, 0xa6, 0x87, 0xc7, 0xdb, 0xf8, 0xc6,
+	0x36, 0xb3, 0x7c, 0xbf, 0xec, 0x30, 0x9e, 0x9f, 0xc3, 0x38, 0x8b, 0xc2,
+	0xea, 0xed, 0xdf, 0x06, 0xf0, 0xac, 0xa1, 0xff, 0x30, 0xec, 0x62, 0x3d,
+	0x0e, 0xec, 0x28, 0xd3, 0x4a, 0x67, 0x1e, 0xeb, 0x29, 0x50, 0x53, 0x4c,
+	0x4c, 0x35, 0xc8, 0x84, 0x8c, 0x41, 0x41, 0xe9, 0x8a, 0xd4, 0x6b, 0x52,
+	0x86, 0x55, 0x6f, 0xaa, 0xab, 0xe6, 0xd0, 0xc9, 0xf0, 0x0a, 0x14, 0xf9,
+	0xc3, 0xd4, 0x12, 0x06, 0xc5, 0xfb, 0x2c, 0x0a, 0x16, 0x4c, 0xac, 0x71,
+	0x14, 0x72, 0x1a, 0xe4, 0x5f, 0xcb, 0xf6, 0xbc, 0x48, 0xb1, 0x28, 0xa0,
+	0x7f, 0x84, 0xe2, 0xd2, 0x6e, 0x4d, 0xaf, 0xbd, 0x82, 0xfe, 0x09, 0xd1,
+	0xa5, 0x53, 0x68, 0x35, 0xbc, 0xef, 0xc6, 0x58, 0x7e, 0xd7, 0xa0, 0x8f,
+	0x44, 0x98, 0x78, 0xd4, 0x4a, 0x72, 0x59, 0xee, 0x4f, 0xfb, 0x9a, 0xc9,
+	0xed, 0xfb, 0xed, 0xc1, 0x4e, 0x41, 0x27, 0x3a, 0xb3, 0x98, 0x8f, 0x9a,
+	0x46, 0x0d, 0xe3, 0xb0, 0x37, 0xbc, 0xbf, 0x81, 0xc2, 0xc1, 0xe3, 0xdc,
+	0xcf, 0x7f, 0xe8, 0x77, 0xc8, 0xa8, 0xf1, 0xb7, 0x6f, 0x52, 0xfa, 0x2d,
+	0xb5, 0x3f, 0xf4, 0x1f, 0xcb, 0xde, 0x4b, 0x22, 0x3c, 0xf3, 0x28, 0xd6,
+	0xa8, 0x60, 0x83, 0xe7, 0x02, 0xf0, 0x11, 0xcf, 0xe8, 0xd4, 0x2c, 0x17,
+	0xc9, 0xf5, 0x8f, 0xa2, 0xf7, 0xd7, 0x6d, 0x83, 0xea, 0xec, 0x2b, 0xdf,
+	0xcc, 0x64, 0x18, 0x1b, 0x1f, 0x64, 0x76, 0x0a, 0x5a, 0x3c, 0x22, 0xe5,
+	0x8a, 0x2f, 0xa5, 0x55, 0xf3, 0x9c, 0x13, 0x34, 0x5d, 0x36, 0x69, 0x52,
+	0xa0, 0x85, 0x8f, 0xbd, 0x72, 0x83, 0x2c, 0x60, 0xa1, 0x1f, 0xff, 0xfc,
+	0xf7, 0xa6, 0x86, 0x25, 0xd0, 0xb5, 0x36, 0xeb, 0x98, 0x70, 0x66, 0x95,
+	0x8c, 0x94, 0xf1, 0xcc, 0xbd, 0x64, 0x2e, 0x65, 0x32, 0x52, 0x46, 0x55,
+	0x81, 0x3d, 0x6f, 0x0a, 0xd8, 0x87, 0x75, 0x31, 0xc6, 0x89, 0xa2, 0x9e,
+	0x6f, 0x37, 0xda, 0xb0, 0xd1, 0x43, 0xdb, 0x13, 0xf0, 0x0f, 0x51, 0x0b,
+	0x63, 0xf5, 0xea, 0x7d, 0x8c, 0x0d, 0xec, 0xef, 0x82, 0x1d, 0xb5, 0xdd,
+	0xf2, 0x29, 0x5a, 0xb0, 0xeb, 0xbd, 0xe9, 0xf2, 0x32, 0x3d, 0xc4, 0x73,
+	0xd8, 0x56, 0xed, 0x88, 0xdd, 0x55, 0x72, 0x88, 0xc4, 0x41, 0x3c, 0xf7,
+	0x88, 0xe2, 0x36, 0x69, 0xa1, 0x7f, 0x1f, 0xaf, 0x15, 0x72, 0xf3, 0x99,
+	0xdc, 0x7c, 0x26, 0x37, 0x92, 0xc9, 0x3d, 0xd5, 0x27, 0xf7, 0x14, 0xcb,
+	0x61, 0x6c, 0x90, 0x8d, 0x0d, 0xb2, 0xb1, 0x66, 0x36, 0x36, 0xca, 0xc6,
+	0xa2, 0xed, 0x8d, 0xc1, 0x36, 0x77, 0xca, 0xd1, 0x6c, 0x8a, 0x3d, 0xf9,
+	0x70, 0xe8, 0x53, 0x50, 0xf7, 0xdc, 0xcd, 0xba, 0x31, 0x42, 0xe7, 0xfc,
+	0x21, 0x5a, 0x49, 0xc6, 0x28, 0x4e, 0x56, 0x28, 0x4c, 0x74, 0xc8, 0x8e,
+	0x50, 0xd7, 0xbb, 0x2e, 0x67, 0x7d, 0x1f, 0x7b, 0x66, 0xb3, 0x5c, 0x79,
+	0x96, 0x1c, 0x7c, 0x9f, 0x16, 0xcb, 0xe4, 0x03, 0x2b, 0x3a, 0xf6, 0xad,
+	0xa2, 0x9e, 0xe3, 0xc4, 0xe7, 0x35, 0x37, 0xf5, 0xaa, 0x2b, 0x62, 0x72,
+	0xcb, 0xa1, 0x41, 0x42, 0xaf, 0xc1, 0x4f, 0x49, 0x93, 0xa2, 0xc4, 0xa6,
+	0x0f, 0x8d, 0x97, 0x54, 0x8c, 0xc6, 0x9d, 0x4d, 0x79, 0x79, 0xaf, 0x43,
+	0x57, 0x30, 0xcf, 0xc5, 0xa4, 0x4c, 0xbf, 0x4a, 0x4a, 0xf4, 0x4e, 0x42,
+	0x7a, 0xe8, 0x03, 0xc3, 0x25, 0x41, 0x6f, 0x27, 0xfd, 0x3e, 0xff, 0x88,
+	0x7d, 0x6e, 0xdf, 0x5f, 0x23, 0x7b, 0xb4, 0xc6, 0x38, 0x4b, 0x39, 0xa0,
+	0x9e, 0x72, 0x80, 0xc2, 0x52, 0xab, 0x13, 0x3f, 0x68, 0x80, 0x7f, 0x96,
+	0xfc, 0x60, 0xb7, 0xa1, 0xf6, 0xa3, 0x89, 0x3d, 0xcc, 0x5b, 0xde, 0x9b,
+	0xab, 0xce, 0x92, 0xe7, 0x9e, 0xaa, 0x33, 0x6a, 0x4f, 0x5b, 0x39, 0x2e,
+	0xfb, 0xe6, 0xf8, 0x33, 0xe6, 0x18, 0xa2, 0x06, 0xe2, 0xec, 0x09, 0x13,
+	0xb1, 0xe3, 0xfd, 0xdd, 0x60, 0x5c, 0x39, 0x1b, 0x8c, 0x6f, 0xa2, 0xf1,
+	0x0d, 0x9b, 0xd6, 0xdb, 0x45, 0x72, 0xba, 0x43, 0xb4, 0xd4, 0x19, 0xa4,
+	0xca, 0x05, 0x13, 0x63, 0xef, 0xa3, 0xca, 0xaa, 0x5e, 0xe2, 0x38, 0xae,
+	0xc3, 0xc7, 0xe3, 0x5d, 0x09, 0x7c, 0x0e, 0xd2, 0xf8, 0x9a, 0xab, 0xb0,
+	0xb3, 0xe4, 0xb5, 0x7c, 0x83, 0x7e, 0x4c, 0xd7, 0xf6, 0x15, 0xb0, 0xa6,
+	0x12, 0xf9, 0x93, 0xfd, 0xf3, 0xe9, 0x80, 0x18, 0xf7, 0xc5, 0x45, 0xda,
+	0xe5, 0x3a, 0xa4, 0xb3, 0x3e, 0x9b, 0xc6, 0x2f, 0xd8, 0x5a, 0xbd, 0xc3,
+	0x3e, 0x63, 0xfc, 0xd9, 0x19, 0xfe, 0x4c, 0x2d, 0x3c, 0x53, 0xc4, 0x5c,
+	0x7f, 0x91, 0xa1, 0x27, 0xb1, 0x0f, 0x3a, 0x2d, 0x55, 0x7f, 0x04, 0xfb,
+	0xd0, 0xd7, 0xe5, 0x6f, 0xd7, 0xb3, 0x7e, 0xd6, 0x01, 0x7e, 0xf0, 0xef,
+	0xa7, 0x90, 0xb9, 0xe0, 0x08, 0xcb, 0x14, 0x69, 0x7c, 0x95, 0xf9, 0x05,
+	0x6d, 0x97, 0xdf, 0x79, 0x6d, 0x03, 0xd4, 0x80, 0x57, 0x1a, 0x53, 0x25,
+	0xd8, 0xa5, 0x2b, 0xbe, 0x68, 0x80, 0x3f, 0x74, 0x6f, 0x10, 0x2d, 0xcf,
+	0xf7, 0x73, 0x23, 0x8f, 0xa9, 0xb8, 0x33, 0x44, 0x75, 0xe0, 0xd7, 0x84,
+	0x3d, 0xcb, 0x34, 0x51, 0x3e, 0xaa, 0xbe, 0xa1, 0xaf, 0xc7, 0xdf, 0xc4,
+	0x6d, 0xdf, 0xf0, 0xde, 0xcb, 0x6d, 0x40, 0x6c, 0x7b, 0x2d, 0xcc, 0x62,
+	0x65, 0x7e, 0xe1, 0xf1, 0xcd, 0x32, 0xf6, 0x06, 0x7c, 0x46, 0xf0, 0x25,
+	0x51, 0xb7, 0x6d, 0x82, 0x6f, 0xf4, 0xaf, 0xea, 0x2c, 0x57, 0x62, 0x3d,
+	0x58, 0xff, 0x9a, 0xa9, 0xd5, 0xcf, 0x78, 0xce, 0x1f, 0x88, 0xe5, 0x2b,
+	0xf0, 0xc1, 0xc4, 0x4c, 0x8b, 0xc7, 0xf7, 0x2c, 0xf2, 0x56, 0x9b, 0xc2,
+	0xc4, 0x9e, 0xc2, 0x73, 0x54, 0xff, 0xc9, 0x08, 0xf6, 0xda, 0x75, 0x5a,
+	0xf4, 0x5b, 0xd8, 0x53, 0x20, 0xaf, 0x6b, 0xd2, 0x1b, 0x6d, 0xf6, 0x85,
+	0x4d, 0x95, 0x35, 0x29, 0x4f, 0xfa, 0xbc, 0x27, 0xbf, 0x83, 0x5f, 0x08,
+	0x2b, 0x9c, 0x98, 0xf9, 0x08, 0xfb, 0xb3, 0xde, 0xe3, 0xbd, 0xb1, 0x94,
+	0x4f, 0xbc, 0xd5, 0x29, 0xec, 0xeb, 0x54, 0x66, 0x23, 0xef, 0x97, 0x49,
+	0x2b, 0x55, 0x9d, 0xce, 0x57, 0x3f, 0x93, 0xba, 0xc7, 0xfc, 0x5a, 0x80,
+	0x6f, 0x31, 0xae, 0x8b, 0x71, 0x49, 0x01, 0x3e, 0xfc, 0x07, 0x78, 0x45,
+	0xca, 0xf3, 0x55, 0xf4, 0xaf, 0x1e, 0x87, 0xad, 0x06, 0x64, 0x53, 0x8c,
+	0xb1, 0x3d, 0x73, 0xed, 0x7c, 0x7d, 0xde, 0xcc, 0x7b, 0x4a, 0xdf, 0x10,
+	0x4d, 0x6e, 0x0c, 0xd1, 0xb3, 0xbd, 0x21, 0x1a, 0x3f, 0xcd, 0x32, 0xe0,
+	0xa6, 0xaa, 0x27, 0x22, 0xc6, 0xa8, 0xa7, 0xfc, 0x50, 0x36, 0x74, 0x5e,
+	0x27, 0xbe, 0x6f, 0x10, 0x2d, 0xf7, 0x78, 0x0e, 0xb3, 0x4f, 0xa7, 0x4e,
+	0x87, 0x7e, 0x4a, 0x74, 0xa8, 0xc7, 0xb2, 0x5b, 0xbe, 0x83, 0x5e, 0x01,
+	0x9d, 0x82, 0x38, 0x0f, 0x19, 0x1e, 0xf2, 0xdd, 0x7a, 0x88, 0xfc, 0x15,
+	0xe1, 0x37, 0x87, 0x9c, 0xc6, 0xeb, 0x9f, 0x42, 0xfc, 0x31, 0x8f, 0xdf,
+	0xc4, 0xda, 0x0b, 0xb4, 0xe2, 0xcf, 0x63, 0x0c, 0xef, 0xf1, 0x61, 0x7c,
+	0x1f, 0x46, 0x1e, 0xc8, 0xf2, 0x84, 0xe0, 0x3c, 0xb1, 0x1b, 0x71, 0x30,
+	0x00, 0xee, 0xdf, 0x63, 0x6e, 0xcf, 0x13, 0x18, 0x57, 0xda, 0x83, 0xbc,
+	0x70, 0x3f, 0xfa, 0x59, 0xd7, 0x28, 0xda, 0x01, 0xbc, 0xef, 0xc1, 0xd8,
+	0xfe, 0x1c, 0x91, 0xcb, 0xdd, 0x2d, 0x3f, 0x20, 0x26, 0x56, 0x11, 0x2b,
+	0x6b, 0x9c, 0x27, 0x38, 0x16, 0x79, 0x4f, 0x8b, 0xe0, 0x6f, 0x1b, 0x3a,
+	0x78, 0x6f, 0x8b, 0xd8, 0x43, 0xce, 0x71, 0x82, 0x2a, 0x1b, 0x3b, 0xe5,
+	0x0f, 0x5e, 0x0f, 0x38, 0xec, 0x34, 0xaf, 0xc5, 0x15, 0x0d, 0xf0, 0x59,
+	0xb8, 0x31, 0x8d, 0xef, 0xc8, 0x85, 0x22, 0xb2, 0x1b, 0xa7, 0x53, 0x2e,
+	0x6b, 0x6c, 0x8c, 0x29, 0x9c, 0xc6, 0x89, 0xc0, 0x3b, 0x73, 0x59, 0xce,
+	0x5d, 0x8c, 0x25, 0x0a, 0x20, 0xbb, 0x19, 0x1a, 0x52, 0x2e, 0xf9, 0x23,
+	0xd4, 0x00, 0x2e, 0x03, 0xf0, 0x59, 0x03, 0x7c, 0x56, 0xef, 0xe3, 0xb3,
+	0xfa, 0xe7, 0xf2, 0x19, 0xb8, 0xaa, 0x03, 0xae, 0xea, 0x80, 0xab, 0x50,
+	0x1b, 0xbc, 0x03, 0xec, 0xbf, 0xdd, 0xd9, 0x89, 0xe3, 0x98, 0xdf, 0x98,
+	0xe7, 0xa6, 0xe8, 0xf2, 0xde, 0xff, 0x94, 0xe7, 0x8e, 0x83, 0x13, 0x6c,
+	0xfa, 0xfe, 0xde, 0x7b, 0x73, 0xdd, 0x09, 0x70, 0x9d, 0xf5, 0xf9, 0x5c,
+	0xd7, 0x64, 0xae, 0x33, 0x81, 0xbd, 0x26, 0x78, 0x40, 0x5f, 0xed, 0x9f,
+	0xe7, 0x24, 0xe6, 0xe1, 0x3e, 0x33, 0xcb, 0xa5, 0x3a, 0x75, 0x81, 0x7b,
+	0xc3, 0xe3, 0x79, 0x60, 0x73, 0x92, 0x72, 0xd1, 0x13, 0x66, 0x89, 0xac,
+	0x49, 0xe0, 0x61, 0x75, 0x88, 0x8c, 0xd3, 0xb7, 0xf0, 0x8e, 0x7a, 0x00,
+	0x71, 0x8e, 0x7f, 0x1b, 0xb9, 0x8e, 0x41, 0x70, 0x8d, 0x49, 0x85, 0x55,
+	0x0b, 0xef, 0xda, 0xb6, 0x71, 0x87, 0x90, 0x6f, 0x8c, 0x9a, 0x3b, 0xf3,
+	0x7b, 0x7e, 0xee, 0xf1, 0x98, 0x41, 0xd2, 0xd7, 0x5c, 0xc7, 0xd1, 0x5d,
+	0xff, 0x1a, 0xb8, 0xe1, 0x7d, 0x8f, 0xf9, 0x2f, 0x06, 0x0a, 0x0a, 0x64,
+	0xae, 0xca, 0xe3, 0x56, 0x8d, 0xe7, 0x6e, 0x3a, 0x88, 0x73, 0xe7, 0x35,
+	0xe0, 0x87, 0x73, 0xe7, 0xf9, 0x2a, 0xd7, 0x7b, 0x69, 0x8c, 0xb6, 0x7a,
+	0xf9, 0x9c, 0xa3, 0xb0, 0xdb, 0x82, 0x4c, 0xff, 0x58, 0xc6, 0x8b, 0x94,
+	0xcf, 0x62, 0x4d, 0x06, 0xe6, 0xb1, 0xd6, 0x6c, 0x2a, 0xac, 0xb1, 0x5f,
+	0x5c, 0xc8, 0x57, 0xc4, 0x1c, 0x6d, 0x6e, 0xe3, 0x83, 0x93, 0xbd, 0x0f,
+	0x4c, 0xe6, 0x50, 0x03, 0xb1, 0x59, 0xc4, 0xbc, 0xd6, 0x96, 0x2e, 0xca,
+	0x74, 0xb1, 0xbc, 0x57, 0x7e, 0x76, 0x4b, 0x9e, 0x79, 0x6d, 0xa2, 0xcc,
+	0xfc, 0xc5, 0x76, 0x18, 0x8a, 0x4b, 0x07, 0x33, 0x2e, 0xad, 0x60, 0x3f,
+	0x07, 0x55, 0x5c, 0xea, 0xde, 0xc3, 0x19, 0x9f, 0xee, 0x46, 0xcb, 0x7d,
+	0x37, 0xb2, 0x38, 0x31, 0x61, 0x2f, 0xeb, 0x1d, 0x24, 0x03, 0x76, 0x45,
+	0x6a, 0x4d, 0x7f, 0x93, 0x4b, 0x1e, 0x73, 0x04, 0xe3, 0x53, 0x71, 0x29,
+	0xfa, 0x27, 0x60, 0x33, 0xf3, 0x02, 0xcb, 0xb1, 0xfc, 0x4e, 0x72, 0x7f,
+	0x85, 0x9c, 0xd8, 0x41, 0x0e, 0x7d, 0x1b, 0x2c, 0xc3, 0xdc, 0x30, 0x8a,
+	0xf1, 0x21, 0xf3, 0x02, 0x7c, 0xc6, 0xb2, 0xe5, 0x2c, 0x0e, 0x23, 0x7c,
+	0xe3, 0xba, 0x97, 0xe3, 0x23, 0x20, 0xab, 0xc6, 0xeb, 0xe0, 0x9a, 0x98,
+	0xf3, 0x22, 0xd7, 0xa1, 0x5c, 0x6f, 0xe6, 0xf5, 0xa9, 0x37, 0x35, 0x7b,
+	0xb7, 0x5a, 0x53, 0xf4, 0xd7, 0x9a, 0xe8, 0xd8, 0xb1, 0xd6, 0xf4, 0xac,
+	0xb4, 0xd6, 0xac, 0x58, 0x77, 0xaf, 0x35, 0x73, 0xd9, 0x7b, 0xd7, 0x9a,
+	0x71, 0x87, 0xf7, 0x08, 0xb9, 0x54, 0xf0, 0x5a, 0xa8, 0x69, 0x66, 0x7c,
+	0x11, 0xdd, 0xc6, 0x17, 0xd1, 0x69, 0xb7, 0x7c, 0x8e, 0x38, 0xa6, 0xdd,
+	0x72, 0x8b, 0x6b, 0xa0, 0x0d, 0xae, 0x81, 0x0c, 0xe4, 0xd2, 0x7e, 0xce,
+	0xc8, 0x7d, 0xc2, 0xbe, 0x1c, 0x04, 0x27, 0xb3, 0x1f, 0x8b, 0x19, 0x3f,
+	0xa0, 0xf5, 0x3e, 0x05, 0x3f, 0xe4, 0xbc, 0xc2, 0x3e, 0xfb, 0x7f, 0xe2,
+	0x15, 0xb2, 0x07, 0xc0, 0x0f, 0x36, 0xea, 0xcd, 0x46, 0x47, 0xd9, 0x02,
+	0x5f, 0x48, 0x39, 0xe7, 0x33, 0xf6, 0x53, 0xbe, 0x50, 0x3e, 0x51, 0x78,
+	0x2c, 0xd2, 0xbb, 0x3e, 0x63, 0x01, 0xe7, 0x23, 0x8f, 0x73, 0x22, 0xf3,
+	0xef, 0x4d, 0xf9, 0xae, 0x17, 0xa2, 0x2f, 0xc2, 0x9e, 0x33, 0x0e, 0xe6,
+	0xb5, 0x43, 0xeb, 0x36, 0xe4, 0x18, 0x0b, 0xe5, 0x3b, 0xce, 0x3d, 0xe9,
+	0xf9, 0x84, 0x6b, 0xe1, 0xff, 0x16, 0x1b, 0x17, 0xef, 0x82, 0x8d, 0x37,
+	0x33, 0x6c, 0xfc, 0xf2, 0x1e, 0xd8, 0xb8, 0xf8, 0x05, 0xb1, 0xe1, 0x3a,
+	0x1f, 0xa3, 0x5e, 0x7a, 0xcf, 0x63, 0x7c, 0x48, 0xf9, 0xb1, 0xbf, 0x53,
+	0x3e, 0x09, 0x6c, 0xe3, 0xd5, 0x9b, 0x32, 0xce, 0x72, 0x89, 0xfe, 0xd6,
+	0xad, 0x5c, 0x32, 0xfe, 0x6a, 0x8a, 0x8b, 0xf1, 0xb7, 0xa4, 0x3c, 0xb7,
+	0x03, 0x0e, 0xb8, 0x56, 0xbe, 0x0a, 0x1e, 0x68, 0xd1, 0xff, 0xa2, 0x56,
+	0x66, 0xce, 0xae, 0xda, 0x47, 0xdb, 0xf9, 0xbe, 0xe7, 0x7b, 0x5e, 0xa0,
+	0xb3, 0x62, 0x17, 0xfc, 0xb5, 0x9f, 0x5a, 0xaf, 0x9b, 0x7c, 0x7e, 0x00,
+	0x1e, 0x1e, 0x37, 0x39, 0x56, 0x71, 0x56, 0xc4, 0x73, 0x7f, 0x3d, 0x0d,
+	0x3c, 0xfa, 0xbc, 0x76, 0xb5, 0xee, 0x3e, 0xae, 0xff, 0x1e, 0x4a, 0x92,
+	0x3b, 0xf2, 0xc8, 0xb6, 0x73, 0xb3, 0x81, 0x73, 0x73, 0x5d, 0xe9, 0xe0,
+	0xb3, 0x55, 0xea, 0xbf, 0x13, 0xea, 0xac, 0x7c, 0x53, 0x9e, 0x53, 0xe7,
+	0xe5, 0xd1, 0x02, 0x0d, 0xce, 0x67, 0x58, 0x61, 0x5f, 0x0c, 0xab, 0x7a,
+	0x82, 0x31, 0xd5, 0x42, 0xbe, 0x5d, 0x82, 0x3f, 0x1a, 0x2a, 0x16, 0xb0,
+	0xf6, 0xcc, 0x1f, 0x2d, 0xf8, 0xa3, 0x9e, 0xa4, 0x31, 0xf1, 0xe5, 0x9e,
+	0x1d, 0xfe, 0x88, 0x7c, 0x6a, 0x2f, 0x9a, 0x38, 0x6f, 0x5f, 0x49, 0x54,
+	0xfe, 0x5c, 0x68, 0xb5, 0xa9, 0xf9, 0x60, 0xed, 0x38, 0xd7, 0x6d, 0x5c,
+	0x77, 0xcd, 0x2c, 0x55, 0xd1, 0xd7, 0xb3, 0x29, 0x84, 0x4f, 0xbe, 0x7d,
+	0x90, 0x16, 0x8d, 0x1a, 0xe3, 0x17, 0xef, 0x09, 0x35, 0xc3, 0x83, 0xa8,
+	0xa5, 0x92, 0xb1, 0x45, 0xbd, 0x36, 0x06, 0x1c, 0x35, 0x29, 0x80, 0x9d,
+	0x01, 0x74, 0xcf, 0xb5, 0x6d, 0x7b, 0xb9, 0xcd, 0x67, 0xa4, 0x26, 0xf1,
+	0x19, 0xbc, 0xdb, 0xbb, 0x0e, 0x7d, 0x03, 0xcf, 0xe0, 0xcc, 0xea, 0xc4,
+	0xc0, 0xd5, 0xcb, 0x89, 0x45, 0xad, 0x12, 0xdf, 0x51, 0x30, 0x57, 0x96,
+	0xa1, 0xe3, 0x99, 0x42, 0x8a, 0xcb, 0x32, 0xf4, 0x70, 0xcc, 0x10, 0xe6,
+	0x63, 0xff, 0xe5, 0x58, 0x2b, 0xf7, 0xd5, 0xee, 0x85, 0xec, 0xbc, 0x4a,
+	0xca, 0x07, 0xec, 0xdf, 0xd0, 0x7b, 0xbe, 0x90, 0xdf, 0xc7, 0xb4, 0x10,
+	0xf3, 0x8d, 0x7d, 0x8c, 0x43, 0x0d, 0x78, 0xc3, 0x98, 0x84, 0xfb, 0x90,
+	0x57, 0xf6, 0x21, 0x37, 0x97, 0x8a, 0xaa, 0x6d, 0x26, 0xc7, 0xb2, 0xf1,
+	0xba, 0x1a, 0xc7, 0x39, 0x21, 0x4e, 0xd4, 0x59, 0x41, 0x8b, 0x3a, 0xe4,
+	0x34, 0x7c, 0x9c, 0x81, 0x50, 0x5b, 0xac, 0x24, 0x9c, 0xcf, 0xf7, 0xd9,
+	0xba, 0xe2, 0xb9, 0x4d, 0xc8, 0xe0, 0x79, 0x83, 0xf4, 0x86, 0xcf, 0xf7,
+	0x07, 0xd9, 0xdd, 0x46, 0x89, 0x86, 0x21, 0x0f, 0xbb, 0xc6, 0xd8, 0xae,
+	0xa0, 0xa1, 0x6a, 0x11, 0xd6, 0xbd, 0x5f, 0x4f, 0xef, 0x5c, 0x7e, 0x93,
+	0xcd, 0x65, 0x83, 0x5f, 0x08, 0xe7, 0x1d, 0x9f, 0xf3, 0xda, 0xd7, 0x0c,
+	0xba, 0x4e, 0x8a, 0x23, 0xc5, 0x37, 0x90, 0xef, 0x0e, 0x42, 0x26, 0x50,
+	0xfc, 0x92, 0x9e, 0x19, 0x72, 0x99, 0x8a, 0xb1, 0x5d, 0xc7, 0x77, 0xcc,
+	0xed, 0xef, 0x01, 0x62, 0xab, 0x9a, 0xcd, 0xd7, 0x8f, 0xd3, 0x4d, 0xe0,
+	0x74, 0xb3, 0xb0, 0x75, 0xee, 0x28, 0x15, 0x30, 0x8e, 0x6d, 0x64, 0x2e,
+	0x61, 0x99, 0x4f, 0xac, 0xed, 0x7a, 0x2a, 0x3b, 0xe8, 0xf8, 0x53, 0x9f,
+	0x8e, 0x12, 0xaf, 0x4d, 0x34, 0xd2, 0xf3, 0xb3, 0xfa, 0x6b, 0xc0, 0xcf,
+	0x38, 0x6f, 0x3c, 0xa0, 0x63, 0x1d, 0x5c, 0x7f, 0xd5, 0x55, 0x3f, 0x0e,
+	0x56, 0xdb, 0xf4, 0xfe, 0x30, 0x9b, 0x67, 0x5f, 0x1a, 0x0f, 0x1e, 0xda,
+	0x64, 0xb3, 0xcf, 0x76, 0x6b, 0x87, 0x79, 0x91, 0xd8, 0xbd, 0x19, 0x8d,
+	0xf1, 0x66, 0xd4, 0x38, 0x07, 0xe3, 0x79, 0x0b, 0x1f, 0x8c, 0xd5, 0xcf,
+	0xc7, 0xa8, 0xf5, 0x05, 0x31, 0xfa, 0x46, 0x9b, 0xb9, 0x22, 0xc5, 0x68,
+	0xe3, 0x0e, 0x8c, 0xa2, 0x06, 0x2a, 0xe5, 0xf8, 0xe4, 0x78, 0xc9, 0xf1,
+	0x99, 0x3f, 0xf3, 0xfd, 0x08, 0x38, 0x38, 0xe3, 0xb6, 0x18, 0xdc, 0x16,
+	0xa9, 0x1c, 0xe7, 0x96, 0x23, 0x4a, 0xe3, 0x78, 0x19, 0x71, 0x1c, 0x19,
+	0x9c, 0xf3, 0x38, 0x86, 0x59, 0x8e, 0xe3, 0x98, 0xe5, 0x46, 0x32, 0x39,
+	0xb4, 0x88, 0xe7, 0x28, 0x8b, 0xe7, 0x16, 0x78, 0x37, 0xca, 0xe2, 0xb9,
+	0x85, 0x18, 0x5e, 0xc9, 0xe2, 0xb9, 0x95, 0xc5, 0x33, 0xdf, 0xdb, 0x19,
+	0x55, 0x95, 0x8b, 0x9d, 0x3a, 0x78, 0x6d, 0x45, 0xe9, 0x6c, 0x62, 0x9d,
+	0xb0, 0xb1, 0x93, 0xc7, 0xc5, 0x1d, 0xf7, 0x5b, 0x58, 0xcf, 0xad, 0xbc,
+	0x32, 0x8b, 0xbc, 0x72, 0x0e, 0x79, 0xa5, 0xdb, 0x77, 0xbf, 0x75, 0x56,
+	0xe5, 0x95, 0x27, 0x8b, 0x79, 0x5e, 0xe9, 0x66, 0x79, 0xa5, 0xab, 0xf2,
+	0xca, 0x13, 0x45, 0xce, 0x2b, 0x31, 0x05, 0xc5, 0xfe, 0xbc, 0x12, 0x6f,
+	0xcb, 0x2b, 0xb9, 0x2c, 0xf7, 0xef, 0x94, 0x57, 0x72, 0x9f, 0x71, 0x6e,
+	0xb1, 0x72, 0x5e, 0xbd, 0x2d, 0x9f, 0xe4, 0x63, 0xd8, 0x56, 0xe6, 0x25,
+	0xe6, 0xe0, 0xb4, 0xae, 0xbf, 0x92, 0xe4, 0xb1, 0x74, 0x0c, 0xf3, 0xe0,
+	0xbd, 0xb3, 0x53, 0x2c, 0xd9, 0x59, 0x2c, 0x0d, 0xa7, 0x32, 0x9d, 0xfe,
+	0x78, 0x3a, 0x56, 0xdc, 0x1e, 0x4f, 0xb9, 0x9e, 0x3c, 0x9e, 0x52, 0x9d,
+	0x1f, 0x1a, 0x65, 0xae, 0x07, 0x70, 0x96, 0x76, 0xfd, 0x39, 0xf4, 0x5e,
+	0xe8, 0x4d, 0xa3, 0xae, 0x36, 0xe9, 0x6a, 0xce, 0x37, 0xea, 0xbe, 0x07,
+	0x6d, 0x2f, 0xb7, 0xb5, 0xb8, 0xf5, 0xad, 0x8b, 0xda, 0xfa, 0x7d, 0xf0,
+	0xc8, 0x79, 0xf5, 0xfd, 0x33, 0x79, 0xb5, 0x84, 0x33, 0xb0, 0x97, 0x8f,
+	0x7b, 0x1d, 0xf3, 0xb9, 0xe2, 0x2c, 0x9e, 0x5e, 0xee, 0xdd, 0x82, 0xf9,
+	0x8a, 0xc7, 0x7d, 0xff, 0x44, 0x0e, 0x41, 0x5d, 0xbe, 0x35, 0x96, 0xcf,
+	0x38, 0x1e, 0xd6, 0xec, 0xd0, 0xa5, 0x6d, 0xe7, 0x9c, 0xf4, 0x7c, 0x83,
+	0x75, 0xa3, 0x3e, 0xe1, 0x3a, 0x25, 0xfc, 0x8a, 0x4e, 0x2f, 0xd1, 0xb7,
+	0x7c, 0xee, 0xd3, 0x69, 0xf6, 0x31, 0x29, 0x5f, 0x40, 0xcd, 0xf2, 0xf4,
+	0xb6, 0x9a, 0xa5, 0x48, 0xe3, 0x07, 0xfa, 0xcf, 0x87, 0x37, 0xe5, 0xf8,
+	0xa4, 0x7b, 0x36, 0xa0, 0x40, 0x9b, 0x5d, 0xe7, 0x5a, 0x76, 0xab, 0x76,
+	0x25, 0x1a, 0xbd, 0x21, 0xf5, 0x49, 0xce, 0x85, 0x57, 0x33, 0x5f, 0xe1,
+	0xdb, 0x99, 0x1b, 0xe0, 0xd6, 0x48, 0xdd, 0xf1, 0x06, 0xeb, 0x3c, 0x0f,
+	0xbf, 0xa3, 0x4d, 0xb8, 0xbe, 0xb9, 0xdb, 0xbd, 0xab, 0x89, 0x7d, 0x71,
+	0x9d, 0xa3, 0x06, 0xa9, 0xbb, 0x8b, 0x25, 0xdf, 0xfd, 0x59, 0x8b, 0x52,
+	0x9e, 0x88, 0xfc, 0x05, 0xd8, 0x02, 0x9c, 0x8b, 0x45, 0xec, 0xcd, 0x24,
+	0x78, 0xc9, 0x75, 0x0e, 0xe8, 0x42, 0x61, 0x7f, 0x19, 0xba, 0x8d, 0x03,
+	0x5c, 0x3f, 0x7e, 0x2a, 0x97, 0x7b, 0x2a, 0x07, 0xfb, 0x8c, 0x91, 0x7a,
+	0xb2, 0x5b, 0xe7, 0x36, 0x48, 0xf8, 0xb9, 0x80, 0x79, 0x9c, 0xbb, 0xe0,
+	0xa7, 0x24, 0xa2, 0x33, 0x8e, 0x98, 0xed, 0x38, 0x62, 0xae, 0xa3, 0x03,
+	0xdd, 0xb6, 0x4d, 0xbb, 0xb0, 0x27, 0xc8, 0xc1, 0xf4, 0x00, 0x6c, 0xb9,
+	0xe0, 0x88, 0x3a, 0x6a, 0xc1, 0x1f, 0x18, 0xae, 0x78, 0x9a, 0x3e, 0xc1,
+	0x1a, 0x6f, 0xc8, 0xf4, 0xde, 0xc5, 0x11, 0xd1, 0xd6, 0xdc, 0x37, 0x30,
+	0x37, 0xdb, 0xc4, 0x31, 0xca, 0xf9, 0x72, 0x5e, 0x5b, 0x80, 0x8f, 0x8e,
+	0xac, 0x6b, 0xe0, 0x35, 0xce, 0x97, 0x23, 0xd9, 0xfd, 0x12, 0xf6, 0x07,
+	0xeb, 0xbf, 0x74, 0x47, 0xad, 0x99, 0xd7, 0x94, 0xe9, 0xdd, 0x69, 0x3c,
+	0xc3, 0xf3, 0x13, 0x6c, 0x99, 0x98, 0xba, 0xa0, 0xce, 0x3d, 0xd3, 0xa8,
+	0xf1, 0xb8, 0x95, 0xa8, 0x83, 0xf8, 0xae, 0x8b, 0x6b, 0x27, 0x89, 0xf8,
+	0x4f, 0x9f, 0x63, 0x3e, 0x13, 0xcd, 0xb0, 0x0e, 0x3e, 0x1b, 0x71, 0xfc,
+	0xfc, 0x1b, 0x2f, 0xf3, 0x0a, 0xbd, 0x68, 0x18, 0x00, 0x00, 0x00 };
+
+static const u32 bnx2_TPAT_b09FwData[(0x0/4) + 1] = { 0x0 };
+static const u32 bnx2_TPAT_b09FwRodata[(0x0/4) + 1] = { 0x0 };
+static const u32 bnx2_TPAT_b09FwBss[(0x850/4) + 1] = { 0x0 };
+static const u32 bnx2_TPAT_b09FwSbss[(0x2c/4) + 1] = { 0x0 };
 
 static struct fw_info bnx2_tpat_fw_09 = {
-	.ver_major			= 0x1,
-	.ver_minor			= 0x0,
-	.ver_fix			= 0x0,
+	.ver_major			= 0x3,
+	.ver_minor			= 0x4,
+	.ver_fix			= 0x3,
 
 	.start_addr			= 0x08000860,
 
 	.text_addr			= 0x08000800,
-	.text_len			= 0x1480,
+	.text_len			= 0x1864,
 	.text_index			= 0x0,
 	.gz_text			= bnx2_TPAT_b09FwText,
 	.gz_text_len			= sizeof(bnx2_TPAT_b09FwText),
 
-	.data_addr			= 0x08001ca0,
+	.data_addr			= 0x08002080,
 	.data_len			= 0x0,
 	.data_index			= 0x0,
 	.data				= bnx2_TPAT_b09FwData,
 
-	.sbss_addr			= 0x08001ca0,
-	.sbss_len			= 0x34,
+	.sbss_addr			= 0x08002088,
+	.sbss_len			= 0x2c,
 	.sbss_index			= 0x0,
 	.sbss				= bnx2_TPAT_b09FwSbss,
 
-	.bss_addr			= 0x08001ce0,
-	.bss_len			= 0x250,
+	.bss_addr			= 0x080020c0,
+	.bss_len			= 0x850,
 	.bss_index			= 0x0,
 	.bss				= bnx2_TPAT_b09FwBss,
 
@@ -3308,732 +3279,769 @@
 };
 
 static u8 bnx2_TXP_b09FwText[] = {
-	0x1f, 0x8b, 0x08, 0x08, 0x51, 0xfe, 0x2f, 0x45, 0x00, 0x03, 0x74, 0x65,
-	0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, 0xcd, 0x7b, 0x7f, 0x70,
-	0x1b, 0xe7, 0x99, 0xde, 0xbb, 0x0b, 0x80, 0x04, 0x29, 0x8a, 0x5a, 0x31,
-	0x30, 0x83, 0x38, 0xb4, 0x8d, 0x15, 0x17, 0x34, 0x6d, 0xf2, 0x1c, 0x58,
-	0xe5, 0xf9, 0xd8, 0x06, 0xb5, 0xd7, 0xc0, 0x92, 0xa2, 0x63, 0x26, 0x47,
-	0xbb, 0xcc, 0x9d, 0x92, 0x51, 0x7d, 0x28, 0x48, 0x29, 0x6e, 0xe3, 0xb4,
-	0xaa, 0xe3, 0x3f, 0x34, 0x4d, 0x5b, 0xc3, 0x00, 0x25, 0xcb, 0x2e, 0x44,
-	0xd0, 0x16, 0x63, 0xa5, 0x33, 0x37, 0x53, 0x18, 0x80, 0x28, 0xe7, 0xba,
-	0x24, 0xdc, 0xe4, 0x2e, 0xe9, 0x1f, 0xc9, 0x99, 0xa5, 0x6c, 0xc5, 0x6d,
-	0xae, 0x33, 0xbe, 0x3f, 0xda, 0xa6, 0x37, 0xd7, 0x19, 0x8d, 0xfc, 0x23,
-	0xce, 0x8f, 0xb9, 0xb8, 0x69, 0x7a, 0x56, 0x5b, 0xd9, 0xe8, 0xf3, 0x7c,
-	0xbb, 0x4b, 0x82, 0x32, 0x15, 0x5b, 0xd7, 0x76, 0xa6, 0x9c, 0xc1, 0x10,
-	0xfb, 0xed, 0xb7, 0xdf, 0xf7, 0xfe, 0x7e, 0xdf, 0xe7, 0xfd, 0x16, 0x71,
-	0x91, 0x6e, 0xf1, 0xff, 0x76, 0xe3, 0x93, 0x38, 0x7a, 0xec, 0xb1, 0x3b,
-	0xc6, 0xef, 0xd8, 0x2f, 0x72, 0xe7, 0x9d, 0xb2, 0x2b, 0xaa, 0xf3, 0xe6,
-	0xdb, 0x21, 0x91, 0xdc, 0x4f, 0xe5, 0xaf, 0xfc, 0x87, 0xc7, 0x8d, 0x60,
-	0x7d, 0x7e, 0x24, 0xaa, 0xa7, 0x5f, 0xcc, 0x64, 0x2c, 0x89, 0x86, 0xd2,
-	0x33, 0x9f, 0x9d, 0xb3, 0x44, 0x6c, 0x77, 0x24, 0x91, 0x95, 0xf7, 0x5a,
-	0x85, 0x58, 0x58, 0x38, 0x7e, 0x53, 0xfa, 0xca, 0xe3, 0xdf, 0xff, 0x2d,
-	0xf3, 0x9d, 0x6a, 0x48, 0xa2, 0x46, 0x3a, 0x27, 0xc6, 0x90, 0x44, 0x07,
-	0xf0, 0xcc, 0xef, 0xdf, 0x3a, 0xa5, 0x4b, 0x6f, 0xb0, 0x56, 0x5c, 0x16,
-	0x2a, 0x6f, 0xb7, 0xbe, 0x7f, 0x6b, 0x4c, 0xfe, 0x55, 0xd3, 0x90, 0x17,
-	0x9b, 0x61, 0x6d, 0xb2, 0xd2, 0x23, 0xa5, 0x8a, 0x2b, 0xc7, 0xcb, 0x05,
-	0xc9, 0x36, 0x5f, 0x90, 0xe2, 0xb2, 0xd1, 0x9b, 0x39, 0xf7, 0x07, 0x52,
-	0x5a, 0xee, 0xeb, 0xcd, 0x9e, 0x73, 0xa5, 0x58, 0x8e, 0xf7, 0x66, 0x9a,
-	0x46, 0x6f, 0xf6, 0x4c, 0x0c, 0xd7, 0x7d, 0xbd, 0x99, 0x33, 0x66, 0x41,
-	0xa4, 0x1f, 0x73, 0xe2, 0xbd, 0xd9, 0x8a, 0x99, 0x13, 0x19, 0x4c, 0xbd,
-	0x22, 0x03, 0xbd, 0xd9, 0x66, 0x4d, 0x5b, 0x37, 0x34, 0x29, 0xfe, 0x86,
-	0x18, 0xbd, 0xe9, 0xcb, 0xad, 0x4f, 0x58, 0x86, 0xec, 0xb5, 0x64, 0xcf,
-	0x1e, 0x4b, 0x9e, 0x88, 0xa7, 0xa3, 0x92, 0x3f, 0xdd, 0x25, 0xb6, 0xe2,
-	0xc9, 0x90, 0xfc, 0x99, 0x11, 0x63, 0x43, 0x22, 0x62, 0xc7, 0x82, 0xeb,
-	0x56, 0x2b, 0x93, 0xfa, 0x02, 0xe5, 0x8a, 0xbd, 0xa4, 0x77, 0xb2, 0x29,
-	0x92, 0xa9, 0x44, 0x25, 0x93, 0x7a, 0xaf, 0xe5, 0x3d, 0x13, 0xc5, 0xbe,
-	0xe1, 0xde, 0x89, 0x4a, 0xab, 0xe5, 0xa4, 0xb0, 0x47, 0x2a, 0x78, 0x36,
-	0x22, 0xd5, 0x98, 0x5d, 0x2d, 0xa5, 0x4c, 0xdd, 0xd3, 0x09, 0x79, 0xe4,
-	0xb5, 0x2d, 0xba, 0xf5, 0xdb, 0x92, 0x8f, 0x49, 0xb5, 0x98, 0xba, 0x4b,
-	0x9e, 0x4e, 0x19, 0x72, 0x12, 0xeb, 0x3d, 0x95, 0x82, 0x1c, 0xad, 0x63,
-	0x5a, 0xa6, 0x69, 0xc6, 0x45, 0x7b, 0x5a, 0x32, 0x67, 0x06, 0x8d, 0xac,
-	0x60, 0x6f, 0xab, 0x75, 0x4b, 0x26, 0x85, 0xfd, 0x46, 0xff, 0x67, 0xcb,
-	0x8e, 0x99, 0xb9, 0xaa, 0x0c, 0x48, 0xb1, 0x32, 0x98, 0xfa, 0x13, 0xd1,
-	0xa4, 0xd3, 0xa2, 0x7c, 0x5a, 0x72, 0x3f, 0xf6, 0xcd, 0x58, 0x18, 0x6f,
-	0x8a, 0xad, 0x27, 0x23, 0xf2, 0x0f, 0x0c, 0x33, 0x91, 0x09, 0xf5, 0x4b,
-	0xf1, 0x74, 0x27, 0xe8, 0xb4, 0xfb, 0x74, 0xcc, 0x3d, 0x30, 0x26, 0xb1,
-	0x5d, 0x22, 0x5a, 0x28, 0x9d, 0xc4, 0xba, 0x22, 0x45, 0x77, 0x00, 0xcf,
-	0x26, 0xc7, 0x7f, 0x2a, 0x7b, 0x24, 0xb1, 0x37, 0x2c, 0x25, 0xb7, 0x1b,
-	0x72, 0x34, 0xa0, 0x83, 0xe4, 0xf8, 0x5f, 0x40, 0x29, 0xba, 0x95, 0x8c,
-	0x1f, 0x93, 0x9c, 0x96, 0x6d, 0x76, 0x48, 0x29, 0x19, 0x95, 0x05, 0xd0,
-	0xb1, 0x90, 0xfa, 0xa2, 0x96, 0x39, 0x77, 0x50, 0xcb, 0x9e, 0xc3, 0xbc,
-	0x66, 0xdd, 0xb7, 0x35, 0x03, 0xeb, 0xe8, 0x52, 0x4c, 0x1e, 0xc4, 0xbd,
-	0xa8, 0xcc, 0x61, 0xde, 0x1c, 0x78, 0x2a, 0x35, 0xf7, 0xc8, 0xfa, 0x6c,
-	0xac, 0x37, 0x03, 0x1d, 0x16, 0x71, 0xff, 0xb7, 0x67, 0x34, 0x31, 0x2c,
-	0x5b, 0x7e, 0x3c, 0x06, 0x1d, 0x9e, 0x81, 0xfe, 0xce, 0xc4, 0xe5, 0x78,
-	0x45, 0x62, 0xba, 0x24, 0xe3, 0x79, 0x79, 0x41, 0xea, 0x2e, 0xf5, 0x0f,
-	0x7d, 0x42, 0xdf, 0x45, 0x97, 0xcf, 0x41, 0x6f, 0x15, 0x07, 0xf2, 0x98,
-	0x02, 0x0d, 0x0f, 0x6a, 0xf7, 0xd7, 0x67, 0xb5, 0x03, 0xcd, 0x1f, 0x6b,
-	0xd2, 0x7d, 0x4c, 0xfb, 0x5c, 0xf3, 0x88, 0xe6, 0xcb, 0x1e, 0xba, 0x8b,
-	0x8a, 0x3d, 0x13, 0x95, 0x95, 0xa6, 0xa7, 0xbb, 0x1a, 0xec, 0xd3, 0x36,
-	0x6c, 0xe8, 0xe1, 0x6f, 0x6f, 0xce, 0x59, 0x69, 0xc6, 0x64, 0x01, 0xb4,
-	0x1d, 0x6f, 0x72, 0xfe, 0xef, 0x41, 0x3f, 0x51, 0x71, 0x6f, 0xed, 0x91,
-	0x1c, 0xc6, 0x8b, 0x67, 0xc4, 0xce, 0xa4, 0x74, 0x3c, 0xd3, 0x2b, 0x21,
-	0xab, 0x1f, 0x9f, 0x6e, 0x99, 0xab, 0x77, 0xda, 0x21, 0x2b, 0x26, 0x73,
-	0x4d, 0xca, 0x10, 0xff, 0x2b, 0x81, 0x1c, 0x49, 0x2b, 0xc7, 0xf9, 0x1c,
-	0xc7, 0x0d, 0x8c, 0xb7, 0x8f, 0xd1, 0x2e, 0x7a, 0x41, 0x8f, 0x39, 0x2c,
-	0x18, 0xcb, 0x57, 0x92, 0xc6, 0xe7, 0xf8, 0xbf, 0x49, 0xd9, 0x06, 0x32,
-	0x0d, 0x63, 0xae, 0x2e, 0xf9, 0x3a, 0xf6, 0x39, 0x7d, 0xa5, 0x15, 0x19,
-	0xc3, 0xb5, 0xf5, 0x4b, 0xc8, 0x92, 0xfb, 0x86, 0x41, 0x93, 0x2e, 0xb9,
-	0x3a, 0xd7, 0xe2, 0x7d, 0x81, 0xee, 0x8b, 0x7b, 0x75, 0x19, 0x86, 0x7e,
-	0x4d, 0xec, 0xd3, 0x85, 0x39, 0x3d, 0x90, 0x1f, 0x78, 0x3d, 0x87, 0xef,
-	0xe0, 0x5d, 0xb7, 0x74, 0x3c, 0xdf, 0x29, 0x73, 0x29, 0xda, 0x0b, 0xe9,
-	0xdc, 0x85, 0xb5, 0xbb, 0x64, 0xfe, 0x34, 0xe5, 0x01, 0xbb, 0xaa, 0xc4,
-	0xa4, 0x74, 0xc6, 0x34, 0x1c, 0x31, 0x21, 0x1b, 0x1b, 0xf3, 0x3a, 0x25,
-	0x67, 0xb4, 0x5a, 0x13, 0xa9, 0x11, 0xe3, 0x9b, 0xca, 0xce, 0x47, 0x8c,
-	0xa4, 0x26, 0x85, 0x8e, 0xf4, 0x10, 0x64, 0x6b, 0x1e, 0x14, 0xe1, 0xf5,
-	0x0f, 0xc4, 0x9e, 0xa5, 0xff, 0xc4, 0xb8, 0x17, 0xfc, 0xa9, 0x1f, 0xf4,
-	0xd3, 0xe7, 0x06, 0xa0, 0x97, 0xb8, 0xf2, 0x83, 0x89, 0x1d, 0xfd, 0xc0,
-	0x9c, 0xaa, 0x82, 0xdf, 0xe2, 0xb9, 0x30, 0xfd, 0x2f, 0x05, 0x73, 0x93,
-	0x5d, 0x56, 0x14, 0xb6, 0x40, 0x5a, 0xc6, 0xb1, 0x7e, 0xab, 0xf5, 0xd9,
-	0x94, 0x47, 0x53, 0xf1, 0x8c, 0x8d, 0x67, 0xc3, 0x90, 0xbb, 0xf9, 0x70,
-	0x42, 0xed, 0x3f, 0xee, 0xef, 0x6f, 0xc8, 0x1c, 0xe8, 0x2e, 0x56, 0x42,
-	0x92, 0x35, 0xb8, 0xc6, 0x9f, 0x71, 0x3c, 0xe7, 0xad, 0x05, 0xbb, 0x3d,
-	0x35, 0x68, 0xdc, 0x07, 0x5f, 0xa2, 0x8f, 0x15, 0x57, 0x29, 0x63, 0xac,
-	0x33, 0x46, 0x19, 0x1b, 0x8a, 0xc6, 0xcc, 0x19, 0xda, 0x91, 0x0c, 0x84,
-	0x84, 0x76, 0x8e, 0x98, 0x01, 0xbb, 0x2a, 0xf9, 0x76, 0x95, 0x77, 0xa9,
-	0xff, 0xbb, 0x7d, 0xff, 0xd4, 0x65, 0x28, 0x49, 0x7b, 0x7f, 0x5a, 0xb2,
-	0xf0, 0xf1, 0x39, 0xec, 0x54, 0x07, 0x4f, 0xb5, 0xca, 0x20, 0x64, 0x15,
-	0xf8, 0x1d, 0xf4, 0x3b, 0xfa, 0x6e, 0x2b, 0x88, 0x05, 0xc5, 0x0a, 0x7d,
-	0xa6, 0x68, 0xe8, 0x52, 0xc0, 0x07, 0x76, 0x63, 0x99, 0xc3, 0x99, 0x90,
-	0x39, 0x93, 0x03, 0x6d, 0xb0, 0x7b, 0xc9, 0xdc, 0x49, 0x7b, 0xc6, 0x9c,
-	0xa6, 0xec, 0x0f, 0xfc, 0xac, 0xe6, 0x52, 0x4f, 0xdd, 0xd8, 0x37, 0xa0,
-	0x29, 0x8c, 0x31, 0xae, 0x13, 0x85, 0xcd, 0x07, 0x36, 0x43, 0xfb, 0x33,
-	0xed, 0x75, 0xe9, 0x90, 0xe1, 0x24, 0x62, 0xd9, 0x19, 0x1d, 0xfa, 0x1b,
-	0x40, 0x4c, 0x09, 0xcb, 0x11, 0xc8, 0xea, 0x4b, 0x15, 0xd2, 0xe7, 0xc0,
-	0xef, 0x10, 0xdb, 0xce, 0x4c, 0xc2, 0xcf, 0xa6, 0xb4, 0x09, 0xf8, 0xc4,
-	0x67, 0xea, 0xa4, 0xa9, 0x25, 0xf4, 0x4b, 0xe7, 0x5c, 0x4e, 0x9b, 0x6c,
-	0x1e, 0xd4, 0xa6, 0xce, 0xd1, 0x4f, 0xe8, 0x23, 0xa6, 0xf1, 0x80, 0x78,
-	0x3c, 0x14, 0x9b, 0xaf, 0x68, 0xf4, 0xd5, 0xe2, 0xa9, 0x2e, 0xd0, 0xb1,
-	0x0b, 0xf4, 0x18, 0xf0, 0x3d, 0xd8, 0x97, 0x65, 0xce, 0xd0, 0x66, 0x9c,
-	0xa4, 0x95, 0xf8, 0xe7, 0xf2, 0x41, 0x39, 0x4c, 0x6c, 0xca, 0x61, 0x04,
-	0x32, 0xd9, 0x2e, 0x87, 0x85, 0x0f, 0xca, 0xc1, 0x2e, 0x40, 0x0e, 0x0b,
-	0x88, 0x43, 0x0b, 0x4d, 0xf2, 0xdc, 0x12, 0xfd, 0x4e, 0x81, 0x75, 0xca,
-	0xbd, 0x7a, 0x9a, 0x36, 0x4a, 0x3f, 0x49, 0x26, 0x4a, 0x58, 0xa1, 0xe1,
-	0xf6, 0x28, 0xdf, 0x98, 0x54, 0xb2, 0xf8, 0x30, 0x7e, 0xc9, 0xdf, 0x16,
-	0xcf, 0x53, 0x75, 0xc6, 0x1b, 0xd8, 0x79, 0xd2, 0x32, 0xbe, 0x20, 0x5b,
-	0x7c, 0xdf, 0xb7, 0xc5, 0x37, 0xf6, 0x09, 0x62, 0x10, 0x79, 0x0e, 0xe2,
-	0x31, 0x6d, 0xe5, 0xa5, 0x56, 0xc8, 0xb2, 0xa0, 0x03, 0xda, 0x0b, 0x69,
-	0x30, 0x8d, 0xcf, 0x0a, 0xfe, 0x23, 0x2e, 0xd0, 0x97, 0x72, 0x6a, 0x5e,
-	0x87, 0xe4, 0xf6, 0x7a, 0xf3, 0xe7, 0x2a, 0xad, 0x5f, 0xe8, 0xe9, 0xf7,
-	0x5b, 0x99, 0x31, 0xcb, 0xf7, 0xf1, 0xa8, 0x7c, 0xb9, 0x6e, 0xe6, 0x12,
-	0x5a, 0x8f, 0x14, 0x6e, 0x40, 0x5c, 0xa9, 0xd0, 0x3f, 0xfa, 0xaf, 0x11,
-	0xcb, 0x06, 0xfc, 0x58, 0xf6, 0x13, 0xc8, 0x9e, 0xb9, 0xe7, 0xf0, 0xfb,
-	0xeb, 0x31, 0xfe, 0x4f, 0x1a, 0x33, 0xf2, 0x05, 0xe6, 0x9b, 0x3d, 0xba,
-	0x8a, 0xdf, 0x16, 0x73, 0x41, 0x21, 0x9c, 0xee, 0x96, 0xc2, 0x5e, 0x29,
-	0x84, 0xd2, 0xf4, 0x23, 0xfa, 0x46, 0x87, 0x4f, 0x77, 0x90, 0x3b, 0xf8,
-	0x77, 0x4c, 0x17, 0x8b, 0x73, 0x90, 0x27, 0x2a, 0xe4, 0xe3, 0xbd, 0x40,
-	0x27, 0x78, 0x46, 0x22, 0x9e, 0xcd, 0x4d, 0x23, 0x66, 0x52, 0xa6, 0xed,
-	0xf6, 0xc2, 0x58, 0x2a, 0x09, 0xdd, 0x62, 0x2c, 0x15, 0x23, 0x94, 0x7e,
-	0x50, 0xb3, 0xeb, 0x5f, 0xd4, 0x6c, 0xc8, 0xce, 0x86, 0xec, 0x6c, 0xc8,
-	0x2e, 0x03, 0xd9, 0x65, 0x9b, 0xa4, 0x87, 0xb4, 0x78, 0xeb, 0x3b, 0xde,
-	0xfa, 0xa0, 0xb3, 0x5f, 0xf2, 0xca, 0xc7, 0xc9, 0x2f, 0x62, 0xb2, 0x8a,
-	0x07, 0x93, 0x9a, 0x17, 0x0f, 0xb8, 0xde, 0x14, 0x9e, 0xbf, 0x1b, 0x79,
-	0xce, 0xd6, 0x75, 0x6b, 0x4b, 0x26, 0x0b, 0x6d, 0x32, 0x29, 0xb9, 0x94,
-	0x11, 0xe7, 0xd3, 0x97, 0x5d, 0xe8, 0x3d, 0x90, 0xcb, 0x34, 0x68, 0xe8,
-	0x24, 0xef, 0x3e, 0x1f, 0x5c, 0xbf, 0xcf, 0x5f, 0xff, 0xd3, 0x58, 0x93,
-	0xbe, 0xbb, 0xd3, 0xbe, 0xdc, 0x93, 0xb9, 0xf4, 0xd7, 0xf1, 0x83, 0x5a,
-	0x02, 0x31, 0xfa, 0x45, 0xf8, 0xda, 0xc5, 0x50, 0x5c, 0xbe, 0x7f, 0xeb,
-	0x6b, 0xa8, 0x2f, 0xa4, 0x70, 0x63, 0xba, 0x95, 0x08, 0xa7, 0xdf, 0x6b,
-	0x2d, 0x8c, 0x21, 0x7e, 0xa6, 0xcd, 0x78, 0x26, 0x34, 0x2a, 0x2f, 0x35,
-	0x87, 0xe5, 0x3b, 0x4d, 0x4b, 0xfe, 0xa8, 0x99, 0x90, 0x3f, 0x6c, 0x0e,
-	0xc8, 0xb7, 0x9b, 0x71, 0xf9, 0x56, 0x33, 0xa8, 0x45, 0xe2, 0xb4, 0xa5,
-	0x5e, 0xa7, 0xb9, 0x53, 0x3d, 0x04, 0x3b, 0xc7, 0x5a, 0x99, 0xb1, 0x70,
-	0x2e, 0x94, 0x56, 0x35, 0xc2, 0xcc, 0xd1, 0xf2, 0xe3, 0x2d, 0xdd, 0xb2,
-	0x0a, 0xba, 0xde, 0x33, 0x6e, 0xdc, 0x25, 0x39, 0x3d, 0x8d, 0x31, 0x77,
-	0x3c, 0xec, 0x94, 0xbb, 0x90, 0x5f, 0xa2, 0xa8, 0x65, 0x06, 0xa4, 0x80,
-	0x75, 0x0b, 0xcd, 0x56, 0x6b, 0x29, 0xf5, 0x0f, 0x3f, 0x65, 0xfc, 0x8d,
-	0x7f, 0xd9, 0x29, 0xbd, 0xdf, 0x5e, 0x37, 0x86, 0xfe, 0xbb, 0x5f, 0x0f,
-	0xa1, 0xc6, 0xea, 0x57, 0x8b, 0xe7, 0xb4, 0xf4, 0xa8, 0x93, 0x70, 0x37,
-	0x70, 0x5f, 0xa2, 0xfd, 0xd6, 0xcf, 0x51, 0x85, 0xc8, 0xee, 0x98, 0xc5,
-	0x9a, 0x6b, 0x26, 0xfb, 0x79, 0xfc, 0xff, 0x58, 0x5a, 0xf6, 0xf4, 0xe1,
-	0xff, 0xde, 0x34, 0x4c, 0x2a, 0xcd, 0x98, 0xac, 0xb5, 0xc5, 0x64, 0xd1,
-	0x1c, 0xe4, 0xdf, 0x05, 0xf0, 0xe4, 0x40, 0x1e, 0xbf, 0xd3, 0x8c, 0x6a,
-	0xd9, 0xd3, 0xfd, 0x52, 0xaa, 0x33, 0xaf, 0x71, 0x5e, 0xd4, 0xaf, 0x7b,
-	0x78, 0xdd, 0x81, 0x6b, 0x41, 0xae, 0xf9, 0x94, 0x48, 0xaf, 0xf9, 0xa3,
-	0xcf, 0x4b, 0xdd, 0xaf, 0x5b, 0x22, 0xb2, 0xac, 0x6c, 0x8c, 0xe3, 0xaf,
-	0x65, 0xbf, 0x36, 0xb4, 0x35, 0xfe, 0xec, 0xe6, 0xf8, 0x3b, 0xd9, 0x4f,
-	0x6f, 0x8e, 0x77, 0x87, 0x3d, 0x1e, 0xc6, 0xb5, 0x99, 0x66, 0xc1, 0x1f,
-	0xbb, 0x0c, 0xb9, 0xb7, 0x5a, 0x0b, 0xc8, 0x3d, 0x45, 0xeb, 0x32, 0xea,
-	0x24, 0xc6, 0x9f, 0xeb, 0x89, 0x37, 0xdb, 0x62, 0x8d, 0x91, 0x09, 0x51,
-	0x9f, 0x51, 0xf1, 0xd6, 0xe4, 0xfd, 0x4e, 0xc4, 0x9d, 0xcb, 0xf8, 0xce,
-	0x3c, 0x17, 0xc4, 0x3c, 0xce, 0xe1, 0xf3, 0x6f, 0x5f, 0x43, 0xe7, 0x31,
-	0xe8, 0xfc, 0xff, 0x1b, 0xdd, 0xe2, 0x4f, 0xe9, 0x56, 0xc5, 0x9d, 0x97,
-	0xb6, 0xd9, 0x2c, 0xe9, 0xef, 0xf6, 0x69, 0x96, 0x68, 0x38, 0x6d, 0x38,
-	0x0b, 0xd6, 0x8d, 0x12, 0x41, 0x0d, 0x4b, 0x9b, 0x2d, 0x35, 0xbf, 0x8b,
-	0xe7, 0x99, 0x27, 0x25, 0x1a, 0x49, 0xd3, 0x2e, 0xd6, 0x07, 0x32, 0xd6,
-	0x31, 0xa7, 0xe6, 0x1e, 0x73, 0xce, 0x2a, 0x3b, 0x59, 0xbf, 0xc9, 0xab,
-	0xcd, 0x7f, 0x74, 0x13, 0x6a, 0x73, 0x3c, 0xcf, 0x98, 0xcb, 0xf1, 0x46,
-	0x4f, 0xc6, 0x62, 0x0e, 0x5a, 0x72, 0x8a, 0xf8, 0x2c, 0xa8, 0xb9, 0xaf,
-	0x0e, 0x70, 0x6e, 0x67, 0x3a, 0x76, 0xd3, 0x8f, 0xf1, 0xbf, 0x23, 0xfd,
-	0xce, 0x4d, 0x17, 0x2c, 0xae, 0x3b, 0x75, 0xd3, 0x59, 0xb5, 0x46, 0x18,
-	0xf1, 0x8c, 0xf3, 0x2e, 0xdf, 0xc4, 0x67, 0x9f, 0x44, 0x1c, 0x3f, 0xe1,
-	0x42, 0x97, 0xee, 0x8b, 0x4e, 0x1e, 0x9f, 0x39, 0xd2, 0x54, 0xe1, 0x7d,
-	0xe3, 0xe6, 0x8c, 0x15, 0x56, 0xf9, 0xf6, 0x4b, 0x98, 0x73, 0x04, 0x73,
-	0x0e, 0xbb, 0x01, 0x3f, 0xea, 0xbe, 0x93, 0xc5, 0xfd, 0xc3, 0x65, 0xc3,
-	0x71, 0xca, 0xe6, 0x38, 0x6a, 0x8e, 0xf8, 0x71, 0xe4, 0xe3, 0x1c, 0x72,
-	0xa0, 0x2d, 0xe6, 0x70, 0x41, 0xd2, 0x5d, 0x93, 0xa8, 0xe5, 0x56, 0x90,
-	0x4f, 0x50, 0x87, 0xa4, 0xaa, 0x32, 0xd8, 0x95, 0x39, 0xad, 0xc3, 0x3e,
-	0xef, 0x80, 0xbd, 0x1a, 0x8e, 0x9e, 0x44, 0x5c, 0x47, 0xdc, 0x5c, 0xa8,
-	0x58, 0x5a, 0xb6, 0x3c, 0x68, 0x94, 0xe4, 0x56, 0x59, 0x37, 0xcc, 0xf8,
-	0xa4, 0xec, 0x92, 0x6c, 0x18, 0xf3, 0x86, 0x3f, 0x2e, 0xb9, 0xb8, 0x86,
-	0xd8, 0x70, 0x03, 0xe2, 0x16, 0xeb, 0xe4, 0xf6, 0x18, 0xfa, 0x0b, 0x11,
-	0xeb, 0x8b, 0x21, 0xc6, 0x9e, 0x4e, 0x8b, 0x75, 0x3f, 0xe7, 0xed, 0x92,
-	0x8d, 0x0f, 0xcc, 0x7b, 0xb7, 0x6d, 0x5e, 0xfb, 0xf8, 0x7b, 0x18, 0xdf,
-	0x25, 0x17, 0x41, 0x47, 0x38, 0x39, 0x26, 0x25, 0xf0, 0x10, 0x39, 0xd5,
-	0x6a, 0x5d, 0x00, 0x3f, 0x3a, 0xf8, 0x2f, 0x56, 0x59, 0x0b, 0x84, 0xa4,
-	0x6a, 0xe0, 0x9e, 0xdb, 0x6a, 0xd5, 0x10, 0x46, 0xf5, 0x55, 0xd2, 0x1c,
-	0x95, 0x49, 0x77, 0x48, 0xec, 0x06, 0xe5, 0x60, 0xc2, 0xeb, 0xfe, 0xac,
-	0x2b, 0x7b, 0x86, 0x39, 0x13, 0x16, 0xb1, 0xfa, 0xe7, 0x5d, 0x19, 0xe4,
-	0x3e, 0x7d, 0xf5, 0x62, 0x57, 0x16, 0x7a, 0x0f, 0xad, 0xfe, 0xe7, 0x2e,
-	0xe7, 0x34, 0xe9, 0x0a, 0x21, 0xf7, 0xdd, 0x22, 0x45, 0xa3, 0x25, 0xdf,
-	0x44, 0x8d, 0x50, 0x1c, 0x46, 0x2e, 0x83, 0x17, 0xe8, 0xa0, 0xbb, 0x60,
-	0x48, 0xb4, 0x3b, 0xfd, 0x7d, 0xd0, 0x37, 0x06, 0xd9, 0xec, 0xc2, 0x9c,
-	0x10, 0xc6, 0x87, 0xf0, 0xbf, 0x7d, 0xfc, 0x8d, 0x2e, 0xe4, 0x05, 0xc4,
-	0x60, 0x89, 0x66, 0xc6, 0x7a, 0xb0, 0xfe, 0xf7, 0x30, 0x8e, 0x09, 0xc9,
-	0xcd, 0xf1, 0x27, 0xbc, 0xf1, 0xb7, 0x41, 0x0b, 0x9f, 0x63, 0x8d, 0x22,
-	0xd1, 0xb9, 0x31, 0x03, 0x34, 0x70, 0x6e, 0x4c, 0xcd, 0x75, 0xce, 0xd0,
-	0x06, 0x0c, 0xa7, 0x66, 0xdd, 0x2c, 0xd9, 0xe5, 0x7e, 0x99, 0x5c, 0xee,
-	0x93, 0x03, 0xcb, 0xe6, 0x4c, 0x95, 0xd8, 0x0f, 0x3c, 0x0b, 0xea, 0x30,
-	0x7d, 0x55, 0x20, 0x01, 0x33, 0x7e, 0x44, 0x06, 0xe3, 0x5f, 0x92, 0x5f,
-	0xb6, 0x90, 0xef, 0x91, 0xeb, 0x7b, 0x24, 0xac, 0xd6, 0x89, 0x07, 0x7b,
-	0xd2, 0x46, 0xb7, 0xed, 0xeb, 0x9c, 0xb9, 0xd6, 0xba, 0x70, 0xfe, 0xd5,
-	0xf8, 0x55, 0xeb, 0xfe, 0x85, 0xbf, 0xae, 0x81, 0x75, 0x07, 0xb0, 0x26,
-	0x79, 0x34, 0xbb, 0x26, 0x4e, 0x8b, 0xdd, 0x09, 0xfa, 0x9c, 0xe4, 0x8d,
-	0xc0, 0x86, 0xfd, 0x72, 0x62, 0x99, 0xf1, 0x42, 0xfa, 0xf1, 0x19, 0x8d,
-	0x48, 0x72, 0xf8, 0x1c, 0xea, 0xae, 0x09, 0xb5, 0x86, 0x57, 0x93, 0xe9,
-	0xab, 0x29, 0xd4, 0xc4, 0x3f, 0x05, 0x3d, 0xac, 0x15, 0xc8, 0x73, 0x18,
-	0xfc, 0xa6, 0x50, 0x8b, 0x11, 0x47, 0xb5, 0x1e, 0xcf, 0xa4, 0xf0, 0xfd,
-	0x5c, 0xa2, 0x2b, 0x8b, 0x98, 0x08, 0xff, 0xbe, 0x39, 0xa4, 0x72, 0x18,
-	0xf5, 0x32, 0xda, 0x45, 0x3c, 0x83, 0xe7, 0xa1, 0x27, 0xca, 0x68, 0xbc,
-	0xcb, 0xa9, 0x50, 0x46, 0x02, 0x7a, 0x2c, 0xd8, 0x64, 0x58, 0x61, 0x29,
-	0x7d, 0xd5, 0xc6, 0xbc, 0xb7, 0x42, 0xac, 0x77, 0x33, 0x16, 0xbf, 0x23,
-	0xe6, 0xac, 0x4e, 0x61, 0x2e, 0xbf, 0xdf, 0x85, 0x75, 0x07, 0x87, 0x8b,
-	0xd2, 0x31, 0x7c, 0x18, 0xf1, 0x4e, 0x1f, 0x1b, 0x01, 0x6d, 0xb4, 0xf3,
-	0x16, 0xb0, 0xc0, 0x6f, 0x81, 0x1f, 0xf8, 0x46, 0xd2, 0x92, 0xf9, 0x25,
-	0xca, 0x55, 0x3e, 0x0e, 0x1e, 0xc0, 0x7f, 0x12, 0x71, 0x8d, 0x3c, 0x70,
-	0x6f, 0x41, 0x8e, 0xbe, 0x5b, 0xf2, 0x4b, 0x51, 0x55, 0xeb, 0xdb, 0x06,
-	0xf7, 0xd7, 0x34, 0x3d, 0xdd, 0x0d, 0x1d, 0x93, 0xb7, 0x1c, 0x68, 0x7b,
-	0x0c, 0x79, 0x80, 0xbc, 0x91, 0x2f, 0xfa, 0xca, 0x28, 0xfc, 0x84, 0xf4,
-	0xfb, 0xb6, 0xa7, 0xad, 0x23, 0xa6, 0xa8, 0x38, 0x98, 0xca, 0x20, 0xb0,
-	0xbd, 0xd4, 0x1c, 0x97, 0x3f, 0x6e, 0x8e, 0xc9, 0x77, 0x9b, 0x29, 0xe4,
-	0xc0, 0x51, 0xe4, 0xc0, 0x61, 0xe4, 0x40, 0x0b, 0x39, 0x30, 0x81, 0x1c,
-	0x38, 0x80, 0x1c, 0x18, 0x47, 0x9c, 0x14, 0x39, 0xa1, 0xf2, 0x6d, 0x2c,
-	0x0a, 0xcc, 0x1d, 0xb5, 0x9b, 0x0e, 0x78, 0x99, 0xc1, 0x5e, 0xb3, 0xe0,
-	0xeb, 0x50, 0xd7, 0x44, 0x65, 0x1c, 0x31, 0xd7, 0x42, 0x3c, 0x4a, 0x20,
-	0xdf, 0x8c, 0x01, 0x6b, 0x89, 0x6c, 0x2c, 0x25, 0x10, 0x13, 0x5b, 0xe2,
-	0x00, 0x13, 0x97, 0x8c, 0x14, 0x9e, 0xdd, 0xab, 0xec, 0x33, 0x94, 0xbe,
-	0x3b, 0x2c, 0xdd, 0xa3, 0x92, 0x2f, 0x9f, 0xc4, 0x58, 0x1c, 0xeb, 0x75,
-	0x21, 0x2f, 0x31, 0x2e, 0x30, 0x06, 0x2c, 0x39, 0xbf, 0x6b, 0xd1, 0xd7,
-	0xba, 0xb5, 0xcc, 0xe9, 0x82, 0x30, 0x96, 0x23, 0x0f, 0xc0, 0x1e, 0x38,
-	0x36, 0x89, 0xe7, 0xf8, 0xfd, 0x2f, 0xfd, 0x98, 0xf9, 0xb1, 0x4e, 0x81,
-	0xd1, 0xbe, 0xc4, 0x9c, 0x67, 0x61, 0x3d, 0xb7, 0xdd, 0x4f, 0x9f, 0x47,
-	0xad, 0x14, 0xdc, 0x27, 0xae, 0x66, 0x3f, 0xe1, 0x24, 0x68, 0x1e, 0x04,
-	0xbe, 0x47, 0x6d, 0x75, 0xb0, 0x8a, 0xef, 0xed, 0xf3, 0x5d, 0xcc, 0x57,
-	0x63, 0x51, 0x23, 0x6d, 0xb1, 0x9e, 0x43, 0xac, 0x3c, 0x86, 0xb8, 0x68,
-	0x3b, 0xfa, 0x5a, 0x03, 0x7c, 0x42, 0x8e, 0x65, 0xdb, 0x09, 0x0f, 0xbd,
-	0xd6, 0x7a, 0xd6, 0x1a, 0x96, 0x89, 0xb5, 0x31, 0xc9, 0xae, 0x0d, 0xc6,
-	0xcf, 0x4b, 0xd7, 0x65, 0x5b, 0x5e, 0x6b, 0x95, 0x5c, 0xf3, 0xa4, 0x0d,
-	0xbb, 0xdc, 0xb7, 0xdf, 0x90, 0x1a, 0x30, 0xdc, 0xbe, 0xfd, 0x9d, 0xac,
-	0xe9, 0x5f, 0x14, 0x3d, 0x21, 0x99, 0x45, 0x5b, 0xc6, 0xf6, 0x07, 0xb5,
-	0xe7, 0x2f, 0x3b, 0xa4, 0x1b, 0x63, 0x6b, 0x09, 0xcc, 0x61, 0xdd, 0xaf,
-	0xfa, 0x27, 0xe0, 0x59, 0xf3, 0x9e, 0x51, 0x39, 0x8f, 0x98, 0x19, 0xbc,
-	0x37, 0x6d, 0xe7, 0xfc, 0x22, 0x70, 0x0d, 0xe4, 0x99, 0x59, 0x24, 0xee,
-	0xda, 0x05, 0x39, 0x45, 0x60, 0x23, 0xd4, 0xfd, 0x20, 0x9e, 0x6d, 0xc9,
-	0x57, 0x53, 0xb4, 0x87, 0xc7, 0x20, 0x4b, 0xac, 0x15, 0x0e, 0xf8, 0xf9,
-	0x9a, 0xcc, 0x2d, 0x51, 0x7e, 0x71, 0xd4, 0x96, 0xdc, 0x5b, 0xa2, 0x5d,
-	0xe9, 0xab, 0xeb, 0x46, 0xdb, 0xd9, 0x58, 0xc4, 0xfa, 0x43, 0xc4, 0xd8,
-	0x88, 0xd5, 0x65, 0xf6, 0x06, 0x58, 0x53, 0x1d, 0x80, 0x4e, 0xa6, 0x15,
-	0xe6, 0xce, 0xd4, 0x53, 0x62, 0x9d, 0x62, 0xac, 0x92, 0x44, 0xc8, 0x22,
-	0xbe, 0x17, 0x43, 0x4f, 0xcf, 0xe2, 0x1e, 0xe5, 0xc9, 0x5a, 0x1f, 0xf7,
-	0x57, 0xff, 0xa3, 0xd2, 0x49, 0x08, 0xba, 0xcb, 0xef, 0x67, 0x11, 0x22,
-	0x4b, 0xa1, 0x34, 0x62, 0xe0, 0x18, 0x79, 0x50, 0x7b, 0xa3, 0x9e, 0xa4,
-	0xdf, 0x81, 0x67, 0xd8, 0x46, 0x5b, 0x5d, 0xa9, 0xfe, 0x4a, 0x95, 0x08,
-	0x6c, 0x59, 0x0a, 0x91, 0x34, 0x78, 0x1a, 0xc3, 0x77, 0x38, 0xff, 0x09,
-	0xe8, 0xf3, 0x2c, 0x9e, 0x5f, 0x00, 0x5f, 0x1b, 0x65, 0xd2, 0x9d, 0x4c,
-	0x1c, 0x57, 0xbe, 0x8b, 0x6b, 0x97, 0xb5, 0xcc, 0xd7, 0xe4, 0xbc, 0xe2,
-	0xef, 0x13, 0xac, 0x9d, 0xa1, 0xa7, 0xeb, 0xe1, 0x6f, 0xf2, 0x3a, 0xf9,
-	0xf3, 0xd6, 0x67, 0xce, 0xca, 0x58, 0x09, 0xc9, 0x96, 0x5f, 0x6a, 0x85,
-	0x2d, 0x2b, 0x3e, 0xef, 0xeb, 0x31, 0xeb, 0x46, 0x41, 0x07, 0xfb, 0x00,
-	0xfb, 0x95, 0x2e, 0x41, 0x07, 0x6d, 0xa7, 0x10, 0x4d, 0x3f, 0x2e, 0x2b,
-	0x4b, 0xff, 0x54, 0x6a, 0x4b, 0x05, 0xa9, 0x2f, 0xfd, 0x23, 0x39, 0xb7,
-	0xd4, 0x92, 0x0b, 0x29, 0x15, 0x93, 0xac, 0x0e, 0xe5, 0xcf, 0x72, 0xa3,
-	0x87, 0x07, 0x93, 0xe3, 0x97, 0x20, 0xc0, 0x95, 0xaa, 0x47, 0xfb, 0x54,
-	0x1b, 0xed, 0x17, 0x60, 0x6b, 0xaf, 0x58, 0xa4, 0x7f, 0x4c, 0x6a, 0x65,
-	0xd2, 0xfe, 0xa0, 0xa2, 0xfd, 0xc0, 0x26, 0xed, 0x92, 0x0b, 0x59, 0xa4,
-	0x7f, 0x27, 0xda, 0x81, 0xf3, 0xfb, 0x49, 0x7f, 0x02, 0xcf, 0x7e, 0xd0,
-	0xfe, 0x6a, 0xee, 0x6b, 0xad, 0x8d, 0x72, 0x44, 0xd1, 0x1c, 0x4a, 0x8f,
-	0x41, 0x3e, 0xaf, 0xb5, 0xd6, 0x5d, 0xfa, 0x11, 0xbe, 0xbb, 0xf7, 0x20,
-	0x46, 0xf5, 0x61, 0xaf, 0x5e, 0xc9, 0xcf, 0x46, 0x11, 0x27, 0xc7, 0xa1,
-	0xdb, 0x2e, 0xe5, 0x87, 0x08, 0x17, 0xd0, 0xd9, 0x34, 0xe6, 0x1f, 0xa2,
-	0xbf, 0x29, 0xb9, 0x38, 0x90, 0x4b, 0xb1, 0x9c, 0x8e, 0xa0, 0xfe, 0xc7,
-	0x3e, 0x86, 0x93, 0x73, 0xf9, 0xcc, 0x00, 0x62, 0x1a, 0xff, 0x7f, 0x64,
-	0x7b, 0x28, 0x20, 0xd6, 0x42, 0xe7, 0x3d, 0x90, 0x1f, 0xe8, 0x18, 0x9b,
-	0x41, 0x6e, 0x4d, 0x0e, 0xd7, 0x54, 0x7f, 0x91, 0x71, 0xe5, 0x28, 0xf2,
-	0xe9, 0x21, 0x7c, 0xbc, 0xfd, 0x26, 0x9a, 0xdc, 0x73, 0x3b, 0x4f, 0x45,
-	0x77, 0x7d, 0x2f, 0x01, 0x52, 0xa6, 0xc9, 0x7d, 0x0b, 0x12, 0x4a, 0x87,
-	0xb0, 0x2f, 0xc7, 0x7a, 0x10, 0x63, 0x06, 0xa2, 0xd9, 0xe6, 0xcf, 0x31,
-	0x4e, 0x5f, 0x66, 0x7c, 0x0f, 0x68, 0x1f, 0xc5, 0x9a, 0x8c, 0xbb, 0x63,
-	0xe0, 0x99, 0x35, 0x26, 0xe3, 0x26, 0xf2, 0x48, 0xe3, 0x47, 0xcc, 0x2d,
-	0xf8, 0x3e, 0xe0, 0x7f, 0xe7, 0x7d, 0x89, 0xde, 0x9c, 0x36, 0xab, 0x05,
-	0x31, 0xb1, 0x27, 0x74, 0x6e, 0xc5, 0xa5, 0xd8, 0x30, 0x5f, 0x20, 0x66,
-	0xd4, 0x29, 0x83, 0x35, 0xca, 0x89, 0xfd, 0x27, 0xd4, 0x7f, 0xb5, 0xe7,
-	0x21, 0x8f, 0xa8, 0xec, 0xb5, 0x0e, 0x22, 0xa6, 0x80, 0xfe, 0xca, 0x18,
-	0x78, 0x63, 0x8f, 0x66, 0x10, 0xf9, 0x2b, 0x04, 0x21, 0xa0, 0x96, 0x5a,
-	0x0b, 0xc9, 0xbd, 0xe1, 0x11, 0xa3, 0x28, 0x8f, 0x46, 0x58, 0x36, 0x17,
-	0xd6, 0x98, 0x07, 0xc2, 0xb2, 0xb0, 0x26, 0x72, 0x69, 0x91, 0x71, 0x45,
-	0xfd, 0x41, 0xe6, 0x86, 0x33, 0x8f, 0x3c, 0x5b, 0x5a, 0x62, 0x8c, 0x61,
-	0x9c, 0xb8, 0x01, 0xba, 0x48, 0x7e, 0xe3, 0xab, 0xc8, 0x49, 0xa5, 0xf2,
-	0x20, 0x62, 0xa6, 0xac, 0xeb, 0x90, 0x29, 0x72, 0x19, 0x6b, 0xd4, 0x1d,
-	0xfa, 0x32, 0x41, 0x4f, 0x26, 0x2a, 0xc5, 0x45, 0xf6, 0x63, 0xa2, 0xa0,
-	0x85, 0x35, 0x76, 0x48, 0xd5, 0x3f, 0x37, 0xa8, 0xd8, 0xca, 0xff, 0xe1,
-	0xb6, 0x7d, 0x93, 0x27, 0xf7, 0xe9, 0x8c, 0x63, 0x37, 0x8b, 0x3d, 0x63,
-	0x77, 0x1d, 0xa8, 0x74, 0x48, 0xb5, 0x8f, 0x76, 0x49, 0xfd, 0xbf, 0xa0,
-	0x62, 0xed, 0x02, 0x78, 0x2a, 0x2e, 0x12, 0xe3, 0x86, 0x31, 0x2f, 0xe6,
-	0xcf, 0xa3, 0x5c, 0xff, 0x89, 0xcc, 0xed, 0x7f, 0x17, 0x74, 0x79, 0x71,
-	0x2d, 0xbf, 0x1f, 0xf1, 0x76, 0x46, 0x97, 0x3b, 0xef, 0x1a, 0xc7, 0xb3,
-	0xcc, 0x81, 0xef, 0xf8, 0x78, 0x92, 0x63, 0xec, 0x61, 0x81, 0xbe, 0x15,
-	0x03, 0xff, 0xfb, 0xa4, 0xb0, 0x12, 0x85, 0x1c, 0x90, 0x4b, 0x6b, 0xde,
-	0x5a, 0xac, 0x77, 0x4f, 0x42, 0x47, 0xfa, 0xa9, 0xa8, 0x44, 0x4e, 0xf5,
-	0x49, 0xf8, 0xeb, 0xdd, 0xd2, 0xf1, 0xf5, 0x21, 0x09, 0x7d, 0xdd, 0x64,
-	0x4e, 0x4f, 0x9c, 0x80, 0xbe, 0xe6, 0x65, 0x5c, 0x9e, 0x44, 0xde, 0x62,
-	0x5e, 0x57, 0x76, 0x6a, 0xf4, 0x4b, 0x08, 0x05, 0xab, 0xfe, 0x8c, 0x2d,
-	0x8f, 0xee, 0xff, 0x85, 0xea, 0x33, 0x01, 0xc3, 0x8b, 0xfe, 0xfc, 0x94,
-	0xd8, 0xcd, 0x77, 0x21, 0x6b, 0xc3, 0x79, 0xed, 0xd6, 0xa0, 0xa6, 0x1c,
-	0x56, 0xfd, 0xc2, 0x47, 0xf7, 0x7b, 0x35, 0x25, 0xf0, 0xb8, 0xe6, 0xa8,
-	0x9a, 0x12, 0xf1, 0x35, 0xcc, 0x79, 0xfd, 0xa2, 0x63, 0xaf, 0xbc, 0x0c,
-	0x42, 0x4f, 0xb7, 0x88, 0x7d, 0x08, 0x7e, 0xf1, 0x9c, 0x2c, 0xe9, 0x69,
-	0x4d, 0xad, 0x19, 0x7a, 0x86, 0x71, 0x8a, 0xf1, 0x8b, 0x36, 0x9e, 0x4c,
-	0x14, 0x61, 0x7f, 0xa1, 0xe7, 0x19, 0xa3, 0x3c, 0xdb, 0x9e, 0x68, 0x8b,
-	0x75, 0x0b, 0x95, 0x7b, 0xa0, 0x43, 0xd4, 0xf2, 0x16, 0xe2, 0x9c, 0x81,
-	0x5c, 0x6e, 0xf1, 0xda, 0xeb, 0xe1, 0xe5, 0x63, 0x31, 0x75, 0x5d, 0xac,
-	0x7a, 0x18, 0xdc, 0x5b, 0x9f, 0x75, 0x07, 0x62, 0x4c, 0x93, 0x74, 0x70,
-	0xdf, 0x01, 0x09, 0x3d, 0x17, 0x93, 0xf0, 0x73, 0xb4, 0x3f, 0x33, 0xe1,
-	0x40, 0x7e, 0x0b, 0x16, 0x31, 0xd0, 0x0a, 0xb0, 0xc5, 0xcd, 0xa2, 0xaf,
-	0x0c, 0xc0, 0x77, 0xcc, 0x78, 0x55, 0x92, 0x12, 0xaa, 0x45, 0xe5, 0xad,
-	0x45, 0x33, 0x41, 0x7b, 0x39, 0x6b, 0x61, 0xbc, 0xd9, 0x75, 0x79, 0x5d,
-	0x51, 0xc1, 0xb1, 0x2f, 0x87, 0x80, 0x19, 0x86, 0x6d, 0xbd, 0x47, 0x5e,
-	0x87, 0xbe, 0x73, 0x6a, 0xec, 0x66, 0xac, 0x0b, 0x1a, 0x9e, 0x33, 0xc1,
-	0x03, 0xd7, 0xfd, 0x1e, 0xd6, 0x54, 0xf8, 0xca, 0xd9, 0x60, 0x4d, 0xba,
-	0x48, 0xdb, 0xed, 0x83, 0xdd, 0xe1, 0xba, 0xd9, 0x21, 0xb9, 0xd9, 0x84,
-	0xe8, 0x8b, 0x9f, 0x91, 0xc1, 0xfd, 0xba, 0xc7, 0x8f, 0xe2, 0x91, 0x63,
-	0xec, 0xc7, 0xdd, 0xae, 0xfc, 0x51, 0x5f, 0x83, 0xcd, 0x3c, 0x48, 0x1d,
-	0x23, 0xf7, 0x23, 0x8f, 0x31, 0x8e, 0x85, 0x90, 0xc7, 0xb2, 0x4d, 0x4f,
-	0xef, 0xd5, 0x07, 0xfb, 0xe5, 0xc9, 0xe7, 0x68, 0x4f, 0xb8, 0xb7, 0x69,
-	0x53, 0x41, 0x0f, 0x98, 0xf7, 0x2c, 0x39, 0xf9, 0x6c, 0x50, 0x73, 0xb0,
-	0xbe, 0x32, 0xe3, 0x07, 0xc0, 0x8f, 0x7e, 0x27, 0xe3, 0x81, 0xae, 0x6c,
-	0x37, 0x6f, 0x59, 0x5e, 0xdd, 0x51, 0x49, 0xb0, 0x2f, 0x6e, 0xb0, 0x4e,
-	0xb3, 0xe3, 0x9e, 0xbc, 0x8b, 0x18, 0x2b, 0x35, 0x67, 0x11, 0xa3, 0x23,
-	0x72, 0x71, 0xd6, 0x86, 0xee, 0x3f, 0x0b, 0xba, 0x0e, 0x75, 0x11, 0x23,
-	0x5f, 0x9c, 0x75, 0x70, 0x7d, 0x48, 0xd5, 0x66, 0xa1, 0x3b, 0x61, 0xc7,
-	0xcd, 0x7e, 0xfa, 0x91, 0xaf, 0xa7, 0x84, 0x56, 0x5c, 0x32, 0xb5, 0x12,
-	0x62, 0xf6, 0x64, 0x8a, 0x39, 0xbe, 0x53, 0xf5, 0x4d, 0xd9, 0xaf, 0xc9,
-	0x2b, 0xbc, 0xb0, 0x4f, 0x2b, 0x56, 0x19, 0xe7, 0x0b, 0xf1, 0x0e, 0x21,
-	0x0e, 0x11, 0xad, 0x66, 0x51, 0x27, 0x9a, 0x9c, 0x57, 0xbd, 0x58, 0x11,
-	0xc7, 0x3d, 0x42, 0x19, 0x68, 0xf5, 0xea, 0x3e, 0xad, 0x50, 0x0d, 0xc9,
-	0xc5, 0x18, 0xe9, 0x4e, 0xa8, 0xfa, 0x7d, 0xbf, 0xb2, 0xb5, 0x1e, 0xe4,
-	0x12, 0xd8, 0x4c, 0xea, 0x93, 0xd8, 0x57, 0x8d, 0xc1, 0xa6, 0xa8, 0x7b,
-	0xea, 0x5d, 0xc5, 0x48, 0x5f, 0xf7, 0x3b, 0xe5, 0x4c, 0xd0, 0x51, 0x26,
-	0x7e, 0xef, 0xf4, 0xf1, 0xfb, 0xa2, 0x5f, 0x0f, 0x3d, 0x26, 0xac, 0x53,
-	0x16, 0x2a, 0xa4, 0x05, 0xf1, 0xd6, 0xdd, 0xc9, 0x96, 0x28, 0x47, 0x2f,
-	0xa6, 0x1c, 0x45, 0x1d, 0xa3, 0xaf, 0x19, 0xbe, 0x0d, 0xf0, 0x6f, 0x14,
-	0xf7, 0xbc, 0x5a, 0xaa, 0xd8, 0x8c, 0xc0, 0xdf, 0xa7, 0x21, 0x23, 0xea,
-	0x06, 0xfa, 0x5b, 0xe3, 0x99, 0x0a, 0xf4, 0xb7, 0xf6, 0xf2, 0xfb, 0x76,
-	0x1f, 0x63, 0xde, 0xb0, 0x3c, 0x89, 0xf1, 0x13, 0x67, 0x48, 0xcf, 0xb8,
-	0x8f, 0xc7, 0x12, 0x90, 0x09, 0x63, 0xfc, 0xa8, 0xbc, 0xd5, 0x70, 0x14,
-	0xfe, 0xdb, 0xb7, 0x7f, 0x46, 0xe6, 0xdd, 0x59, 0xe0, 0x3f, 0xc8, 0xdf,
-	0x48, 0xc0, 0x3f, 0xe3, 0x2a, 0x3e, 0x1e, 0xfe, 0x68, 0x35, 0x49, 0xd8,
-	0xcb, 0xd9, 0xf7, 0x5e, 0x67, 0xce, 0xde, 0x0d, 0xfc, 0xf5, 0x91, 0xd6,
-	0x0f, 0x79, 0xeb, 0xff, 0x17, 0xe8, 0xea, 0x73, 0xd8, 0x23, 0x0a, 0xfa,
-	0xfa, 0x29, 0xd3, 0x0f, 0x7b, 0x4e, 0xf7, 0x9e, 0xbb, 0xff, 0x3a, 0xe9,
-	0x32, 0xa4, 0x01, 0x8c, 0x50, 0x50, 0x79, 0x94, 0xb5, 0x62, 0xc4, 0xd7,
-	0xdf, 0x31, 0x60, 0x67, 0xae, 0x1b, 0xc4, 0xde, 0x4e, 0x29, 0xf4, 0x05,
-	0xf5, 0x27, 0x62, 0xf6, 0xe6, 0x78, 0x50, 0xcf, 0xf2, 0xf9, 0x94, 0x93,
-	0x2f, 0xb3, 0x4f, 0xc8, 0x5c, 0xc0, 0x31, 0x65, 0x87, 0x1f, 0x42, 0xb7,
-	0x09, 0xcf, 0x20, 0xdd, 0xf7, 0x29, 0xba, 0x1d, 0x45, 0x37, 0xfd, 0x8b,
-	0x67, 0x3a, 0xec, 0xa3, 0x05, 0x7d, 0x33, 0xae, 0x07, 0x4c, 0x00, 0x7d,
-	0x7f, 0x17, 0x3a, 0xfe, 0x4e, 0x05, 0x98, 0xa0, 0x02, 0x4c, 0x80, 0x3d,
-	0xbe, 0x0d, 0x1d, 0x7f, 0xab, 0x02, 0x4c, 0x50, 0x89, 0xfb, 0x3d, 0x0a,
-	0x9b, 0x98, 0xfe, 0x23, 0xda, 0x6e, 0xd0, 0x93, 0xb9, 0xda, 0x2e, 0x39,
-	0xce, 0xf9, 0x01, 0x36, 0x8e, 0xc2, 0x8e, 0x78, 0x6e, 0x11, 0xf4, 0x3b,
-	0xfc, 0x1c, 0xd1, 0xe0, 0xb9, 0x00, 0x72, 0x44, 0x83, 0xe7, 0x18, 0x23,
-	0xf1, 0x10, 0x30, 0x61, 0x48, 0xe2, 0xc2, 0x5e, 0xef, 0xdc, 0x18, 0xd6,
-	0x1a, 0x1d, 0x84, 0x27, 0x75, 0xa8, 0xbe, 0xd6, 0x71, 0xd5, 0x6f, 0x40,
-	0x5c, 0xa8, 0x06, 0xb5, 0x5b, 0x52, 0x26, 0x96, 0x88, 0x33, 0x65, 0xaf,
-	0x9e, 0x86, 0x0e, 0x5c, 0x62, 0xc3, 0xcd, 0xbe, 0xf4, 0x70, 0x1d, 0x7b,
-	0x16, 0x2d, 0x8f, 0xbe, 0xe3, 0xee, 0xd6, 0x33, 0x07, 0x10, 0x9f, 0xa7,
-	0xca, 0x09, 0x99, 0x2c, 0x7b, 0x98, 0x00, 0xf5, 0xcf, 0x55, 0xfd, 0x51,
-	0x9b, 0x7a, 0x80, 0xfe, 0x36, 0x6d, 0x23, 0x71, 0x3e, 0x45, 0x19, 0x53,
-	0xff, 0xd3, 0xaa, 0x67, 0x7d, 0xa0, 0xee, 0xf5, 0xe5, 0x27, 0x95, 0x2d,
-	0x84, 0x19, 0x67, 0xa8, 0x3f, 0xcf, 0x87, 0x61, 0x17, 0x79, 0x37, 0x90,
-	0x4b, 0x3b, 0x1e, 0xf9, 0xbc, 0x26, 0xd6, 0x4e, 0xe3, 0xb9, 0xb6, 0xf1,
-	0xcd, 0xfb, 0x3e, 0xbd, 0x88, 0x7d, 0x9b, 0x3d, 0x06, 0xc6, 0xa9, 0xad,
-	0xf1, 0x10, 0xea, 0x87, 0xb0, 0xba, 0x8f, 0x18, 0xde, 0x88, 0x49, 0xb6,
-	0x61, 0x89, 0x53, 0xe5, 0x3c, 0xf6, 0x2d, 0x18, 0x8f, 0x9e, 0x90, 0xec,
-	0x52, 0xaf, 0xe4, 0x62, 0x66, 0xca, 0x96, 0xbf, 0x27, 0x1b, 0xcb, 0x85,
-	0x04, 0xcf, 0x0d, 0x0b, 0x33, 0x1a, 0x9e, 0x7b, 0x18, 0xd7, 0xa4, 0xd9,
-	0x92, 0xc3, 0x65, 0xe6, 0x9d, 0x91, 0x78, 0x03, 0xf7, 0x72, 0xb3, 0xec,
-	0xd5, 0x54, 0x61, 0x93, 0x66, 0xa2, 0x8a, 0x78, 0xf0, 0x72, 0x99, 0xfb,
-	0x01, 0x1b, 0x95, 0xd9, 0xcf, 0x09, 0xee, 0x3f, 0x01, 0x1c, 0x88, 0x58,
-	0x1d, 0xf3, 0xe7, 0x28, 0x5e, 0x6d, 0x23, 0x2c, 0x81, 0xae, 0x3b, 0x65,
-	0xdd, 0x8f, 0xbb, 0xb5, 0xb2, 0xd7, 0x47, 0x39, 0x4b, 0x7a, 0xdc, 0xff,
-	0xd5, 0x5a, 0x8f, 0xa1, 0x16, 0xda, 0xe4, 0xf5, 0x8f, 0xb9, 0x8f, 0x81,
-	0xb0, 0x2b, 0x27, 0xdc, 0x40, 0x26, 0xbc, 0xcf, 0x31, 0x9e, 0x8d, 0xb6,
-	0x5a, 0x67, 0xad, 0xf6, 0x9e, 0xdf, 0xf5, 0xf4, 0xcc, 0xde, 0xb8, 0x2d,
-	0x63, 0xbd, 0xe6, 0xa0, 0x26, 0xf6, 0x7b, 0x66, 0x87, 0x46, 0xbc, 0x9e,
-	0xd9, 0xfc, 0xc8, 0xf6, 0x9e, 0xd9, 0xcf, 0x6f, 0xf3, 0x7a, 0x66, 0x17,
-	0x9d, 0x22, 0x3e, 0x5e, 0xcf, 0x6c, 0xf8, 0x76, 0xaf, 0x67, 0xf6, 0xf0,
-	0xed, 0x5e, 0xcf, 0xec, 0x91, 0x11, 0xaf, 0x67, 0xf6, 0xfb, 0xb7, 0x6f,
-	0xef, 0x99, 0x3d, 0x36, 0xb2, 0xbd, 0x67, 0x26, 0x13, 0xc8, 0x77, 0x13,
-	0x5b, 0x3d, 0xb3, 0xf2, 0xc8, 0xb5, 0x7b, 0x66, 0xaf, 0x06, 0x78, 0x1d,
-	0xfc, 0x8c, 0x81, 0x87, 0x14, 0xf0, 0xfa, 0x28, 0xf0, 0xfa, 0xaf, 0xeb,
-	0x59, 0x87, 0xc1, 0xe7, 0xcd, 0x7e, 0x5e, 0xb8, 0x1e, 0xdc, 0x7e, 0xbb,
-	0xff, 0x8c, 0xa0, 0xde, 0x4d, 0xf8, 0xb5, 0x0a, 0xb1, 0xfb, 0x1e, 0xbf,
-	0x66, 0xfb, 0x6b, 0xd1, 0xad, 0xf3, 0xec, 0xf6, 0xff, 0x37, 0xa0, 0xf4,
-	0x0e, 0xf0, 0x3c, 0xf9, 0x79, 0x0d, 0xb5, 0x1f, 0xf9, 0x47, 0xa2, 0xef,
-	0xbe, 0xe8, 0x7c, 0xd5, 0x22, 0xc6, 0x7f, 0x1c, 0xbe, 0x6a, 0xef, 0x0d,
-	0xc9, 0x3a, 0xfc, 0x96, 0x39, 0xea, 0xa4, 0x64, 0x31, 0x3f, 0xab, 0xe6,
-	0x27, 0x26, 0xb6, 0xe6, 0xa7, 0x26, 0xbe, 0xaa, 0x6a, 0x52, 0xf3, 0x5f,
-	0xe3, 0xf3, 0x0d, 0x65, 0xdf, 0x96, 0x87, 0xe1, 0x9d, 0x4a, 0x80, 0xb7,
-	0xc2, 0x3e, 0x76, 0x36, 0x1c, 0xdb, 0x9d, 0xc0, 0x33, 0xe6, 0x8b, 0xb6,
-	0x34, 0x14, 0x7e, 0x0f, 0xa5, 0xcd, 0x17, 0x73, 0xaa, 0x5e, 0x33, 0x9c,
-	0xbc, 0x1b, 0xd4, 0xdf, 0xa8, 0xa1, 0x86, 0x06, 0xd5, 0xf9, 0x9b, 0xbe,
-	0x36, 0x8c, 0x3c, 0xd6, 0x5e, 0x63, 0xb3, 0xae, 0xd6, 0xfd, 0xba, 0xda,
-	0x90, 0xbb, 0xf7, 0xb7, 0x63, 0x73, 0x99, 0xf8, 0x5b, 0x0a, 0x9b, 0xef,
-	0x42, 0x6d, 0x4e, 0xec, 0x4d, 0x1c, 0x43, 0x0c, 0x41, 0x7c, 0xce, 0x7e,
-	0x01, 0xeb, 0x19, 0xe6, 0x46, 0xd6, 0x37, 0x31, 0x7c, 0xf8, 0xbe, 0x41,
-	0x80, 0xd1, 0x3b, 0xfc, 0xf8, 0xce, 0xba, 0x28, 0xc0, 0x2a, 0x77, 0x75,
-	0x7b, 0xb5, 0xd1, 0x2e, 0xcd, 0xab, 0x3f, 0x13, 0xfe, 0x9c, 0xf0, 0x26,
-	0x16, 0x0e, 0x6f, 0x62, 0xe1, 0x6d, 0xe7, 0x30, 0xa2, 0xde, 0x6d, 0x50,
-	0xe7, 0x39, 0x3c, 0xdf, 0x11, 0x4d, 0x4f, 0xf3, 0x8c, 0x07, 0x38, 0xc7,
-	0xe2, 0x99, 0x0f, 0x7d, 0xe9, 0x41, 0x2d, 0x5b, 0x37, 0x10, 0xef, 0x99,
-	0x7f, 0x90, 0x6b, 0xcb, 0xc1, 0xd9, 0x62, 0xa0, 0x27, 0xca, 0x8e, 0x63,
-	0x7f, 0xaa, 0xa1, 0xe6, 0x4d, 0x45, 0xac, 0x43, 0xa0, 0x65, 0x0a, 0xff,
-	0x03, 0x99, 0xde, 0xa3, 0x72, 0x5f, 0x27, 0x6c, 0xf6, 0x78, 0x85, 0xd8,
-	0xf5, 0x71, 0x69, 0xf8, 0xf8, 0x75, 0x65, 0xc9, 0xc3, 0xae, 0xe1, 0xed,
-	0xd8, 0x35, 0xb5, 0x21, 0x1e, 0x8d, 0x07, 0x76, 0xa4, 0xd1, 0x70, 0x5e,
-	0x19, 0x22, 0x66, 0x25, 0x9d, 0xcc, 0x3d, 0xd3, 0x88, 0x81, 0xcc, 0x39,
-	0xcc, 0x37, 0xc4, 0xa5, 0xd7, 0xa2, 0x4f, 0x8d, 0x1d, 0xed, 0xb0, 0xa2,
-	0xf8, 0xcc, 0x83, 0x8e, 0x19, 0x3c, 0x93, 0x96, 0x85, 0xd3, 0x5f, 0xd1,
-	0x9c, 0xfa, 0x3c, 0xe8, 0x99, 0x42, 0xae, 0xa3, 0x2d, 0x15, 0x0c, 0xcf,
-	0x8e, 0xd6, 0x11, 0xf7, 0x5d, 0xc6, 0x02, 0xd4, 0xae, 0xa8, 0x47, 0xca,
-	0x8c, 0xbd, 0x3c, 0xeb, 0x0a, 0x62, 0x2e, 0xfb, 0x26, 0xa8, 0x59, 0x59,
-	0xbb, 0x2e, 0x72, 0xdf, 0xed, 0xba, 0xa8, 0xb9, 0xc4, 0x5d, 0x86, 0xb3,
-	0xbe, 0x46, 0xdc, 0xf8, 0x51, 0x31, 0xa4, 0xe1, 0xbc, 0x3c, 0x44, 0x1c,
-	0x79, 0x3d, 0xf8, 0xd1, 0x84, 0x34, 0xcd, 0x17, 0xd6, 0xf5, 0x76, 0xfc,
-	0xe8, 0x61, 0xc7, 0xcc, 0xda, 0x41, 0xac, 0xc9, 0xda, 0x8c, 0x38, 0xd1,
-	0x44, 0x98, 0x1b, 0xc4, 0xb3, 0x83, 0xe0, 0xc7, 0xc3, 0x8a, 0x59, 0x60,
-	0xc5, 0xbf, 0x03, 0xac, 0x58, 0x92, 0xf7, 0xa2, 0xc4, 0x8a, 0xb6, 0x8f,
-	0x15, 0x1d, 0xd8, 0x71, 0x7e, 0x9b, 0x1d, 0x6b, 0xaa, 0x07, 0xc5, 0x7b,
-	0x79, 0x60, 0xbd, 0xec, 0xa2, 0x79, 0x1d, 0xf8, 0x50, 0x93, 0x98, 0x3a,
-	0xaf, 0x0f, 0xb7, 0xad, 0x19, 0xe0, 0xc0, 0x7d, 0x0a, 0xdf, 0xdd, 0x57,
-	0xd9, 0x85, 0xda, 0x44, 0xe1, 0x3d, 0xff, 0x9c, 0x2f, 0x7c, 0xd5, 0xd9,
-	0x67, 0xb8, 0xed, 0xec, 0x73, 0x0b, 0x17, 0xe2, 0x39, 0xbf, 0xc7, 0x17,
-	0x81, 0xde, 0xfe, 0x07, 0x69, 0x82, 0x5f, 0xd1, 0x07, 0x34, 0xcf, 0x4f,
-	0xb6, 0xe1, 0xc3, 0xff, 0x7a, 0x15, 0x3e, 0x44, 0xce, 0x5a, 0x89, 0x49,
-	0x06, 0xd8, 0xd0, 0x5e, 0xe3, 0x5a, 0xf4, 0xe5, 0x51, 0xe9, 0x00, 0x7f,
-	0x9d, 0x8b, 0x7d, 0xc0, 0x44, 0xdd, 0x12, 0x05, 0x36, 0x8a, 0x28, 0x6c,
-	0x34, 0x44, 0x0c, 0x33, 0x7c, 0x18, 0x98, 0xa6, 0xb1, 0x89, 0x8f, 0xcc,
-	0xd4, 0x0f, 0xa0, 0x97, 0x87, 0x95, 0xad, 0x8c, 0xcb, 0x53, 0x88, 0x9d,
-	0x1d, 0x6b, 0xc0, 0x75, 0x2b, 0x1e, 0x6e, 0x8a, 0x5c, 0x85, 0x9b, 0x8e,
-	0xec, 0x88, 0x9b, 0x54, 0xbf, 0x7e, 0x9c, 0x32, 0x79, 0xdd, 0xf5, 0xfa,
-	0xf5, 0x97, 0x5c, 0xaf, 0x5f, 0xff, 0xba, 0xdb, 0xde, 0xaf, 0xbf, 0x49,
-	0x8a, 0x86, 0x69, 0x5f, 0x94, 0xab, 0xfa, 0xf5, 0x33, 0xec, 0x7f, 0x57,
-	0xbb, 0xbc, 0xbe, 0x7c, 0xb7, 0xdf, 0xaf, 0x37, 0xa5, 0xb8, 0x6d, 0xdc,
-	0x90, 0xb7, 0xad, 0xa0, 0x5f, 0xff, 0x2f, 0x30, 0xd6, 0x83, 0x3d, 0xb6,
-	0xf7, 0xea, 0x2f, 0xb9, 0xec, 0xd5, 0xc7, 0x38, 0xcf, 0xef, 0xd5, 0x73,
-	0x1e, 0x6a, 0x78, 0x97, 0x7d, 0xfa, 0x9b, 0x21, 0x8b, 0x7e, 0xc8, 0xa1,
-	0x4f, 0x3a, 0x9e, 0x8b, 0x73, 0x8e, 0xea, 0xcf, 0x5f, 0x74, 0x63, 0x78,
-	0xce, 0xeb, 0xa3, 0x1f, 0x86, 0x5d, 0x1d, 0xd9, 0xec, 0xcf, 0x7b, 0x7b,
-	0xbc, 0xe1, 0x6e, 0x5f, 0x7f, 0xfb, 0x3a, 0x03, 0xfe, 0x3a, 0x31, 0xac,
-	0x13, 0xbf, 0x6a, 0x9d, 0xad, 0x7e, 0xfc, 0x1b, 0xae, 0xd7, 0x8b, 0x77,
-	0x4e, 0x8b, 0xdd, 0x81, 0x98, 0xfc, 0xe2, 0xd0, 0x8d, 0xfe, 0x1a, 0x9b,
-	0xbd, 0x78, 0xc6, 0x0e, 0xe0, 0x75, 0xc6, 0x0f, 0x3e, 0xff, 0xff, 0xbe,
-	0x17, 0xcf, 0x3e, 0xbc, 0x77, 0x9e, 0x42, 0xff, 0x04, 0x2e, 0x7f, 0xd6,
-	0xeb, 0xc1, 0x4f, 0x54, 0x82, 0xde, 0x3a, 0xeb, 0xc6, 0xe0, 0xbd, 0x8c,
-	0xc1, 0xc4, 0x71, 0xa1, 0xad, 0x90, 0x3e, 0xae, 0xdb, 0x23, 0x73, 0x0a,
-	0x17, 0xc1, 0xa6, 0x92, 0xd7, 0xc6, 0xc6, 0xb5, 0xc5, 0x00, 0x1b, 0xc7,
-	0x14, 0x36, 0xae, 0xad, 0x05, 0xd8, 0x38, 0x73, 0x0d, 0x6c, 0xfc, 0xdf,
-	0xba, 0xbc, 0xf8, 0x1f, 0x95, 0x82, 0xc2, 0xc6, 0xd7, 0x7a, 0xc7, 0x86,
-	0xf7, 0xba, 0x89, 0x03, 0xc4, 0x3b, 0x17, 0xef, 0xbb, 0x86, 0xaf, 0x05,
-	0x78, 0x99, 0xb9, 0xbe, 0x5f, 0x66, 0x9e, 0xdb, 0xc2, 0xcb, 0x1e, 0x26,
-	0x36, 0x13, 0x47, 0x55, 0x2e, 0x04, 0x3e, 0x68, 0xb2, 0xef, 0x7d, 0x48,
-	0xd9, 0x6e, 0xa9, 0x32, 0xab, 0x70, 0x59, 0x1e, 0xb5, 0x6d, 0x51, 0xe1,
-	0x60, 0x62, 0xe0, 0x2e, 0x91, 0xbe, 0x20, 0x17, 0x05, 0x18, 0x33, 0xec,
-	0xc7, 0x67, 0x9e, 0x29, 0xbc, 0x1d, 0xca, 0x10, 0x03, 0xbb, 0x41, 0x8d,
-	0x40, 0x39, 0x0f, 0x23, 0x76, 0x19, 0xbe, 0xac, 0x3c, 0x9f, 0xdd, 0xb7,
-	0xff, 0x87, 0xef, 0xdb, 0x06, 0xe3, 0x5a, 0x80, 0x11, 0x51, 0x03, 0x55,
-	0xc6, 0xd5, 0xbb, 0x0e, 0x1e, 0x46, 0xf4, 0xf0, 0x61, 0xd6, 0x9d, 0x01,
-	0x4e, 0x9e, 0x95, 0x09, 0xe0, 0xf3, 0xf5, 0xdf, 0x65, 0xef, 0x29, 0xc0,
-	0x44, 0x36, 0xfe, 0xb7, 0xf7, 0xa2, 0x78, 0xdd, 0xa1, 0xce, 0xfe, 0xce,
-	0x0f, 0x45, 0xdb, 0xc6, 0xff, 0x3e, 0xe2, 0x37, 0xea, 0xa1, 0x0a, 0x73,
-	0x1d, 0xb1, 0xd0, 0x6f, 0x40, 0x07, 0x63, 0xd7, 0xc0, 0x42, 0x57, 0xe7,
-	0x26, 0xe6, 0xcb, 0xad, 0xbc, 0xe4, 0x6c, 0xe6, 0x25, 0xee, 0xf1, 0xeb,
-	0x72, 0x27, 0xc7, 0x6c, 0x23, 0x62, 0x4d, 0xe1, 0x33, 0x8f, 0x7c, 0xbd,
-	0x3d, 0x37, 0xcd, 0x5d, 0x47, 0x6e, 0x9a, 0x50, 0xb9, 0x89, 0xf4, 0xa2,
-	0x9e, 0x83, 0x4c, 0xbe, 0x0b, 0x59, 0x7e, 0x07, 0xb4, 0xff, 0x11, 0xf8,
-	0xf9, 0x43, 0x60, 0xac, 0x6f, 0x03, 0x63, 0x7d, 0xab, 0xd2, 0xfe, 0x0e,
-	0xc3, 0xb8, 0xb0, 0x0e, 0xf4, 0xea, 0x66, 0x0f, 0xc3, 0x1f, 0x86, 0x57,
-	0x35, 0xca, 0x86, 0x33, 0x57, 0x1e, 0x31, 0xe6, 0xbd, 0xf3, 0xd2, 0x44,
-	0x4e, 0xd2, 0x88, 0x11, 0xcc, 0x15, 0xea, 0x3a, 0xce, 0x7e, 0x25, 0xb1,
-	0x42, 0x5d, 0xd5, 0x93, 0x43, 0x52, 0x6d, 0x78, 0xf8, 0x6a, 0xe1, 0x8c,
-	0xb7, 0xc6, 0x9c, 0x8f, 0xaf, 0xf2, 0x3e, 0xbe, 0xca, 0x35, 0x36, 0x12,
-	0xac, 0xcf, 0x17, 0x52, 0xdb, 0x31, 0xd5, 0x61, 0x1f, 0x53, 0xcd, 0xff,
-	0x15, 0x31, 0x15, 0xf7, 0xca, 0xe3, 0x99, 0xc9, 0xa5, 0x84, 0x1c, 0x80,
-	0x7c, 0x27, 0xca, 0xd4, 0x93, 0x69, 0xc3, 0x6e, 0x3e, 0x44, 0x57, 0x8e,
-	0xd2, 0x4b, 0x28, 0xe9, 0xe9, 0x69, 0x12, 0x7a, 0x9a, 0xf8, 0xb5, 0xf5,
-	0x8d, 0x1a, 0x33, 0xde, 0x1c, 0x8b, 0xe2, 0xf3, 0x7f, 0xaa, 0x23, 0xd2,
-	0x4f, 0x3d, 0x5d, 0x8d, 0xb9, 0xae, 0x07, 0x7b, 0x6d, 0xc7, 0x5d, 0xb6,
-	0xc2, 0x5d, 0x1d, 0xfe, 0x9c, 0x99, 0x89, 0x49, 0xe8, 0xf0, 0xdf, 0x63,
-	0xce, 0x9f, 0xc0, 0xb7, 0x7e, 0x88, 0x78, 0xfd, 0xef, 0xa0, 0x8b, 0x7f,
-	0x8b, 0xda, 0xe0, 0x55, 0xe4, 0x9f, 0x1f, 0x60, 0x6c, 0x0b, 0xc7, 0xa8,
-	0x33, 0xfa, 0xd1, 0x8c, 0x95, 0x98, 0x28, 0xba, 0x89, 0x09, 0x0f, 0x7f,
-	0xfc, 0xea, 0x6f, 0x66, 0xac, 0x29, 0xbe, 0xc3, 0x00, 0xf9, 0xfe, 0xf9,
-	0xdd, 0x73, 0x0a, 0x7b, 0x04, 0x98, 0x23, 0x67, 0x73, 0xff, 0x92, 0x9b,
-	0x9a, 0xa8, 0xe1, 0xe3, 0x61, 0x9b, 0xef, 0xd9, 0x1e, 0xb6, 0x59, 0xfa,
-	0xeb, 0xd4, 0xbb, 0x87, 0x6b, 0x1e, 0x4e, 0xd3, 0xaf, 0xeb, 0xc0, 0x1c,
-	0x35, 0xf8, 0x64, 0xa1, 0x69, 0xab, 0xcf, 0xf1, 0x8a, 0x6d, 0x46, 0x20,
-	0x1f, 0xf6, 0x58, 0x4f, 0xd1, 0x0b, 0x5d, 0xd3, 0x28, 0x13, 0x81, 0xba,
-	0x66, 0xfc, 0x9f, 0xf9, 0xd7, 0x4f, 0xfb, 0xd7, 0x4f, 0xf9, 0xd7, 0x27,
-	0x91, 0x77, 0x9f, 0x54, 0xb9, 0x93, 0xe3, 0x1c, 0x83, 0x72, 0x5d, 0xac,
-	0x85, 0xf5, 0xce, 0x8e, 0xfe, 0xb4, 0x55, 0x8d, 0x79, 0xfe, 0x5c, 0x68,
-	0x3a, 0xf8, 0xfc, 0x63, 0x7c, 0x0e, 0xe2, 0x33, 0x8d, 0xcf, 0x63, 0xf8,
-	0x6c, 0xca, 0x54, 0xcb, 0x56, 0xa8, 0xa3, 0x61, 0xc9, 0x62, 0xbc, 0x88,
-	0x3a, 0x34, 0x93, 0x7a, 0x44, 0x8a, 0xf5, 0x92, 0x94, 0x96, 0x34, 0xe9,
-	0xb6, 0xd2, 0x52, 0xaa, 0x1f, 0x93, 0xe3, 0x4b, 0xde, 0xb9, 0x61, 0x57,
-	0xda, 0xc6, 0xdc, 0x96, 0x3c, 0x9c, 0x7a, 0x5c, 0xf4, 0x3b, 0x8f, 0x61,
-	0x9e, 0xe8, 0xc5, 0xd1, 0xdb, 0xd4, 0xf9, 0x58, 0x3d, 0xe5, 0xc9, 0xf8,
-	0x80, 0x65, 0x9b, 0xc8, 0x5b, 0xc3, 0x4f, 0x62, 0xed, 0x8c, 0x7a, 0x3f,
-	0x30, 0x2d, 0x27, 0x4e, 0x6f, 0xec, 0xf5, 0x62, 0xa9, 0x69, 0xbc, 0x81,
-	0x4d, 0xeb, 0xe0, 0xc3, 0x46, 0xec, 0x9b, 0x82, 0x9d, 0x1f, 0x71, 0xc3,
-	0xda, 0x04, 0x62, 0xe0, 0x84, 0xab, 0x6a, 0x3d, 0xc4, 0x2a, 0xc3, 0x49,
-	0x9e, 0x8a, 0xe1, 0x9a, 0xef, 0xd0, 0x20, 0x0f, 0x2a, 0x5b, 0xd9, 0x00,
-	0x8e, 0xd1, 0x54, 0xbf, 0xaf, 0xb4, 0x79, 0x0e, 0xa4, 0xfa, 0xff, 0x4e,
-	0x32, 0xa9, 0x4b, 0x7e, 0x8c, 0x38, 0xd6, 0x56, 0xb9, 0xa8, 0x51, 0xb6,
-	0x3f, 0xc1, 0xda, 0xf0, 0x75, 0x61, 0x5e, 0xbb, 0x07, 0xf3, 0x06, 0x10,
-	0x7f, 0x71, 0xaf, 0x09, 0x5e, 0x4e, 0x93, 0x57, 0x3e, 0x83, 0xda, 0xb6,
-	0xfa, 0x49, 0xbd, 0xb8, 0xe4, 0xd7, 0x44, 0xaa, 0x76, 0x48, 0x48, 0x7d,
-	0xf3, 0xcc, 0xc9, 0xeb, 0x93, 0xd4, 0xdd, 0x00, 0x3b, 0xf4, 0x60, 0x0e,
-	0xeb, 0x08, 0xc8, 0xc8, 0x3b, 0x27, 0x53, 0x67, 0x64, 0x45, 0xf7, 0x93,
-	0x7a, 0x69, 0x29, 0x83, 0x71, 0xf6, 0xa4, 0xf1, 0xbd, 0xaa, 0x2b, 0xec,
-	0x7f, 0x31, 0x74, 0x58, 0x1a, 0xd5, 0x16, 0xe8, 0x45, 0x8e, 0xdd, 0x7b,
-	0x58, 0x6a, 0xd5, 0x79, 0x79, 0xa1, 0xba, 0xb1, 0x0b, 0xd8, 0x09, 0x32,
-	0x25, 0xfd, 0x3d, 0x3e, 0xfd, 0x54, 0x41, 0x30, 0x0e, 0x79, 0x9e, 0x2e,
-	0xc4, 0xbd, 0xba, 0x96, 0xb8, 0xed, 0x24, 0xdf, 0x1b, 0x8c, 0xf3, 0x3d,
-	0xbe, 0x23, 0xcb, 0xb4, 0xc9, 0x8b, 0xf7, 0x2e, 0x58, 0x9f, 0x92, 0x0b,
-	0xa9, 0x3d, 0xb2, 0x91, 0x52, 0xf5, 0x2f, 0xf1, 0x01, 0x7c, 0xdb, 0x34,
-	0xd6, 0xe5, 0x6e, 0x39, 0x01, 0x3f, 0xbd, 0x90, 0xca, 0xa9, 0xf3, 0x9b,
-	0xe3, 0x4d, 0x62, 0xfb, 0x79, 0xd6, 0x54, 0xb2, 0xae, 0x7a, 0x60, 0xad,
-	0xd6, 0x64, 0x8a, 0xb1, 0xa7, 0x43, 0x36, 0x14, 0xd6, 0xf2, 0x7a, 0xe3,
-	0x1b, 0xb3, 0x9e, 0x6f, 0x84, 0x94, 0xbd, 0xff, 0x1b, 0xd0, 0x71, 0x0c,
-	0x36, 0x1b, 0x51, 0x73, 0x42, 0xe9, 0x4e, 0x7f, 0x8e, 0xc2, 0x66, 0x6d,
-	0x73, 0xc6, 0xc7, 0x33, 0x96, 0xf1, 0xa9, 0x8c, 0x35, 0x36, 0xe1, 0xf5,
-	0x53, 0x4c, 0xc3, 0xd6, 0x2e, 0xb6, 0x82, 0xf7, 0x4d, 0xa6, 0xe0, 0x4f,
-	0x2f, 0x6d, 0x62, 0x63, 0x18, 0xe7, 0xf3, 0x0b, 0xd0, 0x6b, 0x58, 0x3a,
-	0x4e, 0xb5, 0xee, 0x99, 0x4b, 0x8d, 0x24, 0x8e, 0x08, 0xdf, 0x30, 0x62,
-	0xfd, 0x6c, 0x82, 0xda, 0x05, 0xe4, 0xc3, 0x2b, 0xc4, 0x08, 0xc3, 0xe7,
-	0xe5, 0xca, 0x3d, 0x99, 0xd4, 0x7e, 0xad, 0x36, 0x8b, 0xea, 0xe4, 0xf9,
-	0x29, 0xe6, 0xd3, 0xa3, 0xec, 0x7d, 0x86, 0x4e, 0xbd, 0xad, 0x39, 0x65,
-	0xf5, 0x8e, 0x39, 0xf4, 0xd2, 0xd2, 0xe6, 0x21, 0x37, 0x3c, 0x3f, 0xc3,
-	0x04, 0xa8, 0x5b, 0x83, 0x09, 0x47, 0x72, 0xec, 0x71, 0x49, 0x7e, 0x59,
-	0xf6, 0x65, 0x10, 0x47, 0xed, 0x99, 0x0e, 0x99, 0x6f, 0x18, 0xce, 0xe0,
-	0xe2, 0x51, 0xac, 0x31, 0x87, 0xb5, 0xa6, 0x51, 0x83, 0xcc, 0x22, 0x27,
-	0x53, 0xae, 0x8c, 0xd5, 0x0f, 0x43, 0x46, 0x37, 0xf1, 0xcc, 0x78, 0x3c,
-	0x27, 0xe6, 0x4c, 0x41, 0xad, 0xfb, 0x9e, 0x96, 0x1f, 0xfd, 0x18, 0x72,
-	0x5a, 0x58, 0x0e, 0x24, 0x45, 0x9f, 0x4e, 0x86, 0xdf, 0x9f, 0xb3, 0x38,
-	0x16, 0xe5, 0x98, 0x8e, 0xb1, 0xf0, 0xe7, 0x92, 0x51, 0x3d, 0x93, 0x34,
-	0xc7, 0xd9, 0xef, 0x0d, 0x59, 0x73, 0x12, 0x7a, 0xbe, 0xb7, 0x47, 0xba,
-	0xa7, 0xa5, 0x77, 0xd5, 0x1c, 0x7f, 0x1d, 0xb4, 0x84, 0x55, 0x6c, 0x9f,
-	0x13, 0xdd, 0x1f, 0xef, 0xd9, 0x1c, 0x0f, 0xfb, 0xe3, 0xd3, 0xd2, 0xbd,
-	0x3a, 0x62, 0xbc, 0x29, 0x87, 0xb1, 0x66, 0x48, 0x2e, 0xa1, 0xa6, 0xb1,
-	0x86, 0xe6, 0xe0, 0x73, 0x0f, 0x91, 0x96, 0x83, 0xc0, 0x14, 0xf0, 0x09,
-	0xd4, 0xd9, 0xd6, 0x27, 0xe5, 0x4b, 0x46, 0x97, 0xe4, 0x55, 0x4d, 0x1b,
-	0xf6, 0x7a, 0xa5, 0xb0, 0xf3, 0x5b, 0x87, 0xa6, 0x77, 0x7b, 0xfd, 0x00,
-	0x9e, 0x67, 0x8c, 0x62, 0xec, 0x4a, 0x6b, 0xc5, 0xe2, 0x18, 0xef, 0x5d,
-	0x69, 0xd5, 0xad, 0x11, 0x23, 0xab, 0x45, 0xfd, 0x73, 0xed, 0x79, 0xc5,
-	0x7b, 0xa1, 0x3a, 0x68, 0xd4, 0xe4, 0x16, 0x2d, 0x7b, 0x03, 0xf2, 0x83,
-	0xfb, 0x19, 0xcc, 0xbd, 0xd2, 0xca, 0x58, 0xf3, 0xaa, 0x7f, 0x5f, 0x93,
-	0xe0, 0x9a, 0xeb, 0x8c, 0x18, 0x93, 0xea, 0xd9, 0x11, 0xe3, 0x84, 0xd6,
-	0xfe, 0xac, 0xa1, 0x4d, 0x6e, 0x7b, 0xb6, 0x5b, 0xc9, 0x28, 0x64, 0x79,
-	0x73, 0x4a, 0xd5, 0x69, 0x79, 0xda, 0xe5, 0xbc, 0x2b, 0xad, 0xac, 0x15,
-	0xd1, 0x4e, 0xdc, 0xc0, 0x18, 0xc8, 0xb9, 0x97, 0xaf, 0xda, 0x87, 0xd7,
-	0xd7, 0xda, 0xe3, 0x5d, 0xd9, 0xbe, 0xc7, 0x2e, 0x35, 0xe7, 0x82, 0x9a,
-	0x13, 0x56, 0xb2, 0xde, 0xbe, 0xcf, 0xcf, 0x64, 0xfb, 0x3e, 0xdd, 0x9b,
-	0x3c, 0x97, 0xb0, 0xe6, 0x93, 0x98, 0x5b, 0x76, 0x07, 0xe3, 0x75, 0xb9,
-	0xdc, 0xca, 0x5b, 0x17, 0xe5, 0xc2, 0xe6, 0xda, 0xbf, 0xc2, 0x75, 0x3b,
-	0x4d, 0xbf, 0xf2, 0x69, 0xe4, 0x77, 0x8e, 0x3d, 0xaa, 0xe4, 0xbd, 0xdb,
-	0x1a, 0x3c, 0x58, 0xd3, 0xcc, 0xf1, 0x9f, 0x09, 0x75, 0x75, 0x44, 0xc5,
-	0x98, 0xdb, 0xa0, 0xa7, 0x7d, 0xcf, 0xc0, 0x67, 0x47, 0x6d, 0x35, 0xe7,
-	0x92, 0x35, 0x2d, 0xfb, 0x4e, 0x0d, 0x1a, 0x97, 0x10, 0xdb, 0x9c, 0x18,
-	0xaf, 0x51, 0x2b, 0x59, 0x7c, 0x27, 0xfe, 0x4e, 0xd6, 0x01, 0xd0, 0xe5,
-	0xe0, 0xf0, 0xcf, 0xe4, 0xa8, 0x9c, 0xa8, 0x1c, 0x43, 0x2e, 0x9c, 0x93,
-	0xe1, 0x67, 0x90, 0x37, 0x2a, 0x05, 0x3c, 0x49, 0x9f, 0xf5, 0x72, 0xe0,
-	0x9c, 0x7a, 0xcf, 0xfc, 0x24, 0xea, 0x64, 0xd8, 0x6e, 0x79, 0x70, 0x78,
-	0x05, 0xcf, 0xbc, 0xa0, 0x70, 0xa8, 0x2b, 0x0d, 0xf8, 0x40, 0xe2, 0xf9,
-	0x3d, 0xb2, 0xfb, 0x01, 0xda, 0x22, 0x32, 0xfd, 0x6d, 0x11, 0xf5, 0xee,
-	0xbd, 0x6e, 0x75, 0x8a, 0xec, 0xa5, 0xdd, 0x34, 0x61, 0x63, 0x73, 0xde,
-	0x99, 0xd6, 0xb6, 0x6b, 0x73, 0xe6, 0xa2, 0xac, 0x2a, 0xfb, 0xbb, 0x7d,
-	0xd5, 0xfb, 0x3f, 0xba, 0x8a, 0x72, 0x38, 0x39, 0x2d, 0x77, 0xac, 0x7a,
-	0xf6, 0x56, 0x5a, 0x3a, 0xaa, 0xe4, 0x3a, 0xa7, 0xe4, 0xda, 0x92, 0xc3,
-	0x29, 0xca, 0x9c, 0xbc, 0xf0, 0xbd, 0x40, 0x4f, 0x16, 0xf7, 0xfb, 0xf6,
-	0x33, 0xf8, 0x0c, 0x7f, 0x57, 0x42, 0xd9, 0xb0, 0xee, 0xbe, 0x7f, 0x37,
-	0xcf, 0x59, 0xf7, 0xad, 0x92, 0xcf, 0x1b, 0xb7, 0xf1, 0xf9, 0x14, 0x62,
-	0xea, 0xd0, 0x90, 0xc7, 0xeb, 0xab, 0x4b, 0x1f, 0xce, 0xeb, 0x37, 0x37,
-	0x79, 0x0d, 0x49, 0x43, 0xd5, 0xaf, 0x5d, 0xbd, 0xd2, 0x8d, 0xa8, 0x07,
-	0x7b, 0xf8, 0x09, 0xf6, 0x9a, 0x12, 0xd2, 0xe0, 0xed, 0xb7, 0xe1, 0x92,
-	0x96, 0x80, 0x76, 0xd2, 0x73, 0x9f, 0xaf, 0x2f, 0xee, 0x7f, 0x74, 0xc7,
-	0x7b, 0x97, 0xc4, 0x70, 0x86, 0x31, 0xa6, 0x2b, 0x9d, 0x65, 0x7d, 0xff,
-	0x9a, 0x16, 0x5d, 0xe9, 0xcc, 0xde, 0xd4, 0xd9, 0xeb, 0xd0, 0x59, 0x5d,
-	0x7e, 0x13, 0xbc, 0xc0, 0x9f, 0x9f, 0x19, 0x31, 0x0e, 0x13, 0x5b, 0x18,
-	0x5c, 0x0f, 0x31, 0xd4, 0xd7, 0x5d, 0xc7, 0x47, 0xd0, 0xdd, 0x9b, 0xa2,
-	0xf4, 0x07, 0x7e, 0x90, 0x7f, 0xd4, 0xf3, 0x8c, 0x61, 0xe4, 0xa9, 0x43,
-	0xf9, 0x3e, 0x69, 0x53, 0x67, 0xfc, 0x33, 0x9e, 0x3e, 0x95, 0x6f, 0xfb,
-	0xfa, 0xcc, 0xcd, 0x50, 0x67, 0xe6, 0x6e, 0x4f, 0x7f, 0x9d, 0x6a, 0xce,
-	0x62, 0x32, 0xa1, 0xfc, 0xda, 0x1a, 0xba, 0x65, 0x37, 0x75, 0xf8, 0xb4,
-	0xeb, 0xfd, 0x2f, 0xbb, 0xd3, 0xb2, 0xe8, 0x7e, 0x98, 0x1e, 0x3d, 0x1d,
-	0x4e, 0x88, 0xe7, 0x3f, 0x57, 0xeb, 0x4f, 0x5f, 0x0d, 0x2b, 0x5b, 0x9d,
-	0x80, 0xec, 0x4e, 0x56, 0x3e, 0xe6, 0xdb, 0xb7, 0xc7, 0xeb, 0xd0, 0x87,
-	0xf0, 0x7a, 0xb8, 0x3c, 0x68, 0xbc, 0x8d, 0xb5, 0x26, 0x15, 0x86, 0x8b,
-	0x88, 0xe3, 0xf3, 0x9a, 0xd8, 0xe4, 0x35, 0xa0, 0xcd, 0x9b, 0x97, 0x65,
-	0x5d, 0xea, 0x32, 0x3e, 0x3d, 0xaa, 0xde, 0xbf, 0x7f, 0xa3, 0xcc, 0xb8,
-	0x0c, 0xcc, 0x13, 0xeb, 0x93, 0x4b, 0x8d, 0x84, 0x5c, 0x22, 0x96, 0x18,
-	0xc3, 0x7f, 0xf7, 0x98, 0x9f, 0x9b, 0xa3, 0xf2, 0x66, 0xb9, 0xbd, 0x56,
-	0x1c, 0x95, 0xd7, 0xcb, 0x41, 0xbd, 0x48, 0x2c, 0xcb, 0xfc, 0x3f, 0x27,
-	0x6f, 0x2d, 0x0d, 0xca, 0xfa, 0x0c, 0xf2, 0xf8, 0x10, 0x65, 0x30, 0x62,
-	0x7c, 0x46, 0xfd, 0xbe, 0xe2, 0x4a, 0xeb, 0xbc, 0x85, 0x75, 0x97, 0x5b,
-	0x72, 0x84, 0xe7, 0xd0, 0xfc, 0xde, 0xf8, 0x04, 0x56, 0xe1, 0xbc, 0x3e,
-	0xa9, 0x2d, 0xa3, 0x2e, 0x2f, 0x73, 0x5d, 0xca, 0x69, 0x5a, 0x7d, 0x9f,
-	0xc4, 0x3e, 0xf7, 0xf3, 0xbd, 0xf4, 0x18, 0x75, 0x71, 0xa5, 0xb5, 0x61,
-	0xf1, 0x1c, 0x72, 0x4e, 0x1a, 0xd0, 0xd7, 0x97, 0x93, 0x3c, 0x27, 0xcf,
-	0x0b, 0x7f, 0x9f, 0x52, 0x6b, 0xcc, 0xa0, 0x16, 0xb8, 0xd2, 0x5a, 0xb0,
-	0x9e, 0x52, 0x7a, 0x6a, 0x54, 0x1f, 0xf0, 0xc7, 0x79, 0xcd, 0x7b, 0x86,
-	0xb3, 0x6f, 0x88, 0xf5, 0xe7, 0x03, 0xc8, 0xff, 0xac, 0x3d, 0x89, 0xb7,
-	0x28, 0x8b, 0x04, 0x6a, 0x5c, 0xae, 0xc5, 0xdf, 0x04, 0x25, 0x87, 0xf3,
-	0x32, 0x09, 0x7a, 0x80, 0xcb, 0x5c, 0xc6, 0xfd, 0x5b, 0x65, 0x23, 0xe6,
-	0xc5, 0x77, 0xbe, 0xaf, 0xb5, 0x81, 0x98, 0xbf, 0xb1, 0x19, 0xf3, 0xfb,
-	0x71, 0x6d, 0x38, 0xa9, 0xa1, 0xff, 0x84, 0xf5, 0xd9, 0x77, 0x61, 0xcc,
-	0x1f, 0xc7, 0x7c, 0x8e, 0xf5, 0x49, 0x69, 0x59, 0x6c, 0xf6, 0x99, 0x6a,
-	0xc2, 0x77, 0x31, 0x72, 0xb2, 0xd8, 0x18, 0x8c, 0x9f, 0xd7, 0x1c, 0xf5,
-	0xce, 0x46, 0x72, 0x88, 0x7d, 0xb7, 0x3e, 0x69, 0x2c, 0x4b, 0x22, 0x94,
-	0x7e, 0x48, 0xdc, 0x86, 0x87, 0xb9, 0x17, 0x34, 0xf6, 0xdf, 0x6c, 0x69,
-	0x6c, 0x9f, 0x63, 0x84, 0xd2, 0x87, 0xe4, 0x0f, 0xfc, 0x39, 0x8e, 0x9a,
-	0xf3, 0x1f, 0x76, 0xf3, 0xec, 0xab, 0xe1, 0xf6, 0x82, 0x06, 0xd2, 0x76,
-	0x63, 0xfb, 0xbe, 0x89, 0xad, 0x7d, 0xb9, 0x27, 0x6a, 0x98, 0xbd, 0x36,
-	0xf6, 0x7d, 0x15, 0xcf, 0x3c, 0x04, 0x3a, 0xae, 0x84, 0x74, 0xeb, 0x21,
-	0x29, 0x36, 0xae, 0xde, 0xa3, 0x9d, 0x06, 0x3e, 0xc3, 0xf5, 0xb9, 0xcf,
-	0x21, 0xd0, 0x77, 0x45, 0xd3, 0xad, 0x43, 0x90, 0xa5, 0xb7, 0x47, 0xe8,
-	0x39, 0xd3, 0xf8, 0xa1, 0x0c, 0x89, 0xbe, 0xa2, 0x29, 0xf9, 0xeb, 0xb5,
-	0x51, 0x38, 0xc4, 0x94, 0x74, 0xaf, 0xcd, 0x4a, 0x68, 0x8d, 0x3d, 0x00,
-	0xda, 0x22, 0xf5, 0xb8, 0x0b, 0x7e, 0x2c, 0x76, 0xd8, 0x22, 0xde, 0x67,
-	0x1f, 0x77, 0xb5, 0x57, 0x7a, 0x89, 0xf7, 0x59, 0x0f, 0x1c, 0xc4, 0x7f,
-	0xd6, 0x04, 0x2f, 0xb5, 0x32, 0xa9, 0x77, 0x54, 0xde, 0xcc, 0x37, 0x78,
-	0xdf, 0x4c, 0x88, 0xf0, 0x1e, 0xe3, 0x43, 0x9f, 0x44, 0xbe, 0x3e, 0x8c,
-	0x98, 0x90, 0x03, 0x76, 0xc6, 0xba, 0xa7, 0x86, 0x24, 0xec, 0xbd, 0xeb,
-	0xa0, 0xfa, 0x25, 0x6f, 0x2d, 0x9b, 0xfe, 0xef, 0x53, 0x64, 0xdf, 0xf9,
-	0x14, 0x7b, 0x9a, 0x03, 0xb0, 0x53, 0xd6, 0x23, 0xa2, 0x6f, 0xa0, 0xde,
-	0xbc, 0xd4, 0x88, 0xf6, 0xf2, 0x7d, 0xcb, 0xd7, 0x5d, 0x5c, 0x13, 0xbb,
-	0xc7, 0x14, 0x56, 0xf4, 0xef, 0xf1, 0x3b, 0xea, 0xa0, 0x6d, 0x98, 0x32,
-	0x01, 0x4c, 0xc9, 0x3a, 0x69, 0xca, 0x7f, 0xe7, 0xcd, 0x70, 0x4e, 0x6c,
-	0xab, 0x95, 0x86, 0x65, 0x03, 0x38, 0x6b, 0xdd, 0xb5, 0x10, 0x07, 0xdf,
-	0xd6, 0xea, 0x65, 0xf5, 0xbb, 0x34, 0xed, 0x01, 0x60, 0xac, 0x44, 0x9f,
-	0xaa, 0x75, 0x4e, 0x3e, 0x20, 0x9e, 0xbd, 0xc3, 0xca, 0x54, 0xcc, 0x5a,
-	0xaf, 0x7a, 0xb5, 0xc5, 0x46, 0x75, 0x4a, 0xfe, 0xd4, 0x5d, 0x50, 0xbd,
-	0xd2, 0x25, 0xd4, 0x1b, 0xe1, 0x45, 0x55, 0x6b, 0xb5, 0xe1, 0x54, 0xc4,
-	0xb7, 0x67, 0x8f, 0xc0, 0x07, 0x4d, 0xf5, 0x6e, 0x81, 0xbe, 0xd2, 0x6a,
-	0x65, 0x11, 0x2f, 0x74, 0xcb, 0x32, 0x8a, 0xc8, 0x73, 0x59, 0xf5, 0x7e,
-	0x0a, 0xfd, 0xf7, 0xf7, 0x54, 0x1c, 0x96, 0x1a, 0x64, 0xf3, 0x5c, 0x02,
-	0xeb, 0x68, 0xca, 0x3e, 0x43, 0x4a, 0x0f, 0x0f, 0x28, 0xec, 0x1a, 0x5a,
-	0x41, 0x80, 0x5a, 0x1b, 0x12, 0x59, 0x81, 0xbf, 0xc2, 0x77, 0xc3, 0x6b,
-	0xd4, 0x01, 0x65, 0x3b, 0x2b, 0x11, 0xc8, 0x9e, 0x58, 0x22, 0xb4, 0x48,
-	0x19, 0xc7, 0x61, 0x17, 0x5c, 0x07, 0x32, 0xe6, 0xbb, 0x2c, 0xcb, 0x1d,
-	0xf2, 0x4c, 0xc3, 0xf4, 0xdf, 0x3d, 0x7f, 0x89, 0xef, 0xa3, 0xeb, 0x73,
-	0x63, 0x03, 0xc4, 0x4f, 0x52, 0x6a, 0x00, 0x63, 0x9c, 0x66, 0x0d, 0xce,
-	0x18, 0x50, 0x88, 0x47, 0x94, 0xaf, 0xb3, 0x06, 0xf6, 0x7c, 0x9f, 0xf8,
-	0x3a, 0x62, 0x11, 0xdb, 0x8e, 0x62, 0x8f, 0x9d, 0xe4, 0xea, 0xd5, 0x9e,
-	0x93, 0xa0, 0xf3, 0xfc, 0x92, 0x39, 0x55, 0x90, 0x14, 0xdf, 0x71, 0x9e,
-	0xb1, 0xc1, 0xf7, 0x06, 0xe2, 0xe4, 0x42, 0x85, 0xef, 0x33, 0x17, 0xe1,
-	0x59, 0x53, 0x72, 0xbe, 0xcc, 0x1a, 0xf0, 0x76, 0xe8, 0x8b, 0xd7, 0xc5,
-	0xf1, 0x10, 0xfc, 0xff, 0xa2, 0xc1, 0xdf, 0x91, 0xf1, 0x77, 0x41, 0x66,
-	0x2a, 0xa1, 0x1d, 0x84, 0x8e, 0x0b, 0x46, 0xc4, 0xb7, 0x03, 0xa7, 0x4c,
-	0x8c, 0x35, 0x62, 0x9c, 0xc3, 0xf7, 0x97, 0xdd, 0xcb, 0x2d, 0xd6, 0x3f,
-	0x17, 0x10, 0xe7, 0xa6, 0x92, 0x53, 0xb0, 0x9d, 0x42, 0xbc, 0x13, 0xb4,
-	0xfe, 0x5d, 0xdc, 0xcb, 0xbb, 0xdc, 0xc7, 0x4c, 0x5d, 0x94, 0x22, 0x30,
-	0xfd, 0x48, 0xe2, 0x65, 0xd9, 0x83, 0x3a, 0x55, 0x93, 0x37, 0x2d, 0x73,
-	0x5c, 0x34, 0xb5, 0xde, 0xf0, 0x7d, 0xb0, 0xbd, 0x37, 0x10, 0xdf, 0x3a,
-	0xfc, 0xda, 0x3d, 0x5b, 0x26, 0x16, 0x3a, 0xaa, 0xde, 0x05, 0xb8, 0x60,
-	0xb1, 0x7f, 0xc7, 0xdf, 0x44, 0xfe, 0xa5, 0xda, 0x63, 0xeb, 0x8c, 0x8d,
-	0xfd, 0x63, 0xd2, 0xe7, 0xf1, 0x78, 0xc0, 0xf2, 0x68, 0xe4, 0x3a, 0x91,
-	0xb6, 0x75, 0xce, 0xfb, 0xeb, 0x9c, 0xf5, 0xd7, 0xa9, 0xf9, 0xeb, 0x5c,
-	0xd8, 0x5c, 0xe7, 0x6e, 0xe8, 0xbf, 0xd5, 0x7a, 0x0a, 0xf8, 0x21, 0x93,
-	0x6a, 0xb5, 0x1c, 0xd4, 0x59, 0xa5, 0xd1, 0x79, 0x75, 0x46, 0xaa, 0xa7,
-	0xbf, 0x71, 0x6f, 0xc6, 0x2a, 0xc4, 0xc3, 0x0a, 0x7b, 0xa0, 0x92, 0x82,
-	0x1d, 0x16, 0xc4, 0xc3, 0xdc, 0x3c, 0xb7, 0xf3, 0xce, 0xf5, 0xba, 0xa1,
-	0xc3, 0x1c, 0x72, 0x86, 0x91, 0x39, 0x67, 0x49, 0x61, 0xdf, 0x6f, 0xea,
-	0xb0, 0xf3, 0x5e, 0xe4, 0x87, 0x9f, 0xc0, 0x66, 0x8c, 0x4c, 0xbd, 0x91,
-	0x43, 0xbd, 0xc3, 0xf9, 0x77, 0x40, 0x8f, 0x85, 0x4c, 0xad, 0x51, 0xc8,
-	0x9c, 0xe5, 0x79, 0x0e, 0xe6, 0xd5, 0x1a, 0x3d, 0x90, 0x7b, 0x8f, 0xea,
-	0x8b, 0xbc, 0x5c, 0x8e, 0x31, 0x06, 0xc1, 0xd6, 0x63, 0x18, 0x8b, 0xab,
-	0xdf, 0x68, 0xd5, 0xdd, 0x65, 0xf8, 0x74, 0x02, 0xe3, 0xd5, 0xae, 0x49,
-	0x85, 0x47, 0x2d, 0x59, 0x71, 0x7f, 0xa5, 0x15, 0xcb, 0x97, 0xb5, 0x52,
-	0x79, 0x18, 0x73, 0x46, 0xf9, 0x5b, 0x9f, 0x3d, 0xc0, 0x49, 0x53, 0xd5,
-	0x1d, 0x69, 0x4a, 0x80, 0x26, 0xbd, 0x8d, 0xa6, 0x04, 0xe8, 0x41, 0xcc,
-	0x3c, 0xc5, 0xde, 0xf1, 0xa8, 0x9c, 0x28, 0xf3, 0x9d, 0x26, 0xfe, 0x46,
-	0xd5, 0x90, 0x30, 0xb0, 0x65, 0xe4, 0x94, 0x19, 0x5f, 0x57, 0xbd, 0x1a,
-	0x73, 0xb8, 0x2e, 0x23, 0xa9, 0xba, 0xa8, 0xfc, 0x92, 0x38, 0x81, 0x7c,
-	0xf5, 0x86, 0xdb, 0x23, 0x6f, 0xfa, 0x7b, 0x5d, 0x14, 0x9e, 0x33, 0x6e,
-	0xdf, 0xeb, 0xc9, 0x4a, 0x2a, 0xf3, 0x8a, 0x15, 0xf2, 0xf9, 0xea, 0xc3,
-	0x5e, 0x7b, 0x30, 0x37, 0x95, 0x39, 0xdf, 0xd8, 0x69, 0xae, 0x83, 0xb9,
-	0x91, 0xb6, 0xb9, 0x0e, 0xe6, 0xf5, 0x20, 0xef, 0xf5, 0x28, 0x9e, 0x4a,
-	0xa0, 0xeb, 0x52, 0x99, 0x3c, 0xf1, 0x0c, 0x82, 0x7b, 0x1a, 0xc4, 0xc6,
-	0x53, 0xe2, 0x9f, 0xd9, 0xf2, 0xf7, 0x7a, 0x57, 0xf5, 0x6b, 0x94, 0x0d,
-	0x4c, 0x58, 0x3c, 0x9b, 0x99, 0xd1, 0xb2, 0xf5, 0x3c, 0x72, 0xd5, 0x8d,
-	0xc4, 0x43, 0x29, 0x1b, 0xb9, 0x92, 0xe7, 0x3c, 0x8d, 0x72, 0x81, 0xef,
-	0x3d, 0xc3, 0x2e, 0xde, 0x21, 0x5e, 0xbe, 0x31, 0xa4, 0xde, 0x43, 0x70,
-	0xfc, 0x73, 0x20, 0x31, 0x32, 0x63, 0x7c, 0xf7, 0xe0, 0x6e, 0xa9, 0x2f,
-	0x7f, 0x11, 0x63, 0x19, 0xe4, 0xc5, 0x43, 0x5a, 0xe6, 0xdc, 0x24, 0xae,
-	0x1f, 0xc2, 0x35, 0xe2, 0xf0, 0x72, 0x0e, 0xf7, 0x1f, 0xc2, 0xf5, 0xbc,
-	0x96, 0x6d, 0xe6, 0x70, 0xfd, 0x30, 0xae, 0x27, 0x48, 0x9b, 0xf3, 0x8a,
-	0x35, 0xa5, 0xd9, 0x58, 0xcb, 0x3e, 0x37, 0x89, 0x4f, 0xfb, 0x7a, 0xbc,
-	0x07, 0x3d, 0x95, 0x79, 0x3e, 0x96, 0x04, 0x4d, 0x0f, 0x6a, 0x4e, 0xbd,
-	0x1b, 0x6b, 0x0c, 0xe1, 0x79, 0xda, 0x54, 0xfb, 0x39, 0xd4, 0x6d, 0xaa,
-	0x67, 0x14, 0x4a, 0xa7, 0x81, 0x77, 0x1f, 0x41, 0xde, 0xd7, 0xc4, 0xb1,
-	0x1e, 0x97, 0x62, 0x2a, 0x2d, 0x0b, 0xf5, 0x90, 0x64, 0x63, 0x05, 0x7c,
-	0x2f, 0x48, 0x66, 0x1c, 0xf7, 0xeb, 0xb4, 0x05, 0xce, 0x2b, 0x49, 0xb1,
-	0x4a, 0xfc, 0xce, 0x7e, 0xd1, 0x57, 0xc0, 0x37, 0xfb, 0x44, 0x79, 0xc8,
-	0x20, 0x46, 0xfb, 0xdd, 0xa1, 0xa7, 0xe5, 0xbd, 0xd3, 0x8c, 0x7c, 0xac,
-	0x65, 0xea, 0xfe, 0x59, 0x9d, 0xc5, 0xdf, 0x2b, 0xb1, 0x47, 0x25, 0xc5,
-	0x50, 0x9a, 0x7d, 0x0e, 0xd5, 0x17, 0x4f, 0x79, 0x67, 0x7a, 0xed, 0xef,
-	0x90, 0x04, 0xfe, 0xc2, 0x7d, 0xbf, 0x82, 0xe7, 0xbd, 0xbe, 0x54, 0xb6,
-	0xf9, 0x41, 0x5d, 0xf0, 0x5d, 0xfd, 0x15, 0xe8, 0xe2, 0xfc, 0x87, 0xf6,
-	0xb9, 0xd8, 0xe3, 0x9a, 0x47, 0x2c, 0x62, 0x7f, 0x2c, 0x90, 0xdf, 0xd5,
-	0x34, 0x92, 0xbe, 0xc3, 0x58, 0x4b, 0x52, 0x8c, 0xb3, 0xb9, 0x58, 0x42,
-	0xd5, 0xbe, 0x1b, 0x4b, 0xf2, 0xc4, 0x16, 0xbd, 0xa4, 0x95, 0x72, 0x78,
-	0x04, 0xf5, 0x1a, 0x7f, 0xff, 0xf0, 0xb8, 0xe4, 0x53, 0xec, 0xd1, 0x84,
-	0x90, 0x0b, 0x0b, 0xf8, 0xbe, 0x25, 0xb7, 0x92, 0x2f, 0xb7, 0x7c, 0xf5,
-	0x5b, 0x4a, 0x77, 0x35, 0x8b, 0xfb, 0x05, 0xbd, 0x8b, 0x69, 0xa5, 0xb3,
-	0x9a, 0x7a, 0xcf, 0x36, 0xe0, 0x3d, 0xe8, 0xbf, 0xed, 0x6c, 0x73, 0x93,
-	0x16, 0x69, 0xfb, 0x38, 0xdf, 0x5b, 0x18, 0xb6, 0x85, 0xf4, 0x93, 0x0f,
-	0xe6, 0xac, 0xe0, 0x5c, 0x34, 0xe0, 0x21, 0xe0, 0xf3, 0xa3, 0xca, 0x85,
-	0x74, 0xee, 0x31, 0xa4, 0x7b, 0xca, 0x08, 0x59, 0xcc, 0x01, 0x9f, 0xf6,
-	0xfb, 0xf8, 0xff, 0x37, 0xe5, 0xea, 0xf1, 0x1e, 0x86, 0xa8, 0xfc, 0xdf,
-	0x8b, 0xee, 0xa0, 0xf7, 0xab, 0xcf, 0x80, 0x0d, 0xe7, 0xac, 0xb5, 0xc5,
-	0x67, 0x6d, 0x07, 0x3e, 0x6b, 0x3e, 0x9f, 0x1f, 0x7e, 0x4e, 0xea, 0xd1,
-	0x59, 0x5b, 0xb2, 0xc1, 0x23, 0x6d, 0x6a, 0x27, 0x7b, 0xe3, 0x6f, 0x9c,
-	0xd4, 0xef, 0xad, 0xa2, 0xb6, 0x7b, 0xad, 0x5e, 0x27, 0xeb, 0x64, 0xcf,
-	0xee, 0xce, 0x22, 0xd7, 0x55, 0xab, 0x5e, 0xcd, 0x5c, 0x75, 0xd9, 0x6b,
-	0xde, 0x69, 0x6f, 0x0d, 0x34, 0xff, 0x8e, 0x7a, 0xef, 0xa4, 0xe4, 0x7a,
-	0x7d, 0xa9, 0x6a, 0xb5, 0x3d, 0x57, 0xde, 0xc0, 0x3c, 0x39, 0x5c, 0x90,
-	0x19, 0xe8, 0x31, 0x89, 0xeb, 0x9b, 0xe5, 0xe5, 0x65, 0x75, 0x86, 0xe4,
-	0x9f, 0xd5, 0xf0, 0x0c, 0x46, 0x9d, 0x43, 0x23, 0x5e, 0xcd, 0xaa, 0x78,
-	0xbd, 0xb1, 0xac, 0xee, 0xa9, 0xdf, 0x3c, 0xd4, 0xdd, 0x19, 0xc4, 0x73,
-	0xd4, 0x06, 0xd6, 0x6e, 0x29, 0xa2, 0x86, 0x3e, 0x6b, 0xcd, 0x18, 0xc4,
-	0x29, 0x5c, 0x6b, 0x03, 0x6b, 0x9d, 0x5f, 0x96, 0xbd, 0x7c, 0xa7, 0xa3,
-	0xaa, 0xce, 0xbd, 0xbc, 0x7e, 0xf5, 0xbc, 0x04, 0xbf, 0xd7, 0x8d, 0xfa,
-	0x39, 0x8e, 0xef, 0x95, 0xf0, 0xb7, 0xa7, 0x8c, 0x01, 0xa8, 0x6b, 0x66,
-	0x0a, 0x58, 0xaf, 0xd5, 0xf2, 0xfa, 0xd9, 0x2d, 0xd8, 0x7d, 0x84, 0xbf,
-	0x65, 0xc0, 0xdf, 0x23, 0xb0, 0x13, 0xf8, 0xc1, 0xe6, 0x38, 0xaf, 0x59,
-	0x4b, 0x04, 0xd7, 0x4c, 0x58, 0xff, 0x1b, 0xed, 0xcc, 0xfa, 0xa1, 0x98,
-	0x41, 0x00, 0x00, 0x00 };
-static u32 bnx2_TXP_b09FwData[(0xd0/4) + 1] = {
+	0x1f, 0x8b, 0x08, 0x00, 0x0e, 0x34, 0xe7, 0x45, 0x00, 0x03, 0xcd, 0x7c,
+	0x6f, 0x70, 0x5b, 0xd7, 0x95, 0xdf, 0x79, 0xef, 0x81, 0x24, 0x48, 0xd1,
+	0xd4, 0x13, 0x17, 0x56, 0x60, 0x87, 0x71, 0x00, 0xf1, 0x81, 0x66, 0x42,
+	0xae, 0x04, 0x2b, 0x4c, 0xc2, 0x6d, 0xd1, 0xf8, 0x05, 0x00, 0x29, 0x48,
+	0xd1, 0x6c, 0x68, 0x95, 0x49, 0x94, 0x54, 0xe3, 0x62, 0x41, 0x52, 0xf1,
+	0xb6, 0xce, 0x54, 0x9b, 0x78, 0x5a, 0x4d, 0xeb, 0xad, 0x11, 0x90, 0xfa,
+	0xe7, 0x85, 0x04, 0xda, 0x62, 0x44, 0x7f, 0xc8, 0x07, 0x18, 0x80, 0x24,
+	0x6f, 0xf2, 0x44, 0x28, 0x9b, 0x7f, 0xfd, 0xd0, 0xac, 0x50, 0x4a, 0xd6,
+	0xba, 0x9b, 0xb4, 0xa3, 0xed, 0x66, 0x67, 0x3b, 0xd3, 0x2f, 0x1c, 0x49,
+	0xf6, 0x7a, 0x77, 0x67, 0x36, 0xda, 0x6e, 0xb6, 0xab, 0xb6, 0xb2, 0xd1,
+	0xdf, 0xef, 0xbe, 0xf7, 0x28, 0x90, 0xa6, 0x6c, 0xcb, 0xb3, 0xed, 0x94,
+	0x33, 0x18, 0xe0, 0xdd, 0x77, 0xdf, 0xb9, 0xe7, 0x9e, 0x73, 0xee, 0x39,
+	0xe7, 0x77, 0xee, 0x7d, 0x0c, 0x8b, 0x74, 0x89, 0xf7, 0xf7, 0x00, 0x3e,
+	0x91, 0x43, 0x87, 0x9f, 0xd9, 0x3e, 0xb2, 0xfd, 0x13, 0xf8, 0xf9, 0x09,
+	0x31, 0x02, 0x06, 0x6f, 0xbe, 0x69, 0x88, 0x64, 0xff, 0x42, 0x3e, 0xf0,
+	0x1f, 0x1e, 0x37, 0x7d, 0xfa, 0xfc, 0x48, 0x50, 0x4f, 0x4c, 0xec, 0x4a,
+	0x5a, 0x12, 0x34, 0x12, 0xb2, 0x6f, 0xca, 0x12, 0xb1, 0x9d, 0xa1, 0x48,
+	0x4a, 0xde, 0x6a, 0xe6, 0x43, 0x01, 0x61, 0xfb, 0x47, 0x12, 0x77, 0x9e,
+	0xfb, 0xc9, 0xa7, 0xa3, 0xb7, 0xca, 0x86, 0x04, 0xcd, 0x44, 0x56, 0xcc,
+	0x01, 0x09, 0xf6, 0xe1, 0x99, 0x6f, 0x3f, 0x6a, 0x18, 0xd2, 0xb3, 0xca,
+	0xab, 0xcc, 0x95, 0x56, 0x9a, 0x3f, 0x79, 0x34, 0x2c, 0xbf, 0x57, 0x0f,
+	0xc9, 0xf7, 0xea, 0xa6, 0x5c, 0xac, 0x07, 0xb4, 0xf1, 0x92, 0x29, 0xb3,
+	0xa5, 0x69, 0xfd, 0x48, 0x31, 0x2f, 0xa9, 0x7a, 0x56, 0x2f, 0x2c, 0x98,
+	0x3d, 0xc9, 0xf3, 0x39, 0x7d, 0x76, 0xa1, 0xb7, 0x27, 0x75, 0x7e, 0x5a,
+	0x2f, 0x14, 0xc3, 0x3d, 0xc9, 0xba, 0xd9, 0x93, 0x5a, 0x0c, 0xe1, 0xba,
+	0xb7, 0x27, 0xb9, 0x18, 0x9d, 0x17, 0xd9, 0x8a, 0x3e, 0xe1, 0x9e, 0x54,
+	0x29, 0x9a, 0x15, 0xe9, 0x8f, 0xbf, 0x2a, 0x7d, 0x3d, 0xa9, 0xfa, 0x3f,
+	0xd1, 0x1b, 0xa6, 0x26, 0x85, 0x5f, 0x15, 0x33, 0x9c, 0xb8, 0xd5, 0x7c,
+	0xc8, 0xd2, 0xc4, 0xb4, 0x6e, 0x37, 0xb7, 0x58, 0x41, 0xc9, 0x9d, 0xee,
+	0x14, 0x5b, 0xcd, 0xc9, 0x94, 0xdc, 0xe2, 0x90, 0xb9, 0x2c, 0x6d, 0x62,
+	0x87, 0xfc, 0xeb, 0x66, 0x33, 0x19, 0xff, 0x32, 0xe5, 0x8a, 0x71, 0xa4,
+	0x67, 0xbc, 0x2e, 0x92, 0x2c, 0x05, 0x25, 0x19, 0x7f, 0xab, 0xe9, 0x3e,
+	0x13, 0xc4, 0x98, 0x81, 0x9e, 0xb1, 0x52, 0xb3, 0x99, 0x8e, 0x83, 0x7e,
+	0xdc, 0x7f, 0xb6, 0x4d, 0xca, 0x21, 0xbb, 0x3c, 0x1b, 0xff, 0x6f, 0xba,
+	0xab, 0x13, 0xce, 0x91, 0xd7, 0xb6, 0xe8, 0x56, 0x5e, 0x72, 0x21, 0x29,
+	0x17, 0xe2, 0x9f, 0x92, 0x13, 0xf1, 0x30, 0xe6, 0x17, 0x94, 0x63, 0x71,
+	0xc8, 0xd1, 0x3a, 0xac, 0x25, 0xeb, 0xd1, 0x48, 0x56, 0x9e, 0x97, 0xe4,
+	0x62, 0xbf, 0x99, 0x16, 0x8c, 0x6d, 0x35, 0x3f, 0x9a, 0x8c, 0x63, 0xbc,
+	0xe1, 0xff, 0xd5, 0xb4, 0x43, 0xd1, 0x6c, 0x59, 0x06, 0xa5, 0x50, 0xea,
+	0x8f, 0xff, 0x4c, 0x34, 0x09, 0x5a, 0x62, 0x4f, 0x59, 0x26, 0xe4, 0x16,
+	0x1d, 0x4c, 0x19, 0x4d, 0xd9, 0x83, 0xf1, 0x93, 0x16, 0xee, 0xd7, 0x65,
+	0xb3, 0x6e, 0xb5, 0x4b, 0xc1, 0x94, 0x50, 0x97, 0x3c, 0x22, 0x85, 0xd3,
+	0x68, 0x8f, 0xdb, 0xbd, 0x3a, 0x9e, 0xc9, 0x8c, 0xb0, 0x4d, 0x34, 0x23,
+	0x11, 0x33, 0x53, 0xe0, 0xa8, 0xe2, 0x0c, 0x62, 0xfc, 0x98, 0xdd, 0xa9,
+	0x99, 0xb2, 0x62, 0x06, 0xa4, 0xea, 0xc4, 0xec, 0xb0, 0xd6, 0x2e, 0xc7,
+	0x62, 0x5d, 0x90, 0x69, 0x18, 0xb4, 0xe5, 0x9b, 0x7a, 0x22, 0x16, 0xce,
+	0x41, 0x51, 0x3a, 0x64, 0x35, 0x07, 0x7e, 0xe6, 0xe2, 0x59, 0x2d, 0x55,
+	0xff, 0x8a, 0x96, 0x3c, 0xbf, 0x5f, 0xdb, 0x75, 0x1e, 0x7d, 0xea, 0xe7,
+	0x3c, 0xbb, 0x0b, 0x83, 0x37, 0x1d, 0xcf, 0xb2, 0x1d, 0x3c, 0x2b, 0xde,
+	0xd1, 0x06, 0x5d, 0x36, 0x26, 0x43, 0x3d, 0x49, 0xa5, 0x4b, 0xf2, 0xa6,
+	0x4b, 0x6e, 0x42, 0x93, 0x5e, 0xcb, 0x96, 0xe0, 0x27, 0xa1, 0xcf, 0x45,
+	0xe8, 0x72, 0x31, 0x22, 0x47, 0x4a, 0x12, 0xd2, 0x85, 0x63, 0x65, 0xf5,
+	0xaa, 0x43, 0x7b, 0x80, 0x6e, 0xa1, 0xfb, 0x82, 0xc3, 0x67, 0xa1, 0xc3,
+	0x52, 0x1a, 0xf2, 0xc9, 0x60, 0xec, 0x7d, 0xda, 0x9e, 0xea, 0xa4, 0x96,
+	0x81, 0x9d, 0x14, 0x4e, 0x0f, 0x41, 0x77, 0xd1, 0xc8, 0x8a, 0x6c, 0x96,
+	0x82, 0x65, 0x45, 0xbe, 0x2c, 0xdd, 0x72, 0x6c, 0xd1, 0x92, 0x23, 0x8b,
+	0x21, 0xc9, 0x9b, 0x51, 0xb3, 0x26, 0x7d, 0xd9, 0x4d, 0x89, 0x1e, 0x79,
+	0xfe, 0x74, 0x34, 0x53, 0x96, 0x7e, 0xfb, 0x75, 0xdc, 0xcf, 0x9d, 0xa4,
+	0x4e, 0x25, 0x9f, 0x8a, 0x1b, 0x92, 0x85, 0x4d, 0x18, 0xd6, 0x1f, 0x81,
+	0xff, 0xe6, 0x73, 0xc9, 0x78, 0x34, 0x2c, 0xa2, 0x4b, 0xea, 0x0b, 0xfd,
+	0xe6, 0x6e, 0x89, 0x9a, 0x19, 0xca, 0x3f, 0x3e, 0x04, 0x3d, 0xfc, 0x77,
+	0xca, 0x1e, 0xb4, 0xa8, 0xe3, 0xa1, 0xf0, 0x31, 0xe8, 0x32, 0xab, 0x74,
+	0xdc, 0x83, 0xf1, 0x03, 0x9e, 0xed, 0xf4, 0x48, 0xbe, 0x7a, 0xc3, 0x93,
+	0x43, 0x8f, 0xcc, 0x57, 0xbb, 0xa5, 0x00, 0x1d, 0x16, 0xc4, 0x92, 0xc2,
+	0xf9, 0x3f, 0xf7, 0xda, 0x2d, 0x99, 0x3b, 0xff, 0x32, 0xec, 0xe1, 0xb0,
+	0xb6, 0xbf, 0xfe, 0x0b, 0xcd, 0xb3, 0x1f, 0xd8, 0x5f, 0x50, 0xec, 0x89,
+	0xa0, 0x9c, 0xab, 0xbb, 0xf6, 0x57, 0xc1, 0x1a, 0xb3, 0x4d, 0x1b, 0xb6,
+	0xf4, 0xc6, 0x6a, 0x9f, 0x73, 0xf5, 0x3e, 0x3c, 0x1b, 0x94, 0x23, 0x75,
+	0xf6, 0xcf, 0xc3, 0xc6, 0x82, 0xb2, 0xf4, 0x68, 0xb7, 0x64, 0xd1, 0x5e,
+	0x58, 0x14, 0x3b, 0x19, 0xd7, 0xf1, 0x4c, 0x0f, 0xe6, 0xb2, 0x15, 0x9f,
+	0x2e, 0x99, 0xaa, 0x76, 0xd8, 0x86, 0x15, 0x92, 0xa9, 0x3a, 0xf5, 0x8f,
+	0xef, 0x92, 0x6f, 0x03, 0x94, 0x2f, 0xdb, 0xf9, 0x1c, 0xdb, 0x4d, 0xb4,
+	0xb7, 0xb6, 0xd1, 0xb6, 0x37, 0x53, 0xa6, 0x83, 0x82, 0xb6, 0x5c, 0x29,
+	0x66, 0xee, 0xe7, 0x77, 0x9d, 0xf6, 0xd0, 0x6a, 0x0b, 0x01, 0xf4, 0x87,
+	0x1e, 0xab, 0x18, 0xeb, 0xf4, 0x9d, 0x66, 0xdb, 0x08, 0xae, 0x2d, 0x2c,
+	0xaa, 0x2e, 0x8e, 0x1d, 0x00, 0x5f, 0xba, 0x64, 0xab, 0x8a, 0xb7, 0x08,
+	0x6d, 0xc0, 0x9d, 0x47, 0x9f, 0xcc, 0x2e, 0x76, 0xf7, 0xa4, 0x17, 0xd9,
+	0x9e, 0x0c, 0x1b, 0x98, 0xe7, 0x54, 0x5c, 0x1a, 0x73, 0x71, 0xbd, 0x3f,
+	0x00, 0xbe, 0xa6, 0xb1, 0xe0, 0x30, 0x0f, 0x8f, 0xc7, 0x06, 0xee, 0xf7,
+	0xca, 0xd4, 0x79, 0xf6, 0xe5, 0x18, 0x85, 0x2d, 0xba, 0x24, 0xc0, 0x1b,
+	0x3e, 0x56, 0x14, 0xf7, 0x3b, 0x31, 0x4e, 0x37, 0x6c, 0x27, 0x83, 0x31,
+	0x9b, 0x8f, 0x27, 0xe3, 0xbd, 0x92, 0x5d, 0xed, 0x2b, 0xb0, 0x3b, 0xf6,
+	0x1f, 0x5c, 0xd7, 0x17, 0xf2, 0x3d, 0x0f, 0x9a, 0x8b, 0x9d, 0x90, 0x21,
+	0xdb, 0x75, 0xf0, 0xdc, 0x01, 0x1e, 0x82, 0x98, 0x4f, 0x3f, 0xd6, 0x43,
+	0x07, 0xe8, 0x6f, 0xc2, 0x9c, 0x3a, 0x65, 0xfa, 0x74, 0x2f, 0x74, 0x61,
+	0xa2, 0x6f, 0x50, 0x9e, 0x2f, 0x45, 0x61, 0x03, 0xec, 0x0f, 0x1d, 0x2c,
+	0x46, 0xc3, 0x55, 0xb1, 0x65, 0x2e, 0xde, 0x01, 0xfb, 0x6a, 0x36, 0x67,
+	0x60, 0x1f, 0xdf, 0x51, 0xfe, 0x62, 0xc8, 0x1c, 0xd3, 0x24, 0xdf, 0x91,
+	0x38, 0x0c, 0x7e, 0xa2, 0x4f, 0x89, 0xf0, 0x7a, 0x87, 0xc6, 0x35, 0x0b,
+	0x39, 0x72, 0x6c, 0xf8, 0xa4, 0xad, 0x90, 0x21, 0xfd, 0x56, 0x1f, 0xec,
+	0x39, 0xac, 0xfc, 0xc9, 0xd8, 0x86, 0xfe, 0x24, 0x3a, 0x51, 0xc6, 0x58,
+	0x85, 0xf3, 0x01, 0xfa, 0xb0, 0x51, 0x2c, 0x57, 0x79, 0x00, 0x6b, 0x6f,
+	0x56, 0xd9, 0xc7, 0x09, 0xce, 0xb7, 0xf9, 0xf9, 0x38, 0xf9, 0xe2, 0x7c,
+	0x6d, 0x3c, 0x4b, 0x1b, 0x8c, 0x1e, 0xb6, 0xd5, 0xf8, 0x27, 0xbc, 0xf1,
+	0x5d, 0xde, 0x0b, 0xa5, 0x1e, 0x2d, 0xa5, 0x78, 0xf0, 0xe9, 0x88, 0x2c,
+	0x9f, 0xec, 0x37, 0xf7, 0xc0, 0x86, 0xe9, 0xa7, 0x96, 0x2f, 0x50, 0xc7,
+	0xa0, 0x31, 0x42, 0x1d, 0x9b, 0x8a, 0xbf, 0xe4, 0x22, 0xd7, 0x9e, 0xf4,
+	0x19, 0x42, 0x1f, 0x01, 0x9f, 0x8b, 0xb5, 0x38, 0xeb, 0xad, 0xc5, 0x9c,
+	0x43, 0xfb, 0x7b, 0x06, 0xcf, 0xea, 0x32, 0x16, 0xa3, 0x7f, 0x78, 0x5e,
+	0x52, 0xf0, 0x91, 0xd0, 0xa3, 0x54, 0x31, 0x97, 0x4a, 0xa9, 0xd5, 0x6f,
+	0xc1, 0xb6, 0x86, 0xff, 0xae, 0xe9, 0xfa, 0x43, 0xfa, 0x06, 0xfa, 0x9a,
+	0x82, 0xa9, 0x43, 0x72, 0x3a, 0x9c, 0x21, 0x74, 0x13, 0x4f, 0x1a, 0xd1,
+	0x4c, 0x16, 0x7c, 0x4d, 0x59, 0x4d, 0xb1, 0x1e, 0x13, 0x44, 0x0c, 0xf4,
+	0xa9, 0xcb, 0x4e, 0xdf, 0x3f, 0x2d, 0x3b, 0xbe, 0x2e, 0xa8, 0x57, 0xea,
+	0xc1, 0xf7, 0x11, 0x01, 0xb9, 0x0c, 0xdf, 0x35, 0x57, 0xea, 0x96, 0x06,
+	0x78, 0xba, 0xe2, 0xf8, 0xb6, 0x66, 0x78, 0xb6, 0xc6, 0x67, 0xba, 0xf1,
+	0x7c, 0x00, 0x7e, 0x4d, 0xf2, 0x46, 0x02, 0xbf, 0x8b, 0xa4, 0xc9, 0x36,
+	0xdf, 0xce, 0xb9, 0x66, 0xa2, 0x76, 0x59, 0xda, 0x25, 0x13, 0x43, 0xfc,
+	0x58, 0xd4, 0x31, 0x56, 0x1f, 0x7c, 0x79, 0x40, 0x0e, 0x96, 0x42, 0xf2,
+	0xd5, 0x12, 0xe7, 0x95, 0xd6, 0x52, 0xd0, 0x5b, 0x72, 0xb1, 0x09, 0x9d,
+	0x8f, 0xc3, 0xe7, 0x65, 0xb4, 0x31, 0xf8, 0x9f, 0xdd, 0xd5, 0xaf, 0x68,
+	0xe9, 0xf3, 0x59, 0x6d, 0xbc, 0xbe, 0x5f, 0xcb, 0x9c, 0x9f, 0xd4, 0x76,
+	0xb5, 0xf8, 0x22, 0xd1, 0xde, 0xdd, 0x17, 0x9d, 0x38, 0xcd, 0x31, 0xfb,
+	0xe3, 0x1b, 0xfb, 0xa2, 0x5f, 0x6a, 0xad, 0xbe, 0xa8, 0x1f, 0xbe, 0x28,
+	0x03, 0x5f, 0x34, 0x7e, 0xdf, 0xbe, 0xa8, 0x5d, 0xdf, 0xd8, 0x17, 0x75,
+	0xeb, 0x77, 0x7d, 0x11, 0x63, 0xcf, 0xbf, 0xc6, 0xb5, 0x29, 0xdb, 0x76,
+	0xfa, 0x72, 0x0e, 0xc3, 0x0f, 0x6f, 0x82, 0xac, 0xbb, 0xb8, 0x76, 0x22,
+	0x05, 0xd8, 0xfd, 0x34, 0xc6, 0xfa, 0x4d, 0xd8, 0xfb, 0xb6, 0x98, 0x65,
+	0x3e, 0xa1, 0xc6, 0x7d, 0xa7, 0xce, 0xc7, 0x56, 0x75, 0x4e, 0x1e, 0xdf,
+	0x53, 0xe7, 0xb6, 0xab, 0x73, 0xea, 0xba, 0x53, 0x66, 0xd4, 0xb8, 0x4d,
+	0x09, 0x3c, 0x26, 0xf0, 0x2a, 0xf2, 0x59, 0x23, 0x11, 0x05, 0x3d, 0x1d,
+	0xe3, 0x53, 0x5f, 0x31, 0xf0, 0x20, 0xd0, 0x6f, 0xb7, 0xf2, 0x45, 0xbb,
+	0xa0, 0xf7, 0x65, 0xe7, 0xfe, 0x74, 0x95, 0x69, 0xd1, 0xd5, 0x9e, 0x35,
+	0xba, 0xea, 0x90, 0xe1, 0x98, 0xaf, 0xa3, 0xcd, 0x92, 0x8c, 0x51, 0x67,
+	0xf7, 0xa3, 0xab, 0x7f, 0xaa, 0xff, 0xfd, 0xe8, 0xea, 0xb7, 0xee, 0xa1,
+	0xab, 0x7f, 0xb5, 0x4e, 0x57, 0x96, 0xf9, 0x82, 0x46, 0xda, 0x8c, 0x1f,
+	0xf4, 0x47, 0xcd, 0x8f, 0x4e, 0x31, 0x7f, 0xa8, 0x73, 0x4d, 0xfb, 0x79,
+	0x07, 0xd7, 0xf3, 0xa5, 0xa6, 0x61, 0x59, 0x90, 0x1d, 0xd7, 0x34, 0xe5,
+	0x16, 0x35, 0x3f, 0x4f, 0xfe, 0x11, 0x3b, 0xa6, 0x10, 0x6b, 0x5c, 0x1e,
+	0xda, 0xa5, 0xbc, 0xc5, 0xed, 0x3f, 0x55, 0x6a, 0xfe, 0x42, 0x4f, 0xbc,
+	0xdd, 0x4c, 0x8e, 0x58, 0x5e, 0x1c, 0x08, 0xca, 0xd7, 0xaa, 0xd1, 0xac,
+	0xad, 0x75, 0x4b, 0xfe, 0x41, 0xc4, 0x9e, 0x12, 0xfd, 0xd7, 0xd6, 0x7b,
+	0xc4, 0xe8, 0x3e, 0x2f, 0x46, 0x57, 0xc1, 0x2b, 0xf3, 0xab, 0xef, 0xbe,
+	0xd5, 0x08, 0xf1, 0x3b, 0x66, 0xee, 0x93, 0x2f, 0x73, 0x8e, 0x88, 0xf7,
+	0x8c, 0xfb, 0x16, 0x73, 0x9e, 0x7c, 0x20, 0xd1, 0x25, 0xf9, 0x2d, 0x5c,
+	0x8f, 0xf4, 0x73, 0xf4, 0x5d, 0xed, 0x1e, 0xdf, 0x7e, 0x8e, 0xa4, 0x78,
+	0x33, 0x30, 0x65, 0xf4, 0x41, 0x3e, 0x54, 0xe2, 0x3c, 0xde, 0xf2, 0xec,
+	0x89, 0xb9, 0x82, 0xb4, 0xb9, 0xbe, 0x61, 0x2f, 0x72, 0x01, 0xda, 0x81,
+	0xaf, 0x73, 0xea, 0x9b, 0x39, 0x82, 0x44, 0x74, 0x8b, 0x39, 0x82, 0x98,
+	0x46, 0x62, 0x9f, 0x66, 0x43, 0xf7, 0x36, 0x74, 0x6f, 0x43, 0xf7, 0x36,
+	0x74, 0x9f, 0xac, 0x1f, 0xc6, 0x3d, 0x95, 0x87, 0x80, 0x17, 0x97, 0x7e,
+	0xda, 0xa5, 0x0f, 0x3e, 0xb7, 0x4a, 0x4e, 0xe9, 0x84, 0xf3, 0x45, 0xae,
+	0xa1, 0xfc, 0xf5, 0xb8, 0xe6, 0xfa, 0x6b, 0xd2, 0xcb, 0xe0, 0xf9, 0xdb,
+	0x98, 0xa7, 0xad, 0xeb, 0xd6, 0x5d, 0x99, 0xcc, 0xb5, 0xc8, 0x64, 0xd6,
+	0xa1, 0x8c, 0xd8, 0x9f, 0x3e, 0x77, 0x5a, 0xaf, 0xac, 0xca, 0x65, 0x2f,
+	0x78, 0xe8, 0xe0, 0xdc, 0xbd, 0x79, 0x90, 0x7e, 0xaf, 0x47, 0xff, 0x6f,
+	0xd1, 0x87, 0xfe, 0x75, 0xa3, 0x71, 0x39, 0x26, 0x73, 0xc6, 0x77, 0x9b,
+	0x0f, 0x72, 0x66, 0xac, 0x81, 0xef, 0x21, 0x96, 0x5f, 0x44, 0x2c, 0x59,
+	0x31, 0x22, 0xf2, 0x93, 0x47, 0xaf, 0x21, 0x97, 0x96, 0xfc, 0xc3, 0x89,
+	0x66, 0x24, 0x90, 0x78, 0xab, 0x39, 0x37, 0x82, 0x18, 0x97, 0x88, 0x86,
+	0x93, 0xc6, 0xb0, 0x5c, 0xaa, 0x0f, 0xca, 0x8f, 0xea, 0x96, 0xfc, 0xb0,
+	0x1e, 0x91, 0x1f, 0x20, 0xe6, 0x7f, 0xbf, 0xde, 0x9a, 0x73, 0x47, 0x68,
+	0x4f, 0x3d, 0xe9, 0xfa, 0x46, 0xb9, 0x7f, 0x13, 0x34, 0xde, 0x82, 0x9d,
+	0x04, 0xb2, 0xc8, 0xf5, 0x19, 0xbf, 0x26, 0x0e, 0x15, 0x9f, 0x6b, 0x82,
+	0xb7, 0x6c, 0x5b, 0xc2, 0xca, 0xeb, 0x7a, 0xf7, 0xa8, 0xf9, 0x29, 0xb4,
+	0x39, 0xa3, 0x81, 0x6a, 0xb1, 0x53, 0xe5, 0x8b, 0xd0, 0x91, 0xd8, 0xf5,
+	0x60, 0xb0, 0x56, 0xbc, 0x85, 0x7e, 0xcd, 0xe6, 0xa1, 0xf8, 0x6f, 0xed,
+	0x30, 0xff, 0x81, 0x85, 0x35, 0xdd, 0xf9, 0x25, 0x23, 0xb1, 0x49, 0x66,
+	0x43, 0xdf, 0x6f, 0x98, 0x03, 0x7d, 0x59, 0x3d, 0x11, 0x94, 0x74, 0x91,
+	0x6b, 0x2a, 0x24, 0xb3, 0x55, 0x28, 0xff, 0x3c, 0xd7, 0x85, 0x3c, 0x3b,
+	0x17, 0xef, 0x86, 0xed, 0xff, 0x9a, 0xe1, 0xae, 0x03, 0x18, 0x50, 0x75,
+	0x50, 0xf2, 0xe0, 0x37, 0x5f, 0x7f, 0xcb, 0xc3, 0x0e, 0xf0, 0x2a, 0x5b,
+	0x21, 0xf8, 0xc4, 0x70, 0xda, 0x76, 0xfe, 0x30, 0x88, 0xb6, 0xe0, 0x56,
+	0xeb, 0xce, 0x26, 0x7c, 0x3f, 0x10, 0xb2, 0x88, 0x4d, 0x24, 0xf3, 0x05,
+	0x7c, 0xff, 0x4a, 0x42, 0x36, 0xf7, 0xe2, 0x7b, 0x4b, 0x02, 0x26, 0x99,
+	0x60, 0xcc, 0xd5, 0x5a, 0x62, 0xae, 0x68, 0x69, 0xc8, 0x6e, 0x0e, 0x73,
+	0x4f, 0x43, 0x9e, 0x5f, 0xac, 0x07, 0xb5, 0xd4, 0xe9, 0x47, 0xc0, 0x87,
+	0x9f, 0x3b, 0x23, 0x3f, 0x33, 0x97, 0xb7, 0x04, 0xe4, 0x16, 0x7c, 0x5c,
+	0x12, 0x7e, 0xcc, 0x46, 0x6e, 0xb1, 0x03, 0xcb, 0x35, 0xfa, 0x5f, 0xbf,
+	0x20, 0x5f, 0xf3, 0x78, 0x6b, 0x93, 0x05, 0x65, 0xa3, 0x6c, 0xcf, 0x67,
+	0xfe, 0xcd, 0xc0, 0xdd, 0xf6, 0x17, 0x57, 0xdb, 0xcb, 0x99, 0x7f, 0xb8,
+	0xda, 0xde, 0xdb, 0xe6, 0xf2, 0x3f, 0xaa, 0x4d, 0xd4, 0xf7, 0x78, 0x6d,
+	0xb7, 0xa1, 0xb3, 0x66, 0x93, 0xb9, 0x45, 0x01, 0xd8, 0x24, 0x1d, 0xa7,
+	0x2f, 0xbe, 0x1f, 0x5f, 0xbb, 0xc6, 0xcf, 0x9a, 0x49, 0x83, 0xb6, 0x10,
+	0x14, 0x97, 0x26, 0xef, 0x77, 0x20, 0x7f, 0xbf, 0x8d, 0xdf, 0x8c, 0xa3,
+	0x7e, 0x6e, 0xce, 0x3e, 0x7c, 0xfe, 0xcd, 0x7b, 0xd8, 0x4b, 0x08, 0xf6,
+	0xf2, 0xff, 0xab, 0x5d, 0x5c, 0xba, 0x1f, 0xbb, 0xc0, 0x9f, 0xb2, 0x0b,
+	0xd5, 0xff, 0xd2, 0xea, 0x5a, 0x09, 0x43, 0x3e, 0x8c, 0x07, 0x83, 0xd0,
+	0xf1, 0x66, 0x99, 0xb5, 0xc8, 0x8f, 0x15, 0xc9, 0xc1, 0x5f, 0x9e, 0x58,
+	0x17, 0xbb, 0xbb, 0x10, 0x0f, 0x8e, 0x9f, 0x8e, 0x8e, 0x32, 0x1e, 0xc4,
+	0xe0, 0x1b, 0x93, 0xef, 0x88, 0x07, 0x37, 0x8c, 0xd6, 0x78, 0x60, 0x20,
+	0x1e, 0xec, 0x7a, 0x97, 0x78, 0x70, 0xe2, 0x1d, 0xf1, 0x40, 0x83, 0x6c,
+	0x38, 0xbf, 0xbf, 0x35, 0xfc, 0x78, 0x50, 0x58, 0x13, 0x0f, 0x7c, 0x5d,
+	0x59, 0x0a, 0x0b, 0xdc, 0xd5, 0x5b, 0x97, 0xa7, 0x2b, 0x09, 0x06, 0x12,
+	0x8d, 0xcc, 0x9c, 0xf5, 0xb0, 0xb4, 0xc1, 0xe7, 0x5e, 0xaa, 0x8f, 0x40,
+	0x67, 0x97, 0x30, 0xf7, 0x68, 0x9c, 0x89, 0x65, 0x5b, 0x82, 0xeb, 0xe1,
+	0xcd, 0x08, 0x30, 0xe2, 0x6e, 0xe0, 0xbe, 0xdd, 0x67, 0xd5, 0xfa, 0x78,
+	0x33, 0xea, 0x61, 0xf7, 0x6d, 0xc0, 0xee, 0x78, 0x3e, 0x00, 0x4c, 0xc8,
+	0xf6, 0x2b, 0x66, 0x12, 0x7a, 0xaa, 0x3a, 0xf6, 0xee, 0x02, 0x3e, 0x73,
+	0xaa, 0xef, 0xad, 0x08, 0xfb, 0x76, 0x24, 0x12, 0xd1, 0x3f, 0xc3, 0x77,
+	0x7b, 0x22, 0xbc, 0xed, 0xaa, 0x45, 0xba, 0x87, 0xa2, 0x67, 0x15, 0x8d,
+	0x80, 0x14, 0xd4, 0xb3, 0x91, 0x6d, 0x7c, 0xf6, 0x18, 0x62, 0xf6, 0x51,
+	0xc7, 0x94, 0x23, 0x4e, 0x76, 0x77, 0x0e, 0x1f, 0x62, 0xd5, 0x4b, 0x25,
+	0xde, 0x1f, 0xc5, 0xfd, 0x80, 0x30, 0x97, 0xfc, 0x2a, 0xfa, 0x1c, 0x44,
+	0x9f, 0x19, 0xc7, 0xd7, 0x05, 0xef, 0x37, 0x32, 0x29, 0xdc, 0x9f, 0x29,
+	0x36, 0x32, 0xe9, 0x22, 0xf3, 0xd6, 0xa1, 0xf0, 0x11, 0xc8, 0x33, 0x8b,
+	0x5c, 0xcd, 0x96, 0xe8, 0x60, 0x5e, 0x9e, 0xee, 0x1c, 0x07, 0x4e, 0x3a,
+	0x87, 0x1c, 0xc2, 0x9e, 0x8c, 0xc6, 0xcb, 0xf2, 0xe1, 0xce, 0xe4, 0x69,
+	0xe4, 0x0b, 0xf1, 0xed, 0x90, 0x61, 0x23, 0xa3, 0xc7, 0x04, 0xb6, 0x1e,
+	0x87, 0x5f, 0x1e, 0xd1, 0x53, 0xc5, 0x7e, 0x73, 0x56, 0x1e, 0x95, 0x86,
+	0x19, 0x0d, 0x8f, 0xcb, 0x26, 0x49, 0x05, 0xd0, 0x6f, 0xf0, 0x43, 0x92,
+	0x0d, 0x53, 0xd6, 0x0f, 0xc2, 0xdf, 0x6b, 0xd2, 0x61, 0xb5, 0xc6, 0x9e,
+	0x5b, 0x10, 0x6f, 0x2e, 0x40, 0x9f, 0xdd, 0x61, 0x75, 0x7a, 0x3a, 0xd9,
+	0x24, 0xcb, 0xef, 0xe8, 0x77, 0xbb, 0xa5, 0x5f, 0x6b, 0xfb, 0xdb, 0x68,
+	0xdf, 0x84, 0x9c, 0xb3, 0x91, 0x09, 0xc4, 0x20, 0x7f, 0xcc, 0xa1, 0x0d,
+	0x76, 0x72, 0x15, 0xf3, 0x61, 0x1c, 0x2c, 0x94, 0x99, 0xf7, 0x18, 0x52,
+	0x36, 0x71, 0xcf, 0x69, 0x36, 0x2b, 0x16, 0xf8, 0xbd, 0x40, 0x9e, 0x83,
+	0x32, 0xee, 0x0c, 0x88, 0x5d, 0xa3, 0x1c, 0xa2, 0xf0, 0x4a, 0x0f, 0x77,
+	0xa5, 0x16, 0xa3, 0x76, 0x1e, 0x14, 0x8d, 0x0b, 0x7d, 0x5d, 0x49, 0xe4,
+	0x39, 0xfa, 0x85, 0x48, 0x57, 0x0a, 0x36, 0x6b, 0x5c, 0x78, 0xa8, 0x2b,
+	0x7d, 0x9a, 0x7c, 0x19, 0xc8, 0x73, 0x3e, 0x0a, 0x9c, 0xdf, 0x94, 0xdf,
+	0x45, 0x2e, 0x5b, 0x18, 0x44, 0x0e, 0x80, 0xd5, 0xaf, 0x83, 0xef, 0xbc,
+	0x29, 0xc1, 0xae, 0xc4, 0xab, 0xe0, 0x6f, 0x18, 0xb2, 0xd9, 0x84, 0x3e,
+	0x06, 0xda, 0x07, 0x58, 0x13, 0x68, 0x69, 0xb7, 0xba, 0x10, 0x4f, 0x11,
+	0xbb, 0x24, 0x98, 0x1c, 0xe9, 0x06, 0xfd, 0x2b, 0x01, 0xe6, 0x82, 0xc1,
+	0xd8, 0x6a, 0xfb, 0x37, 0xdd, 0xf6, 0x41, 0xf0, 0xc2, 0xe7, 0x88, 0x09,
+	0x24, 0x38, 0x35, 0x62, 0x82, 0x07, 0xf6, 0x0d, 0xa9, 0xbe, 0xe9, 0x45,
+	0xda, 0x40, 0x23, 0x53, 0xb1, 0x1e, 0x91, 0xd4, 0xc2, 0x56, 0x19, 0x5f,
+	0xe8, 0x95, 0x5d, 0x0b, 0xc4, 0x30, 0xac, 0x69, 0x60, 0x2a, 0xc0, 0x18,
+	0xfa, 0x05, 0xe6, 0x76, 0xd1, 0xf0, 0x41, 0xe9, 0x0f, 0x7f, 0x15, 0xeb,
+	0x60, 0xca, 0x8a, 0x45, 0x66, 0xb1, 0xc6, 0x02, 0x8a, 0x4e, 0xd8, 0x1f,
+	0x93, 0x36, 0xba, 0x66, 0xdc, 0xf4, 0xe2, 0xbd, 0xe8, 0x62, 0xe1, 0x5c,
+	0x08, 0xaf, 0xa3, 0xfb, 0x57, 0x1e, 0x5d, 0x13, 0x74, 0xfb, 0x40, 0x93,
+	0x73, 0x7c, 0xa8, 0x73, 0xec, 0xb4, 0xd8, 0x1d, 0xe0, 0x2f, 0x1d, 0x7b,
+	0x58, 0x66, 0x41, 0xe7, 0xe8, 0x02, 0xfd, 0xa4, 0x6c, 0xc5, 0x67, 0xb8,
+	0x4d, 0x62, 0x83, 0xe7, 0x81, 0x73, 0xc6, 0x14, 0x0d, 0x17, 0x73, 0xe8,
+	0x17, 0x12, 0xc0, 0xa9, 0x1f, 0x07, 0x3f, 0xcc, 0xb1, 0x38, 0xe7, 0x00,
+	0xe6, 0x9b, 0xc0, 0x3a, 0x64, 0x7d, 0x85, 0xeb, 0x1b, 0xbf, 0xcf, 0x87,
+	0x3b, 0x53, 0xa7, 0xdb, 0xb1, 0xee, 0xe4, 0x11, 0x43, 0xc5, 0x7e, 0xea,
+	0xc5, 0xea, 0x4c, 0x96, 0x14, 0xdf, 0x9d, 0xa9, 0x12, 0x65, 0x14, 0xef,
+	0x4c, 0x97, 0x28, 0x23, 0x01, 0x3f, 0x71, 0xd8, 0x64, 0x40, 0x22, 0x5b,
+	0xa8, 0xc7, 0x43, 0xe8, 0xf7, 0x57, 0x01, 0xe2, 0xb8, 0xa4, 0xc5, 0xdf,
+	0xf0, 0xb5, 0x17, 0x0e, 0xa3, 0x2f, 0x7f, 0x6f, 0x07, 0xdd, 0xfe, 0xc1,
+	0x82, 0xb4, 0x0f, 0xce, 0xc0, 0x4f, 0xe8, 0x23, 0xc0, 0x91, 0xca, 0xce,
+	0x9b, 0xc0, 0xd8, 0x3b, 0x30, 0x1f, 0xac, 0x8d, 0x98, 0x25, 0xd3, 0xf3,
+	0x94, 0xab, 0x7c, 0x08, 0x73, 0xc0, 0xfc, 0x63, 0xf0, 0x2d, 0x9c, 0x03,
+	0xc7, 0x16, 0xe4, 0x36, 0x4b, 0x92, 0x9b, 0x0f, 0x2a, 0x2c, 0x6b, 0x9b,
+	0x1c, 0x5f, 0xd3, 0xf4, 0x44, 0x17, 0x74, 0xcc, 0xb9, 0xcd, 0x81, 0xb7,
+	0x67, 0x10, 0xff, 0xa2, 0x0a, 0x43, 0x19, 0x17, 0xb8, 0x56, 0x46, 0xb1,
+	0x4e, 0xc8, 0xbf, 0x67, 0x7b, 0x5a, 0x03, 0x3e, 0x45, 0xf9, 0x7f, 0xe4,
+	0xea, 0x09, 0xf8, 0x91, 0x51, 0xf9, 0x7d, 0xf8, 0x92, 0x1f, 0xd7, 0xe3,
+	0xc8, 0x1b, 0x86, 0x91, 0x37, 0x0c, 0x22, 0x6f, 0xb0, 0x90, 0x37, 0x44,
+	0x90, 0x37, 0xf4, 0x21, 0x6f, 0x08, 0x23, 0x3e, 0x88, 0x1c, 0xad, 0xe7,
+	0x61, 0x63, 0x0d, 0xf8, 0x41, 0x33, 0x68, 0xd7, 0x43, 0xc1, 0x64, 0x3d,
+	0x1c, 0x4c, 0xd5, 0x03, 0x98, 0xd3, 0x01, 0x8e, 0x89, 0xf9, 0xe5, 0x3b,
+	0xc7, 0x4a, 0xc3, 0x88, 0x39, 0x36, 0xfc, 0x52, 0x1a, 0xf1, 0x36, 0x2e,
+	0x47, 0xf0, 0xcc, 0xf2, 0x7c, 0x04, 0xcf, 0x34, 0x25, 0x1d, 0x6f, 0x93,
+	0x59, 0x33, 0x0e, 0x1a, 0x5b, 0x94, 0x9d, 0x22, 0xdf, 0x6a, 0x83, 0x9d,
+	0x4a, 0xae, 0xc8, 0x7c, 0xab, 0x0f, 0xf4, 0x3a, 0x11, 0x97, 0xe9, 0x1f,
+	0xe8, 0x0b, 0xec, 0xdd, 0x5f, 0xb2, 0xb8, 0xe6, 0xba, 0xb4, 0xe4, 0xe9,
+	0xbc, 0x10, 0x6b, 0x22, 0x0e, 0xc2, 0x2e, 0xd8, 0x36, 0x81, 0xe7, 0xf8,
+	0xfb, 0x6d, 0xcf, 0xef, 0x7f, 0x24, 0x28, 0x30, 0xde, 0x4b, 0x8c, 0xf9,
+	0x16, 0xe8, 0x39, 0xad, 0xeb, 0xb5, 0xa6, 0x8b, 0xe5, 0xdf, 0x67, 0xfd,
+	0x8d, 0x35, 0xc7, 0xd7, 0xc0, 0x73, 0xbf, 0xb9, 0x8c, 0x1c, 0xd9, 0xde,
+	0xbf, 0x82, 0xdf, 0xad, 0xfd, 0xeb, 0xe8, 0xaf, 0xda, 0x82, 0x66, 0x22,
+	0xce, 0x7c, 0x18, 0x3e, 0x73, 0x10, 0xfe, 0xf1, 0x56, 0x46, 0x5f, 0xba,
+	0x89, 0x79, 0x42, 0x9e, 0xc5, 0x5b, 0x99, 0xc0, 0xc0, 0xb5, 0xe6, 0x8b,
+	0xc0, 0x37, 0x63, 0x4b, 0x23, 0x92, 0x5a, 0xea, 0x0f, 0x5f, 0x96, 0xce,
+	0xdb, 0xb6, 0x5c, 0x6b, 0xce, 0x3a, 0xd1, 0xe3, 0xb6, 0x10, 0x6f, 0x99,
+	0x52, 0x01, 0xa9, 0x6d, 0x3b, 0x3b, 0x88, 0x19, 0x2f, 0x8a, 0x1e, 0x91,
+	0xe4, 0x29, 0x5b, 0x46, 0x76, 0xfa, 0xb9, 0xfb, 0x9d, 0x0e, 0xe9, 0x42,
+	0xdb, 0x52, 0x04, 0x7d, 0x88, 0x53, 0x39, 0xef, 0x2c, 0xe6, 0xac, 0xb9,
+	0xcf, 0x78, 0xf5, 0xc9, 0x42, 0x09, 0x73, 0xaf, 0xdf, 0xca, 0x5c, 0x3e,
+	0x05, 0xec, 0x0e, 0x1d, 0x25, 0x4f, 0xb1, 0xae, 0xb0, 0x09, 0x72, 0x1a,
+	0x83, 0xad, 0xd0, 0x06, 0xfa, 0xf1, 0x6c, 0x53, 0xbe, 0x11, 0xa7, 0x5d,
+	0xbc, 0x04, 0x59, 0x82, 0x56, 0xc0, 0x9f, 0x0f, 0x70, 0xde, 0x3c, 0xe5,
+	0x17, 0x46, 0x6e, 0xce, 0xb1, 0x25, 0xd8, 0x99, 0x58, 0x9f, 0x77, 0xdf,
+	0xca, 0x2c, 0x9f, 0x02, 0xfd, 0x01, 0xd6, 0xde, 0xe0, 0xb3, 0x8b, 0xac,
+	0x1d, 0x32, 0x27, 0xdd, 0x05, 0x3d, 0xed, 0x55, 0xb5, 0xb8, 0x64, 0x35,
+	0x2e, 0xd6, 0x49, 0xfa, 0x2c, 0x89, 0x18, 0xd6, 0x7e, 0xe4, 0xaf, 0x62,
+	0xea, 0x89, 0x49, 0xdc, 0xa3, 0x3c, 0x35, 0xe4, 0x1c, 0xb8, 0x7f, 0x61,
+	0x45, 0xe9, 0xc4, 0x80, 0xee, 0x72, 0x3b, 0x99, 0x84, 0xc9, 0xbc, 0x91,
+	0x80, 0x2f, 0x1c, 0xe1, 0x1c, 0xd4, 0xd8, 0xc8, 0xc7, 0xb9, 0xfe, 0x30,
+	0x67, 0xd8, 0x55, 0x4b, 0x5e, 0xae, 0xfe, 0x66, 0x4b, 0x47, 0x60, 0xd3,
+	0x92, 0x6f, 0x43, 0x3e, 0x90, 0x1c, 0xc1, 0x6f, 0x38, 0x81, 0xa3, 0xd0,
+	0xe7, 0xd9, 0x11, 0xd6, 0x3f, 0x5f, 0x02, 0xb6, 0x27, 0xdf, 0xb1, 0xc8,
+	0x11, 0xb5, 0x86, 0x71, 0xed, 0x30, 0x97, 0xdb, 0x24, 0x97, 0xd5, 0xfc,
+	0x1e, 0x22, 0xf6, 0x80, 0x9e, 0xee, 0x67, 0x7e, 0xe3, 0xf7, 0x39, 0x3f,
+	0x97, 0x3e, 0x63, 0x57, 0xd2, 0x8a, 0x48, 0xaa, 0x78, 0xa9, 0x19, 0xb0,
+	0x2c, 0x60, 0x67, 0x57, 0x8f, 0x29, 0x27, 0x08, 0x3e, 0x58, 0x6b, 0xdb,
+	0xa9, 0x74, 0x09, 0x3e, 0x68, 0x3b, 0xf9, 0x60, 0x62, 0xb3, 0x9c, 0x9b,
+	0xef, 0x91, 0xca, 0xfc, 0xcf, 0xa5, 0x3a, 0xdf, 0x25, 0xe7, 0xe7, 0x9b,
+	0x72, 0x35, 0xae, 0x7c, 0x93, 0xd5, 0xae, 0xd6, 0xb5, 0x3c, 0xec, 0xd6,
+	0x61, 0x62, 0xa3, 0xd7, 0xe5, 0x79, 0x39, 0x57, 0x76, 0x79, 0xcf, 0xb4,
+	0xf0, 0x7e, 0x15, 0xb6, 0xf6, 0xaa, 0x45, 0xfe, 0x47, 0xa4, 0x52, 0x24,
+	0xef, 0xfb, 0x14, 0xef, 0xbb, 0x56, 0x79, 0x97, 0xac, 0x61, 0x91, 0xff,
+	0x8d, 0x78, 0xef, 0x90, 0xec, 0x56, 0xf2, 0x1f, 0xc1, 0xb3, 0xef, 0xb4,
+	0xbf, 0x8a, 0x73, 0xad, 0xb9, 0x5c, 0x6c, 0x53, 0x3c, 0x1b, 0x89, 0x11,
+	0xc8, 0xe7, 0x5a, 0xb3, 0xe1, 0x70, 0x1d, 0xe1, 0xb7, 0xf3, 0x2f, 0xe0,
+	0xab, 0x7a, 0x55, 0xce, 0x92, 0x9b, 0xec, 0xee, 0x4c, 0x2e, 0x8e, 0x42,
+	0xb7, 0x9d, 0x6a, 0x1d, 0xc2, 0x6d, 0x40, 0x67, 0xff, 0x1e, 0xfd, 0xbf,
+	0xcd, 0xf5, 0xa6, 0xe4, 0x92, 0x86, 0x5c, 0x0a, 0xc5, 0xf1, 0x76, 0xe0,
+	0x27, 0x8c, 0xd3, 0xc8, 0x64, 0x1d, 0x3e, 0xd3, 0x07, 0xdf, 0xc6, 0xef,
+	0xf7, 0x6d, 0x0f, 0x79, 0xf8, 0x5c, 0xe8, 0x1c, 0x79, 0x05, 0xd7, 0xf3,
+	0x48, 0x03, 0x31, 0x36, 0x36, 0x58, 0x51, 0xfb, 0x10, 0x71, 0x85, 0x85,
+	0x67, 0x9d, 0x6f, 0xe3, 0xe3, 0x8e, 0x37, 0x56, 0xe7, 0x98, 0x6b, 0xe7,
+	0x54, 0x70, 0x1a, 0xc8, 0xdf, 0x2d, 0xd0, 0xe5, 0xb8, 0x79, 0x31, 0x12,
+	0x06, 0xc6, 0x65, 0x5b, 0x37, 0x7c, 0x4c, 0x04, 0x3e, 0x6b, 0x18, 0xbe,
+	0x9f, 0x6b, 0x99, 0x7e, 0xde, 0xe7, 0x7d, 0x18, 0x34, 0xe9, 0x7f, 0x87,
+	0x31, 0x67, 0xe6, 0xd8, 0xf4, 0x9f, 0x88, 0x27, 0xb5, 0x70, 0x57, 0xf2,
+	0xb4, 0x5b, 0x1b, 0x74, 0x7f, 0xf3, 0xbe, 0x04, 0x1f, 0x49, 0x44, 0xcb,
+	0x79, 0xe4, 0x7e, 0x29, 0xac, 0xd1, 0xa4, 0x85, 0x3c, 0xbb, 0x16, 0x7d,
+	0x85, 0x98, 0x5b, 0xa7, 0x0c, 0x96, 0x28, 0x27, 0xd6, 0xa9, 0x4c, 0xc9,
+	0x57, 0xbe, 0x0b, 0x79, 0x04, 0x65, 0x8b, 0x95, 0x85, 0x4f, 0x01, 0xff,
+	0x98, 0xfb, 0x5c, 0x89, 0xb5, 0xc8, 0x7e, 0xc4, 0x31, 0x03, 0x42, 0x40,
+	0x4e, 0xb5, 0x64, 0xc8, 0x67, 0x03, 0x43, 0xc8, 0x01, 0x9f, 0x45, 0xdf,
+	0x80, 0xe4, 0x97, 0x18, 0x0f, 0x02, 0x32, 0xb7, 0x24, 0x72, 0xfd, 0x14,
+	0xfd, 0x8a, 0xfa, 0x83, 0xcc, 0x1b, 0x99, 0x69, 0x62, 0xed, 0x79, 0xfa,
+	0x18, 0xfa, 0x89, 0x07, 0xa1, 0x8b, 0xd8, 0x4b, 0xdf, 0x40, 0x6c, 0x9a,
+	0x2d, 0xf6, 0xc3, 0x67, 0x4a, 0x43, 0x87, 0x4c, 0x11, 0xd3, 0x98, 0xa3,
+	0x6f, 0x50, 0x77, 0xf4, 0x6b, 0x8e, 0x41, 0x29, 0x9c, 0x62, 0xbd, 0x31,
+	0x08, 0x5e, 0x98, 0xb7, 0x1a, 0x2a, 0x0f, 0x7a, 0x50, 0xf9, 0x56, 0x7e,
+	0x07, 0x5a, 0xc6, 0x8d, 0x1d, 0xdf, 0xa6, 0xd3, 0x8f, 0x3d, 0x22, 0xf6,
+	0xc4, 0xa1, 0xce, 0x5d, 0xa5, 0x76, 0x29, 0xf7, 0xd2, 0x2e, 0xa9, 0xff,
+	0xac, 0x4e, 0x5f, 0x8b, 0x3c, 0x0c, 0xf4, 0x58, 0x23, 0x08, 0xa0, 0x5f,
+	0xc8, 0xeb, 0x47, 0xb9, 0xfe, 0xb6, 0x4c, 0xed, 0xfc, 0x3b, 0xf0, 0xe5,
+	0xfa, 0xb5, 0xdc, 0x4e, 0xf8, 0xdb, 0x09, 0x5d, 0x1e, 0xfb, 0x54, 0x1a,
+	0xcf, 0x32, 0x16, 0xde, 0xf2, 0xf0, 0x38, 0xdb, 0x58, 0xa3, 0x45, 0x9e,
+	0x7e, 0xce, 0xc4, 0x77, 0xaf, 0xe4, 0xcf, 0x05, 0x21, 0x07, 0xe4, 0xc4,
+	0x15, 0x97, 0x16, 0xf3, 0xde, 0xe3, 0xd0, 0x91, 0x7e, 0x32, 0x28, 0x6d,
+	0x27, 0x7b, 0x25, 0xf0, 0xad, 0x2e, 0x69, 0xff, 0xd6, 0x80, 0x18, 0xdf,
+	0x62, 0x2d, 0x29, 0x1a, 0x39, 0xaa, 0xea, 0x58, 0x69, 0x39, 0x86, 0xf8,
+	0xa5, 0x23, 0x16, 0x2b, 0x3b, 0x35, 0xb7, 0x8a, 0x81, 0xc4, 0x55, 0x7f,
+	0xc1, 0x96, 0xaf, 0xef, 0xfc, 0x85, 0xaa, 0xa3, 0x26, 0x47, 0x70, 0xfd,
+	0x72, 0x06, 0xd8, 0x44, 0x83, 0xad, 0x34, 0x32, 0xd7, 0x1e, 0xf5, 0x73,
+	0xcb, 0x41, 0x55, 0x93, 0xff, 0xfa, 0x4e, 0x37, 0xb7, 0x9c, 0x45, 0x6e,
+	0x99, 0x56, 0xb9, 0x25, 0xfc, 0x6b, 0x80, 0xfd, 0xb6, 0x8a, 0x8e, 0xb1,
+	0x72, 0xc2, 0x5c, 0xfd, 0xa3, 0x62, 0x1f, 0xc0, 0xba, 0x38, 0x23, 0xf3,
+	0x7a, 0x42, 0x53, 0x34, 0x8d, 0x17, 0xe8, 0xa7, 0xe8, 0xbf, 0x68, 0xe3,
+	0xac, 0x69, 0xa1, 0xed, 0x65, 0xfa, 0x28, 0xd7, 0xb6, 0xc7, 0x5a, 0x7c,
+	0xdd, 0x5c, 0xa9, 0x0e, 0x1d, 0x22, 0xa7, 0xb7, 0xda, 0x30, 0x7f, 0xc4,
+	0x74, 0x8b, 0xd7, 0x9c, 0x3f, 0x7c, 0x67, 0x28, 0xa4, 0xae, 0x0b, 0x65,
+	0xb7, 0x86, 0xe1, 0xd2, 0x67, 0xfe, 0x01, 0x1f, 0x53, 0x27, 0x1f, 0x1c,
+	0xb7, 0x4f, 0x8c, 0x33, 0x21, 0x09, 0x9c, 0xa1, 0xfd, 0x45, 0x23, 0x69,
+	0xc8, 0x6f, 0xce, 0x22, 0x06, 0x3c, 0x04, 0x6c, 0xf4, 0x88, 0xe8, 0xe7,
+	0x06, 0xb1, 0x76, 0xa2, 0xe1, 0xb2, 0xc4, 0xc4, 0xa8, 0x04, 0xe5, 0x8d,
+	0x53, 0xd1, 0x08, 0xed, 0xe5, 0x2c, 0xe2, 0xd5, 0x91, 0x7a, 0xe7, 0xed,
+	0x86, 0xe2, 0x82, 0x6d, 0xdf, 0x08, 0x00, 0x3b, 0x0c, 0xda, 0x7a, 0xb7,
+	0xdc, 0x80, 0xbe, 0xb3, 0xaa, 0xed, 0x11, 0xd0, 0x05, 0x0f, 0x67, 0x58,
+	0x1b, 0x24, 0xdd, 0xa3, 0xa0, 0x49, 0xda, 0x8d, 0xcc, 0x32, 0x73, 0xd3,
+	0x53, 0xb4, 0xdd, 0x5e, 0xd8, 0x1d, 0xae, 0xeb, 0xed, 0x92, 0x9d, 0x8c,
+	0x88, 0x7e, 0x6a, 0x8f, 0xf4, 0xef, 0xd4, 0xdd, 0xf9, 0xa8, 0x39, 0xb2,
+	0x8d, 0x35, 0xe7, 0x11, 0xb5, 0x1e, 0xf5, 0x25, 0xd8, 0xcc, 0x3e, 0xea,
+	0x18, 0xb1, 0x1f, 0x71, 0x8c, 0x7e, 0xcc, 0x40, 0x1c, 0x4b, 0xd5, 0x5d,
+	0xbd, 0x97, 0xf7, 0x6d, 0x95, 0x63, 0x67, 0x68, 0x4f, 0xb8, 0xb7, 0x6a,
+	0x53, 0xfe, 0xde, 0x10, 0xef, 0x59, 0x72, 0xfc, 0x45, 0xe6, 0x1e, 0xcc,
+	0x39, 0x98, 0x67, 0x45, 0xc3, 0xbb, 0x30, 0x1f, 0xfd, 0x31, 0xfa, 0x03,
+	0x5d, 0xd9, 0x6e, 0x0e, 0x3e, 0xba, 0x50, 0xa7, 0xde, 0x86, 0xb9, 0x7f,
+	0x66, 0x32, 0x5f, 0xb3, 0xc3, 0xae, 0xbc, 0x0b, 0x68, 0x9b, 0x85, 0xef,
+	0x4f, 0x39, 0x6d, 0xb2, 0x32, 0x69, 0x43, 0xf7, 0x5f, 0x02, 0x5f, 0x07,
+	0x3a, 0x59, 0x23, 0x58, 0x99, 0x4c, 0xe3, 0xfa, 0x80, 0xca, 0xd1, 0x8c,
+	0xc7, 0x6c, 0xd0, 0xd8, 0xca, 0x75, 0xe4, 0xe9, 0x29, 0xae, 0x17, 0xe6,
+	0x1f, 0xd3, 0x67, 0xe1, 0xb3, 0xc7, 0xe3, 0x8c, 0xf1, 0xdc, 0x4b, 0xe8,
+	0x00, 0x1f, 0xdd, 0x0a, 0x57, 0xe8, 0xd6, 0x4e, 0xbd, 0x50, 0xa6, 0x9f,
+	0xcf, 0x87, 0xdb, 0x85, 0x78, 0xc4, 0xd4, 0x2b, 0x16, 0x75, 0xa2, 0xc9,
+	0x65, 0xb5, 0xef, 0x20, 0x92, 0x76, 0x0e, 0x61, 0xac, 0xb8, 0x5e, 0x2d,
+	0xef, 0xd4, 0xf3, 0x65, 0x43, 0x56, 0x42, 0xe4, 0x3b, 0xa2, 0xf2, 0xf8,
+	0x9d, 0xca, 0xd6, 0x8a, 0x88, 0x25, 0xb0, 0x99, 0xf8, 0x87, 0x31, 0xae,
+	0x6a, 0x83, 0x4d, 0x51, 0xf7, 0xd4, 0xbb, 0xf2, 0x91, 0x9e, 0xee, 0x37,
+	0x8a, 0x99, 0x45, 0xf8, 0x5f, 0xd6, 0x2f, 0x3a, 0xbc, 0x5a, 0xe3, 0x4b,
+	0x5e, 0x3e, 0xf4, 0x8c, 0x30, 0x4f, 0x99, 0x2b, 0x91, 0x97, 0x22, 0xfc,
+	0xe1, 0x46, 0xb6, 0x44, 0x39, 0xba, 0x3e, 0xe5, 0x10, 0xec, 0x42, 0x5f,
+	0x32, 0x3d, 0x1b, 0xe0, 0xdf, 0x28, 0xee, 0x31, 0x06, 0xe0, 0xbb, 0xde,
+	0x86, 0xf5, 0xbe, 0x17, 0x32, 0xa2, 0x6e, 0xa0, 0xbf, 0x25, 0xee, 0xbb,
+	0x42, 0x7f, 0x4b, 0x57, 0xde, 0xb6, 0x7b, 0xe9, 0xf3, 0x46, 0xe4, 0x18,
+	0xfc, 0xe8, 0xd1, 0x45, 0xf2, 0x93, 0xf6, 0x70, 0xd9, 0x30, 0x64, 0x42,
+	0x1f, 0x3f, 0x2c, 0x6f, 0xd4, 0x7e, 0xa0, 0x70, 0xe0, 0xb6, 0x9d, 0x0d,
+	0x99, 0x86, 0x7f, 0x98, 0x71, 0x20, 0x7f, 0x33, 0x82, 0xf5, 0x19, 0x56,
+	0xfe, 0x71, 0xe6, 0xfd, 0xe5, 0x24, 0x01, 0x37, 0x66, 0x7f, 0xf6, 0x3e,
+	0x63, 0xf6, 0x03, 0xc0, 0x61, 0xef, 0x8b, 0xbe, 0xe1, 0xd2, 0xff, 0x33,
+	0xe8, 0xea, 0xd7, 0x55, 0xfd, 0x22, 0xb7, 0x73, 0x2b, 0x65, 0xfa, 0x5e,
+	0xcf, 0xe9, 0xee, 0x73, 0x9f, 0xbb, 0x4f, 0xbe, 0x4c, 0xa9, 0x01, 0x2b,
+	0xe4, 0x55, 0x1c, 0x65, 0xae, 0xd8, 0xe6, 0xe9, 0x6f, 0x10, 0x18, 0x9a,
+	0x74, 0x7d, 0xdf, 0xdb, 0x21, 0xf9, 0x5e, 0x3f, 0xff, 0x84, 0xcf, 0x5e,
+	0x6d, 0xf7, 0xf3, 0x59, 0x3e, 0xbf, 0x92, 0x41, 0xfe, 0x0c, 0x1b, 0x60,
+	0x2c, 0x60, 0x5b, 0x5c, 0xf9, 0xa1, 0x77, 0xe7, 0x9b, 0xf5, 0x0b, 0xf2,
+	0xbd, 0x5b, 0xf1, 0x9d, 0x56, 0x7c, 0xb3, 0x06, 0xb9, 0x5f, 0x4b, 0x9d,
+	0x67, 0x1d, 0xd2, 0xaf, 0x3b, 0x92, 0x1e, 0xb0, 0x01, 0xf4, 0xfd, 0x63,
+	0xd0, 0xfd, 0x11, 0xf4, 0xfa, 0xc3, 0x12, 0xb0, 0x41, 0x09, 0xd8, 0xa0,
+	0x04, 0x6c, 0x50, 0x02, 0x36, 0x28, 0x85, 0xbd, 0x3a, 0x8b, 0x4d, 0x6c,
+	0xff, 0x3e, 0x6d, 0xd7, 0xaf, 0x6d, 0xac, 0xb7, 0x4b, 0xb7, 0xb6, 0x99,
+	0xaa, 0xfb, 0x18, 0x39, 0xc8, 0x5a, 0x2b, 0xb0, 0x9a, 0x5f, 0xf7, 0xf0,
+	0x62, 0x44, 0x8d, 0xfb, 0x5e, 0x88, 0x11, 0x35, 0x1b, 0xeb, 0x66, 0x28,
+	0x6c, 0x00, 0x1b, 0x1a, 0x12, 0xc6, 0x6f, 0x13, 0xbe, 0x17, 0xb4, 0x86,
+	0xfb, 0xb1, 0x92, 0xda, 0x55, 0x5d, 0xef, 0x88, 0xaa, 0x3b, 0x58, 0x32,
+	0x5b, 0xf6, 0x73, 0xb7, 0x98, 0x8c, 0xcd, 0x13, 0x6f, 0xca, 0x16, 0x3d,
+	0x01, 0x1d, 0x38, 0xc4, 0x88, 0xdc, 0x27, 0xe4, 0xf8, 0xb1, 0xc1, 0x2a,
+	0xc6, 0x2c, 0x58, 0x2e, 0x7f, 0x47, 0x9c, 0xbb, 0xcf, 0xec, 0x82, 0x7f,
+	0xce, 0x14, 0x23, 0x32, 0x5e, 0x74, 0x31, 0x01, 0xf2, 0x9f, 0x75, 0xf5,
+	0xe5, 0x5b, 0xd0, 0xc3, 0xad, 0xcc, 0x94, 0xb5, 0x6a, 0x1b, 0x91, 0xcb,
+	0x71, 0xca, 0x98, 0xfa, 0xdf, 0xab, 0xf6, 0x29, 0x76, 0x55, 0xdd, 0xbd,
+	0xa4, 0x71, 0x65, 0x0b, 0x01, 0xfa, 0x19, 0xd0, 0x89, 0xbb, 0x6b, 0x18,
+	0x76, 0x91, 0x73, 0x7c, 0xb9, 0xb4, 0xe2, 0x91, 0x2f, 0x6a, 0x62, 0x6d,
+	0xd4, 0xfe, 0x1b, 0x2d, 0xed, 0xab, 0xf7, 0x3d, 0x7e, 0xe1, 0xfb, 0x56,
+	0x6b, 0x0d, 0xf4, 0x53, 0x77, 0xdb, 0x81, 0xdd, 0x24, 0xa0, 0xee, 0xc3,
+	0x87, 0xd7, 0x42, 0x92, 0xaa, 0x59, 0x92, 0x2e, 0xb3, 0x1f, 0xeb, 0x17,
+	0xf4, 0x47, 0x7f, 0x22, 0x29, 0xe4, 0xab, 0xd9, 0x50, 0x34, 0x6e, 0xcb,
+	0x7f, 0x96, 0xe5, 0x85, 0x7c, 0x84, 0xe7, 0x0a, 0xf2, 0x13, 0x1a, 0x9e,
+	0xfb, 0x19, 0xae, 0xc9, 0xb3, 0x25, 0x33, 0x45, 0xc6, 0x9d, 0xa1, 0x70,
+	0x0d, 0xf7, 0xb2, 0x93, 0xac, 0xd9, 0x7c, 0x07, 0x36, 0x19, 0x8d, 0x94,
+	0xa1, 0xef, 0x2b, 0x45, 0x8e, 0x07, 0x6c, 0x54, 0x64, 0x5d, 0xc7, 0xbf,
+	0xff, 0x27, 0xc0, 0x81, 0xf0, 0xd5, 0x21, 0xaf, 0x8f, 0x9a, 0xab, 0x6d,
+	0x06, 0x60, 0xe3, 0x0d, 0xcf, 0xdf, 0x56, 0x8a, 0x6e, 0x1d, 0xe5, 0x2c,
+	0xf9, 0x70, 0xfe, 0x77, 0xb3, 0x11, 0x42, 0x0e, 0xb4, 0x3a, 0xc7, 0xab,
+	0xa4, 0x6f, 0xc2, 0xdd, 0xca, 0x51, 0xc7, 0x97, 0x05, 0xef, 0xb3, 0x8d,
+	0x67, 0x27, 0x9a, 0xcd, 0xb3, 0xd6, 0x07, 0xad, 0x99, 0xf5, 0x6d, 0x4f,
+	0x5a, 0xf9, 0xdd, 0x15, 0x27, 0xef, 0xd5, 0xcc, 0xbe, 0xbd, 0xc3, 0xad,
+	0x99, 0xd5, 0x76, 0xac, 0xad, 0x99, 0x59, 0xdb, 0xdd, 0x9a, 0xd9, 0xfc,
+	0xee, 0x02, 0x3e, 0x6e, 0xcd, 0x2c, 0xbb, 0xdd, 0xad, 0x99, 0x95, 0xb7,
+	0xbb, 0x35, 0x33, 0x67, 0x87, 0x5b, 0x33, 0xfb, 0xf9, 0xf6, 0xb5, 0x35,
+	0xb3, 0x1f, 0xec, 0x58, 0x5b, 0x33, 0xbb, 0xb8, 0x3b, 0x87, 0xcf, 0xdd,
+	0x9a, 0xd9, 0xcf, 0x76, 0xdc, 0xbb, 0x66, 0xf6, 0x9a, 0x8f, 0xd7, 0x31,
+	0x9f, 0x11, 0xcc, 0x21, 0x0e, 0xbc, 0x3e, 0x0c, 0xbc, 0xfe, 0x6e, 0x75,
+	0xfe, 0x00, 0xe6, 0x39, 0xe8, 0xc5, 0x83, 0x0f, 0x82, 0xdb, 0x47, 0xbc,
+	0x67, 0x6d, 0xe4, 0xbb, 0x11, 0x2f, 0x57, 0x21, 0x76, 0xdf, 0xec, 0xe5,
+	0x6c, 0xff, 0xa8, 0xf3, 0xee, 0xb9, 0x97, 0xd6, 0xef, 0x0f, 0x21, 0xf5,
+	0xf6, 0xf1, 0x3c, 0xe7, 0x95, 0x47, 0xee, 0x47, 0x39, 0xd8, 0xe8, 0x3f,
+	0xbf, 0xfb, 0x1b, 0x16, 0x31, 0xfe, 0x73, 0x58, 0xab, 0xf6, 0x16, 0x43,
+	0x9d, 0x01, 0x60, 0x8c, 0x3a, 0x2e, 0x29, 0xf4, 0x4f, 0xa9, 0xfe, 0xd7,
+	0x5a, 0xfa, 0xaf, 0xa0, 0x3f, 0xe9, 0x46, 0xff, 0x1d, 0x3e, 0x2f, 0x29,
+	0xfb, 0xb6, 0x5c, 0x0c, 0x9f, 0x2e, 0xf9, 0x78, 0x2b, 0xe0, 0x61, 0xe7,
+	0x46, 0xc6, 0x76, 0x3e, 0x8f, 0x67, 0xa2, 0x17, 0x6d, 0xb9, 0xa9, 0xf0,
+	0xbb, 0x91, 0x88, 0x5e, 0xcc, 0xaa, 0x7c, 0xad, 0x91, 0xc9, 0x39, 0x7e,
+	0xfe, 0x8d, 0x1c, 0x6a, 0x80, 0x39, 0x0c, 0xec, 0x7d, 0x69, 0x10, 0x71,
+	0xac, 0x35, 0xc7, 0x66, 0x5e, 0xad, 0x7b, 0x79, 0xb5, 0x29, 0x9f, 0xd9,
+	0xd9, 0x8a, 0xcd, 0x2f, 0xee, 0xfe, 0xc7, 0x0a, 0x9b, 0x6f, 0x42, 0x6e,
+	0x4e, 0xec, 0x4d, 0x1c, 0x43, 0x0c, 0x41, 0x7c, 0xce, 0x7a, 0x01, 0xf3,
+	0x19, 0xc6, 0x46, 0xe6, 0x37, 0x21, 0x7c, 0x78, 0x26, 0xc9, 0xc7, 0xe8,
+	0xed, 0x9e, 0x7f, 0x67, 0x5e, 0xe4, 0x63, 0x95, 0xe4, 0x26, 0x37, 0x37,
+	0xda, 0xa4, 0xb9, 0xf9, 0x67, 0xc4, 0xeb, 0x13, 0x58, 0xc5, 0xc2, 0x81,
+	0x55, 0x2c, 0xbc, 0x66, 0x1f, 0x4b, 0xd4, 0xf9, 0x27, 0xb5, 0x1f, 0xc6,
+	0xfd, 0xb1, 0x46, 0xe6, 0xca, 0x80, 0x68, 0x7a, 0x82, 0xfb, 0x64, 0xc0,
+	0x3a, 0x16, 0xf7, 0xcd, 0xe8, 0x3b, 0xf7, 0x69, 0xa9, 0x2a, 0xe3, 0x0f,
+	0xf1, 0x91, 0xbf, 0x17, 0xee, 0xeb, 0x89, 0xb2, 0x63, 0xdb, 0x1f, 0x6b,
+	0xc8, 0x79, 0xe3, 0xed, 0xd6, 0x53, 0xe0, 0x25, 0x83, 0x6f, 0x5f, 0xa6,
+	0x9f, 0x55, 0xb1, 0xaf, 0x03, 0xb6, 0x7b, 0xa4, 0x44, 0xec, 0xba, 0x59,
+	0x6a, 0x1e, 0x7e, 0x3d, 0x37, 0xef, 0x62, 0xd7, 0xc0, 0x5a, 0xec, 0x1a,
+	0x5f, 0x16, 0x97, 0xc7, 0x5d, 0x1b, 0xf2, 0x48, 0xbc, 0x4a, 0xfe, 0x18,
+	0x77, 0xf6, 0xc2, 0xff, 0x35, 0x80, 0x69, 0x19, 0x73, 0x18, 0x6f, 0x22,
+	0xc0, 0xf6, 0xf7, 0xe2, 0x4f, 0xb5, 0x1d, 0xea, 0xb0, 0x82, 0xf8, 0x4c,
+	0xc3, 0x7f, 0x4c, 0xe0, 0x99, 0x8c, 0xcc, 0x9e, 0xfe, 0x1a, 0xe6, 0x36,
+	0x2d, 0x57, 0xe6, 0x27, 0xc1, 0xdf, 0x73, 0x32, 0x17, 0xcf, 0xc3, 0x8f,
+	0x70, 0xcf, 0x83, 0xb8, 0xad, 0xdf, 0xfb, 0x9e, 0xd6, 0xcf, 0x5a, 0x51,
+	0xe2, 0x46, 0xa9, 0x16, 0xe9, 0x83, 0xb9, 0x67, 0xc8, 0xbd, 0x61, 0xda,
+	0x0f, 0xeb, 0x27, 0xc8, 0x5d, 0x99, 0xc3, 0x9e, 0xe2, 0xf8, 0x6b, 0x75,
+	0xb2, 0xec, 0x10, 0x7f, 0x35, 0x32, 0x8d, 0x25, 0xe2, 0xc7, 0xf7, 0x8b,
+	0x25, 0xa9, 0x07, 0xe2, 0xc9, 0xfb, 0xc1, 0x91, 0xd1, 0x79, 0x60, 0xc8,
+	0x57, 0x1a, 0x7a, 0x2b, 0x8e, 0x74, 0x31, 0x64, 0x72, 0x29, 0x0b, 0x9a,
+	0x71, 0x85, 0x95, 0x91, 0xc7, 0xc1, 0xed, 0xf5, 0xe3, 0xd9, 0x7e, 0xe4,
+	0xe4, 0x2e, 0x66, 0x4c, 0x01, 0x33, 0xfe, 0x06, 0x30, 0xe3, 0xac, 0x74,
+	0x76, 0x11, 0x33, 0xda, 0x1e, 0x66, 0x4c, 0xc3, 0x9e, 0x73, 0x6b, 0xec,
+	0x59, 0x53, 0xb5, 0x28, 0xde, 0xcb, 0x01, 0xf3, 0xa5, 0x4e, 0x45, 0xef,
+	0x03, 0x27, 0x6a, 0x12, 0x52, 0xe7, 0x52, 0x02, 0x2d, 0x34, 0x7d, 0x3c,
+	0xb8, 0x4d, 0xe1, 0xbc, 0xdd, 0xa5, 0x4d, 0xc8, 0x51, 0x14, 0xee, 0xf3,
+	0xf6, 0x4b, 0x03, 0xeb, 0xf6, 0x90, 0x03, 0x2d, 0x7b, 0xc8, 0x77, 0xf1,
+	0x21, 0x9e, 0xf3, 0x6a, 0x7d, 0x6d, 0xf0, 0x05, 0xff, 0x13, 0x3c, 0x71,
+	0x7d, 0x71, 0x2d, 0x68, 0xee, 0x7a, 0x59, 0x83, 0x13, 0xff, 0x7a, 0x1d,
+	0x4e, 0x44, 0xec, 0x3a, 0x17, 0x92, 0x24, 0x30, 0xa2, 0xbd, 0x44, 0x5a,
+	0x5c, 0xd3, 0xc3, 0xd2, 0x8e, 0xf9, 0x75, 0x9c, 0xea, 0x05, 0x36, 0xea,
+	0x92, 0x20, 0x30, 0x52, 0x9b, 0xc2, 0x48, 0x03, 0xc4, 0x32, 0x83, 0x33,
+	0xc0, 0x36, 0xb5, 0x55, 0x9c, 0x14, 0x8d, 0xff, 0x01, 0xf4, 0xf2, 0x94,
+	0xf2, 0x3d, 0x69, 0x39, 0x01, 0x5f, 0xda, 0xbe, 0x04, 0x7c, 0x77, 0xce,
+	0xc5, 0x4f, 0x6d, 0xeb, 0xf0, 0xd3, 0xc1, 0x0d, 0xf1, 0x93, 0xaa, 0xdf,
+	0x8f, 0x52, 0x26, 0x37, 0x1c, 0xb7, 0x7e, 0x7f, 0xdd, 0x71, 0xeb, 0xf7,
+	0x37, 0x9c, 0xd6, 0xfa, 0xfd, 0x47, 0xa4, 0x60, 0x46, 0xed, 0x15, 0x59,
+	0x57, 0xbf, 0x9f, 0x60, 0x3d, 0xdc, 0xe9, 0x72, 0xeb, 0xf4, 0x5d, 0x5e,
+	0xfd, 0x3e, 0x2a, 0x85, 0x35, 0xed, 0xa6, 0xbc, 0x69, 0xf9, 0xf5, 0xfb,
+	0xef, 0xa2, 0xad, 0x1b, 0x63, 0xac, 0xad, 0xdd, 0x5f, 0x77, 0x58, 0xbb,
+	0x0f, 0xb1, 0x9f, 0x57, 0xbb, 0x67, 0x3f, 0xe4, 0xf2, 0x0e, 0xeb, 0xf6,
+	0x8f, 0x40, 0x16, 0x5b, 0x21, 0x87, 0x5e, 0x69, 0x3f, 0x13, 0x66, 0x1f,
+	0x55, 0xaf, 0x5f, 0x71, 0x42, 0x78, 0xce, 0xad, 0xab, 0xcf, 0xc0, 0xae,
+	0x0e, 0xae, 0xd6, 0xeb, 0xdd, 0x31, 0x6e, 0x3a, 0x6b, 0xe9, 0xaf, 0xa5,
+	0xd3, 0xe7, 0xd1, 0x09, 0x81, 0x4e, 0x78, 0x1d, 0x9d, 0xbb, 0xf5, 0xf9,
+	0x9b, 0x8e, 0x5b, 0x9b, 0x4f, 0x9f, 0x16, 0xbb, 0x1d, 0xbe, 0xf9, 0xe2,
+	0xc0, 0xc3, 0x1e, 0x8d, 0xd5, 0xda, 0x3c, 0x7d, 0x08, 0x70, 0x7b, 0x4c,
+	0x9d, 0xbd, 0x9a, 0xf9, 0x7f, 0x50, 0x9b, 0x67, 0x5d, 0xde, 0xdd, 0x5f,
+	0xe1, 0xfa, 0x04, 0x3e, 0x7f, 0xd1, 0xad, 0xc9, 0x8f, 0x95, 0xfc, 0x5a,
+	0x3b, 0xf3, 0x47, 0xff, 0x5c, 0x54, 0x7f, 0xe4, 0x88, 0xd0, 0x56, 0xc8,
+	0x1f, 0xe9, 0x76, 0xcb, 0x94, 0xc2, 0x47, 0xb0, 0xa9, 0xd8, 0xbd, 0x31,
+	0x72, 0xe5, 0x94, 0x8f, 0x91, 0x43, 0x0a, 0x23, 0x57, 0x96, 0x7c, 0x8c,
+	0x9c, 0xbc, 0x07, 0x46, 0x6e, 0x76, 0xb9, 0x71, 0x20, 0x28, 0x79, 0x85,
+	0x91, 0xef, 0x75, 0x96, 0x8c, 0xf7, 0xba, 0x88, 0x07, 0xc4, 0x3d, 0x5f,
+	0xd0, 0x7b, 0x8f, 0xb5, 0xe6, 0xe3, 0x66, 0xc6, 0xfe, 0xad, 0x32, 0x71,
+	0xe6, 0x2e, 0x6e, 0x76, 0xb1, 0x71, 0x34, 0x72, 0x48, 0xc5, 0x44, 0xe0,
+	0x84, 0x3a, 0xeb, 0xdf, 0xc4, 0xbe, 0x8c, 0x39, 0x01, 0x85, 0xcf, 0x72,
+	0x45, 0xe6, 0x01, 0x6c, 0x23, 0x16, 0xee, 0xe4, 0x31, 0x2b, 0x2f, 0x26,
+	0xf9, 0x58, 0xd3, 0x3f, 0xd7, 0xc2, 0x3d, 0x86, 0x37, 0x8d, 0xa4, 0x85,
+	0x76, 0xc7, 0xcf, 0x15, 0xe2, 0xea, 0x3c, 0x50, 0x12, 0x58, 0x72, 0x6a,
+	0x15, 0x4b, 0xd2, 0x57, 0xfc, 0xf4, 0x6d, 0xdb, 0xa4, 0x5f, 0xf3, 0xb1,
+	0x22, 0x72, 0xa2, 0x12, 0xd7, 0xb6, 0x8f, 0x15, 0x5d, 0x9c, 0x98, 0x72,
+	0x1a, 0xc0, 0xcb, 0x01, 0x19, 0x03, 0x4e, 0x6f, 0x7c, 0x89, 0x35, 0x28,
+	0x1f, 0x1b, 0xd9, 0xf8, 0x6e, 0xad, 0x49, 0xf1, 0xba, 0x5d, 0xed, 0x05,
+	0x5e, 0x1e, 0x08, 0xb6, 0xb4, 0x3f, 0x0b, 0xff, 0x8d, 0xfc, 0x08, 0xd8,
+	0xc4, 0xc5, 0x44, 0x3b, 0xa0, 0x83, 0x91, 0x7b, 0x60, 0xa2, 0xf5, 0x31,
+	0x8a, 0x31, 0xf3, 0x6e, 0x8c, 0x4a, 0xd7, 0xe9, 0xcf, 0xef, 0xc6, 0xa8,
+	0x7b, 0xc7, 0x50, 0xb6, 0x61, 0x76, 0x56, 0x06, 0x9f, 0x69, 0x29, 0xac,
+	0x8b, 0x51, 0x73, 0x1f, 0x20, 0x46, 0xb9, 0xf8, 0xc0, 0xe5, 0xfb, 0xf7,
+	0x21, 0x9b, 0x1f, 0x43, 0xa6, 0x3f, 0x02, 0xe6, 0xfa, 0x21, 0xe6, 0xf5,
+	0x03, 0xe0, 0xa1, 0xef, 0x97, 0xd6, 0x9f, 0x07, 0x19, 0x15, 0xe6, 0x87,
+	0x2e, 0x66, 0x72, 0x31, 0xfd, 0x0c, 0x56, 0x57, 0xad, 0xd8, 0xc8, 0x4c,
+	0x15, 0x87, 0xcc, 0x69, 0x77, 0x1f, 0x35, 0x92, 0x95, 0xa7, 0x3b, 0x53,
+	0x8b, 0x8c, 0x19, 0xea, 0x3a, 0xcc, 0xfa, 0x25, 0xb1, 0x43, 0x55, 0xe5,
+	0x99, 0x03, 0x52, 0xae, 0xb9, 0x78, 0x6b, 0x6e, 0xd1, 0xa5, 0x31, 0xe5,
+	0xe1, 0xad, 0x9c, 0x87, 0xb7, 0xb2, 0xb5, 0xe5, 0x48, 0x00, 0xfd, 0xe7,
+	0xe2, 0x6b, 0x31, 0xd6, 0x8c, 0x87, 0xb1, 0xa6, 0x3f, 0x20, 0xc6, 0xe2,
+	0x58, 0x39, 0x3c, 0x33, 0x3e, 0x1f, 0x91, 0x5d, 0x90, 0xf3, 0x58, 0x91,
+	0xfa, 0xe2, 0x19, 0xb2, 0xf7, 0xd2, 0x19, 0xf5, 0xe5, 0xea, 0x2a, 0x10,
+	0xdb, 0xa7, 0x8d, 0x43, 0x57, 0x63, 0xef, 0xa9, 0x2b, 0x31, 0xdf, 0x18,
+	0x09, 0xe2, 0xf3, 0xf7, 0xa5, 0x2b, 0xce, 0x83, 0xfa, 0x5a, 0x8f, 0xc5,
+	0xee, 0x07, 0x93, 0xad, 0xc5, 0x63, 0xb6, 0xc2, 0x63, 0xed, 0x5e, 0x1f,
+	0xd9, 0x33, 0x0e, 0x5d, 0xfe, 0x27, 0xf4, 0xf9, 0x99, 0xd5, 0x2d, 0x3f,
+	0x85, 0xff, 0xfe, 0x43, 0xe8, 0xe4, 0x3f, 0x22, 0x57, 0x78, 0xcd, 0xea,
+	0x93, 0x3f, 0x40, 0xdb, 0x5d, 0x9c, 0xc3, 0xfe, 0xc1, 0xc7, 0x92, 0xd6,
+	0x35, 0xe0, 0x93, 0x6b, 0x1e, 0x3e, 0x79, 0x3a, 0x99, 0xb4, 0x26, 0x59,
+	0x37, 0x87, 0x9c, 0x0f, 0xa4, 0xa6, 0x14, 0x36, 0xf1, 0x31, 0xc9, 0xed,
+	0x34, 0xc7, 0x9f, 0x75, 0x56, 0x80, 0x7d, 0x56, 0x3c, 0xec, 0x73, 0x60,
+	0xcc, 0xc5, 0x3e, 0xc1, 0xcf, 0x50, 0xff, 0x2e, 0xee, 0x59, 0xb1, 0x93,
+	0x18, 0xa7, 0x0a, 0x4c, 0x52, 0x71, 0x0e, 0x48, 0xbe, 0xbe, 0x57, 0x7d,
+	0x8e, 0x94, 0xec, 0x68, 0x1b, 0xe4, 0xc4, 0xda, 0xeb, 0x49, 0xae, 0x4a,
+	0x27, 0x6a, 0x16, 0xf1, 0x9d, 0x75, 0xa2, 0xe1, 0xdf, 0xf1, 0xae, 0x9f,
+	0xf7, 0xae, 0x4f, 0x78, 0xd7, 0xc7, 0x11, 0x87, 0x8f, 0xa9, 0x58, 0xca,
+	0x76, 0xb6, 0x41, 0xc9, 0x0e, 0x68, 0x01, 0x7b, 0x9c, 0x1d, 0xfe, 0x8b,
+	0x66, 0x59, 0xe9, 0x98, 0xf4, 0x27, 0xf0, 0x39, 0x8e, 0xcf, 0x34, 0x3e,
+	0xfb, 0xf1, 0xc9, 0xe3, 0xb3, 0x2a, 0x53, 0x2d, 0x55, 0x9a, 0x84, 0x8d,
+	0x0c, 0x4a, 0xaa, 0xfe, 0x12, 0xf4, 0xf8, 0x1c, 0x74, 0x7b, 0x58, 0x0a,
+	0xd5, 0x3f, 0x95, 0xd9, 0x79, 0x4d, 0xba, 0x2c, 0xe8, 0xb4, 0x0a, 0x5b,
+	0x9e, 0x77, 0xf7, 0x13, 0x3b, 0x13, 0x7b, 0xd1, 0xb7, 0x29, 0x4f, 0xc5,
+	0x9f, 0x13, 0xfd, 0xb1, 0x39, 0xf4, 0x13, 0xbd, 0x30, 0xfc, 0x31, 0xb5,
+	0x6f, 0x56, 0x8d, 0xbb, 0x32, 0xde, 0x65, 0xd9, 0x51, 0xe8, 0x7c, 0xf0,
+	0x18, 0x68, 0x27, 0xd5, 0xd9, 0xd8, 0x8c, 0x1c, 0x3d, 0xbd, 0xbc, 0xc5,
+	0xf5, 0xad, 0x51, 0xf3, 0x26, 0xf5, 0x8e, 0x79, 0xd8, 0xf0, 0x85, 0x19,
+	0xd8, 0xfb, 0x41, 0x27, 0xa0, 0x8d, 0x21, 0xde, 0x8c, 0x39, 0x37, 0x55,
+	0xbc, 0x81, 0xef, 0xca, 0xc4, 0x4e, 0x86, 0x70, 0xcd, 0xb3, 0x45, 0x88,
+	0x8b, 0xea, 0x6c, 0xe5, 0x32, 0xf0, 0x8d, 0xa6, 0xea, 0x80, 0xb3, 0xab,
+	0xfb, 0x43, 0x86, 0xf2, 0x5b, 0xb1, 0x98, 0x2e, 0xb9, 0x11, 0xe2, 0xdc,
+	0xbd, 0x2a, 0x36, 0xd5, 0x8a, 0xf6, 0x43, 0xcc, 0x15, 0x6f, 0x08, 0xe3,
+	0xdc, 0xe3, 0xe8, 0xd7, 0x07, 0x7f, 0x8c, 0x7b, 0x75, 0xda, 0x27, 0xe7,
+	0xca, 0x67, 0xa6, 0xa5, 0x5a, 0x1e, 0xc5, 0x7c, 0xbd, 0x1c, 0x49, 0xe5,
+	0x12, 0x11, 0xd8, 0xa3, 0xbf, 0x17, 0xe5, 0xd6, 0x4f, 0xaa, 0x8e, 0x8f,
+	0x29, 0xba, 0xd1, 0x87, 0x79, 0x05, 0x64, 0xe4, 0xee, 0x9f, 0xa9, 0xbd,
+	0xb3, 0x82, 0x33, 0x0a, 0x39, 0x25, 0xd1, 0xce, 0x5a, 0x35, 0x7e, 0x97,
+	0x75, 0x55, 0x13, 0x58, 0x31, 0x66, 0xa4, 0x56, 0x6e, 0x82, 0x5f, 0xc4,
+	0xdc, 0x2d, 0x33, 0x52, 0x29, 0x4f, 0xcb, 0x2b, 0xe5, 0x9f, 0x77, 0x03,
+	0x53, 0x41, 0xa6, 0xe4, 0xbf, 0x5b, 0xee, 0x9e, 0xbf, 0xf5, 0xdb, 0x21,
+	0xcf, 0xd3, 0xf9, 0xb0, 0x9b, 0xe7, 0xe6, 0x55, 0x2d, 0xc6, 0xfd, 0xb6,
+	0xf5, 0x29, 0x2b, 0x1a, 0x9e, 0x45, 0xcf, 0x83, 0x0b, 0xb4, 0xcd, 0xfc,
+	0xf8, 0x9c, 0xb5, 0x43, 0xae, 0xc6, 0x37, 0xcb, 0x72, 0x5c, 0xe5, 0xc5,
+	0xc4, 0x0f, 0x58, 0xeb, 0x51, 0xb3, 0x21, 0x7b, 0xe4, 0x28, 0xd6, 0xed,
+	0xd5, 0xf8, 0xd3, 0xb0, 0xd3, 0x67, 0x61, 0x0b, 0xac, 0x01, 0x1c, 0x62,
+	0xae, 0x25, 0x0d, 0x55, 0x23, 0x6b, 0x36, 0xc7, 0xd5, 0x19, 0xee, 0x76,
+	0x59, 0x56, 0x58, 0xcc, 0xad, 0x9d, 0x2f, 0x4f, 0xba, 0x6b, 0xc4, 0x50,
+	0x76, 0xff, 0xc7, 0xe0, 0xc7, 0x84, 0xed, 0xb6, 0xa9, 0x3e, 0x46, 0xa2,
+	0xc3, 0xeb, 0xa3, 0xf4, 0xdb, 0xd2, 0xe7, 0x95, 0x44, 0xd2, 0xda, 0xff,
+	0x89, 0xa4, 0x75, 0x73, 0xb7, 0x5b, 0x6f, 0x89, 0x9a, 0xb6, 0xc6, 0xf7,
+	0x52, 0xdc, 0xf5, 0x98, 0xc1, 0xba, 0xba, 0xb4, 0x8a, 0xa1, 0x61, 0xa4,
+	0x2f, 0x5f, 0x81, 0x7e, 0x03, 0xd2, 0x7e, 0xb2, 0xf9, 0xf8, 0x54, 0x7c,
+	0x28, 0x72, 0x50, 0x78, 0x02, 0x8b, 0x79, 0x75, 0x34, 0x9e, 0x95, 0x2b,
+	0x88, 0x93, 0x77, 0x88, 0x1d, 0x06, 0x2f, 0xcb, 0x9d, 0xc7, 0x93, 0xf1,
+	0x51, 0xad, 0x32, 0x89, 0xac, 0xe5, 0xe5, 0x49, 0xc6, 0xd9, 0x43, 0x22,
+	0xc0, 0x97, 0x27, 0x47, 0x24, 0x5d, 0x54, 0xef, 0xa9, 0xf0, 0x9c, 0xad,
+	0x36, 0x0d, 0xf9, 0xe1, 0xf9, 0x09, 0x06, 0x46, 0xdd, 0xea, 0x8f, 0xa4,
+	0xe5, 0x69, 0xd6, 0xc0, 0x24, 0xb7, 0x20, 0xdb, 0x92, 0xf0, 0xab, 0xf6,
+	0x44, 0xbb, 0x4c, 0xd7, 0x1a, 0x99, 0xfe, 0x53, 0xcf, 0x82, 0xc6, 0x14,
+	0x68, 0xed, 0x45, 0x6e, 0x92, 0x45, 0xac, 0xa6, 0x7c, 0xe9, 0xbb, 0x9f,
+	0x81, 0x8c, 0x3e, 0xc2, 0x3d, 0xe5, 0xd1, 0xac, 0x44, 0x27, 0xf2, 0x8a,
+	0xee, 0x5b, 0x5a, 0x6e, 0xf8, 0x57, 0x10, 0xeb, 0x02, 0xb2, 0x2b, 0x26,
+	0xfa, 0xde, 0x58, 0xe0, 0xed, 0x29, 0x8b, 0x6d, 0x41, 0xb6, 0xe9, 0x68,
+	0x0b, 0xfc, 0x7a, 0x2c, 0xa8, 0x27, 0x63, 0xd1, 0x51, 0x9e, 0x8f, 0x36,
+	0xac, 0x29, 0xee, 0x4d, 0x3c, 0x20, 0x5d, 0x7b, 0xa5, 0xe7, 0x42, 0x74,
+	0xf4, 0x06, 0x78, 0x09, 0x28, 0x5f, 0x3f, 0x25, 0xba, 0xd7, 0xde, 0xbd,
+	0xda, 0x1e, 0xf0, 0xda, 0xf7, 0x4a, 0xd7, 0x85, 0x21, 0xf3, 0x75, 0x99,
+	0x01, 0x4d, 0x43, 0xae, 0x23, 0xd7, 0xb1, 0x06, 0xa6, 0x60, 0x8b, 0x4f,
+	0x92, 0x97, 0xfd, 0xc0, 0x1a, 0x58, 0x1b, 0xc8, 0xbf, 0xad, 0x0f, 0xcb,
+	0x57, 0xcd, 0x4e, 0xc9, 0xa9, 0x5c, 0x37, 0xe0, 0xd6, 0x52, 0x61, 0xef,
+	0x8f, 0x0e, 0x1c, 0xec, 0x71, 0xeb, 0x05, 0xdc, 0xef, 0x18, 0x46, 0xdb,
+	0x9d, 0xe6, 0x39, 0x8b, 0x6d, 0xbc, 0x77, 0xa7, 0x59, 0xb5, 0x86, 0xcc,
+	0x94, 0x16, 0xf4, 0xf6, 0xbd, 0x0f, 0xa9, 0xb9, 0xe7, 0xcb, 0xfd, 0x66,
+	0x45, 0x1e, 0xd5, 0x52, 0x0f, 0x22, 0x5e, 0x38, 0xd3, 0xe8, 0x7b, 0x87,
+	0xe7, 0x29, 0x54, 0x7d, 0xbf, 0x22, 0xfe, 0x35, 0xe9, 0x0c, 0x99, 0xe3,
+	0xea, 0xd9, 0x21, 0xf3, 0xa8, 0xd6, 0xfa, 0x6c, 0x58, 0x1b, 0x5f, 0xf3,
+	0x6c, 0x97, 0x92, 0x91, 0x61, 0xb9, 0x7d, 0x66, 0xcb, 0x7b, 0xe5, 0x79,
+	0x87, 0xfd, 0xee, 0x34, 0x53, 0xd6, 0x03, 0xda, 0xd1, 0x07, 0xe9, 0x0b,
+	0xd9, 0xf7, 0xf6, 0xba, 0x71, 0x78, 0x7d, 0xaf, 0x31, 0x9a, 0xb2, 0x76,
+	0x8c, 0x4d, 0xaa, 0xcf, 0x55, 0xd5, 0x27, 0xa0, 0x64, 0xbd, 0x76, 0x9c,
+	0xbf, 0x91, 0xb5, 0xe3, 0x74, 0xad, 0xce, 0x79, 0x16, 0x34, 0x8f, 0xa1,
+	0x6f, 0xd1, 0xe9, 0x0f, 0x57, 0xe5, 0x76, 0x33, 0x67, 0xbd, 0x29, 0x57,
+	0x57, 0x69, 0xff, 0x12, 0xd7, 0xad, 0x3c, 0xfd, 0xd2, 0xe3, 0x91, 0xbf,
+	0xd9, 0xf6, 0x2f, 0x95, 0xbc, 0x1f, 0xb0, 0xfa, 0xf7, 0x57, 0xb4, 0xe8,
+	0xe8, 0x5f, 0x0a, 0x75, 0xf5, 0xcf, 0x94, 0xaf, 0xf9, 0x18, 0xf4, 0xb4,
+	0xed, 0x05, 0xac, 0xdd, 0xe1, 0xa4, 0xea, 0x73, 0xdd, 0xda, 0x2b, 0xdb,
+	0x4e, 0xf6, 0x9b, 0xd7, 0xe5, 0x33, 0x92, 0x0e, 0xf1, 0x1a, 0x39, 0x94,
+	0xc5, 0xf7, 0x52, 0x3e, 0xc1, 0xbc, 0x00, 0xba, 0xec, 0x1f, 0xfc, 0x4b,
+	0x79, 0x56, 0x8e, 0x96, 0xe6, 0xe0, 0x7b, 0xa6, 0x64, 0xf0, 0x05, 0xfa,
+	0x9f, 0xbc, 0xe9, 0xd6, 0x6a, 0xdc, 0x98, 0x98, 0xf2, 0x62, 0xe2, 0x9c,
+	0xf2, 0x73, 0xaf, 0x79, 0xe7, 0x22, 0xfa, 0x07, 0xcf, 0xe1, 0xd9, 0x57,
+	0x94, 0x0f, 0xf8, 0x3d, 0xa9, 0x62, 0x2d, 0x44, 0x5e, 0xde, 0x2c, 0x0f,
+	0x3c, 0x41, 0x9b, 0x44, 0x06, 0xf0, 0xb1, 0x36, 0xf5, 0x1e, 0x8c, 0x6e,
+	0x75, 0x88, 0x6c, 0xa1, 0xfd, 0x5c, 0x86, 0xad, 0x4d, 0xb9, 0x7b, 0x5f,
+	0x6b, 0xae, 0xa3, 0x13, 0x2b, 0xf2, 0x1f, 0x94, 0x1d, 0x7e, 0xfc, 0x82,
+	0xfb, 0x3d, 0x7c, 0x01, 0xe9, 0x72, 0x6c, 0xaf, 0x6c, 0xbf, 0xe0, 0xda,
+	0xdd, 0xec, 0xfc, 0xb3, 0x4a, 0xbe, 0x53, 0x4a, 0xbe, 0x4d, 0x99, 0x89,
+	0x53, 0xf6, 0x9c, 0x13, 0xcf, 0x4f, 0xba, 0x32, 0xf9, 0x9c, 0x67, 0x47,
+	0xfd, 0x2f, 0xf0, 0x3d, 0x35, 0xca, 0x88, 0x7c, 0xcf, 0xf4, 0x70, 0x3f,
+	0x76, 0xdb, 0x05, 0xce, 0xb7, 0x6f, 0xcd, 0x7c, 0x4f, 0xc0, 0xc7, 0x0e,
+	0x0c, 0xb8, 0x73, 0x7e, 0x6d, 0xfe, 0xfd, 0xcf, 0xf9, 0x77, 0x57, 0xe7,
+	0x6c, 0x48, 0x55, 0xe5, 0xb9, 0xb1, 0xcd, 0xd2, 0x95, 0x93, 0x06, 0xec,
+	0xe3, 0xcf, 0x85, 0x67, 0xc6, 0xc9, 0x8b, 0x3b, 0xee, 0xb2, 0x43, 0x9e,
+	0xfc, 0x39, 0x90, 0xaf, 0x29, 0x4f, 0x7f, 0xe4, 0xe3, 0xd9, 0x0d, 0xef,
+	0x5d, 0x97, 0x46, 0x66, 0x10, 0x6d, 0xba, 0xd2, 0xe1, 0x98, 0xb7, 0xde,
+	0xf6, 0x8a, 0xae, 0x74, 0x98, 0x5c, 0xd5, 0xe1, 0x0d, 0xe8, 0xb0, 0x2a,
+	0x9f, 0xc6, 0x9c, 0xb0, 0xbe, 0x5f, 0x18, 0x32, 0x67, 0x64, 0xab, 0xd2,
+	0xbf, 0x35, 0x00, 0x9f, 0xea, 0xe9, 0xb2, 0xfd, 0x3e, 0x74, 0xf9, 0xba,
+	0x28, 0x7d, 0xaa, 0x73, 0x44, 0x55, 0x45, 0x87, 0xbe, 0x8d, 0x73, 0x6b,
+	0x57, 0x3e, 0x81, 0x3c, 0xaa, 0xb3, 0x01, 0x13, 0xae, 0x7e, 0xd5, 0x9a,
+	0xf7, 0xf4, 0x9b, 0x9d, 0xa0, 0x0e, 0x7f, 0xad, 0xc7, 0xd5, 0x67, 0x87,
+	0xea, 0x73, 0x2a, 0x36, 0xaa, 0xd6, 0xbb, 0x35, 0xf0, 0xe9, 0x1e, 0xea,
+	0xf4, 0x79, 0xc7, 0xfd, 0x2e, 0x22, 0xce, 0x9d, 0x72, 0xde, 0x4b, 0xaf,
+	0xae, 0x4e, 0xc7, 0xc4, 0x5d, 0x57, 0xeb, 0xf5, 0xa9, 0x5f, 0x08, 0x28,
+	0x1b, 0x1e, 0x83, 0x0c, 0x8f, 0x97, 0x1e, 0xf4, 0xec, 0xde, 0x9d, 0xf3,
+	0xc0, 0xfb, 0x9c, 0xf3, 0x91, 0x62, 0xbf, 0xf9, 0x26, 0xee, 0x8d, 0x63,
+	0xce, 0x33, 0xd2, 0x26, 0x29, 0x6f, 0xce, 0x91, 0xd5, 0x39, 0xfb, 0x3c,
+	0xba, 0xfd, 0x52, 0xcc, 0x63, 0x1d, 0xfa, 0xaf, 0x7f, 0xab, 0xde, 0x37,
+	0xb9, 0x59, 0xa4, 0xdf, 0x06, 0x56, 0x0a, 0xf5, 0xca, 0xf5, 0x5a, 0x44,
+	0xae, 0x13, 0x83, 0x8c, 0xe0, 0xdb, 0x99, 0xf3, 0x62, 0x78, 0x50, 0x5e,
+	0x2f, 0x6e, 0xc4, 0xc7, 0xb0, 0xdc, 0x28, 0xfa, 0xbc, 0x10, 0x0b, 0x33,
+	0x5f, 0x98, 0x92, 0x37, 0xe6, 0xfb, 0xa5, 0x31, 0x81, 0xb8, 0x3f, 0x40,
+	0x99, 0x0c, 0x99, 0x7b, 0xd4, 0x7b, 0x48, 0x77, 0x9a, 0x97, 0x2d, 0xd0,
+	0x5f, 0x68, 0xca, 0x41, 0xee, 0x67, 0xf3, 0x77, 0xed, 0x21, 0x69, 0x30,
+	0xa7, 0x18, 0xe8, 0x95, 0xca, 0x02, 0xf2, 0xf9, 0x22, 0xe9, 0x53, 0x6e,
+	0x7b, 0xd5, 0xef, 0x71, 0x8c, 0xf7, 0x39, 0xbe, 0x1f, 0x10, 0xa2, 0x6e,
+	0xee, 0x34, 0x97, 0x2d, 0xee, 0x67, 0x4e, 0x49, 0x0d, 0xfa, 0xfb, 0xe7,
+	0x31, 0xee, 0xb7, 0xe7, 0xd4, 0xf9, 0xdb, 0x4a, 0x6d, 0x02, 0xb9, 0xc3,
+	0x9d, 0xe6, 0x9c, 0x75, 0x56, 0xe9, 0xad, 0x56, 0x7e, 0xc2, 0x6b, 0xe7,
+	0x35, 0xef, 0x35, 0x32, 0xdb, 0x06, 0x98, 0xaf, 0x3e, 0x81, 0x7c, 0x81,
+	0xb9, 0xea, 0x04, 0xf0, 0x1a, 0x65, 0x12, 0x91, 0xd9, 0x22, 0x69, 0x49,
+	0x68, 0x13, 0xf2, 0xfb, 0x9c, 0x8c, 0x83, 0x9f, 0x08, 0x72, 0x7b, 0xc6,
+	0x87, 0x47, 0x65, 0x39, 0xe4, 0xc6, 0x01, 0x9e, 0xfb, 0x5a, 0x46, 0x6c,
+	0x58, 0x5e, 0x8d, 0x0d, 0x5b, 0x71, 0xdd, 0xc8, 0xc4, 0x07, 0xfe, 0x06,
+	0xf4, 0x59, 0xb7, 0x61, 0x6c, 0x18, 0x45, 0x7f, 0xb6, 0xf5, 0xca, 0xec,
+	0x02, 0x92, 0x08, 0xe4, 0x2c, 0x15, 0xe1, 0x99, 0x8e, 0xac, 0x9c, 0xaa,
+	0xf5, 0x87, 0x2f, 0x6b, 0x69, 0x75, 0xf6, 0x23, 0x36, 0xc0, 0xf3, 0x2c,
+	0xbd, 0x52, 0x5b, 0x90, 0x88, 0x91, 0x78, 0x52, 0x9c, 0x9a, 0x8b, 0xd9,
+	0xe7, 0x34, 0x9e, 0x69, 0xb1, 0xa5, 0xb6, 0xb6, 0x8f, 0x89, 0xdc, 0x57,
+	0xbe, 0xe3, 0xf5, 0x49, 0xab, 0x3e, 0x7f, 0xdd, 0xc3, 0x3d, 0xb4, 0x9a,
+	0xd3, 0x03, 0x1e, 0xc8, 0xdb, 0xc3, 0xad, 0xe3, 0x46, 0xee, 0x8e, 0xcb,
+	0x31, 0x91, 0xcd, 0x6c, 0xb1, 0x31, 0xee, 0x4d, 0x3c, 0xf3, 0x24, 0xf8,
+	0xb8, 0x63, 0xe8, 0xd6, 0x93, 0x52, 0xa8, 0xad, 0x1f, 0xa3, 0x95, 0x07,
+	0x3e, 0x43, 0xfa, 0x1c, 0xe7, 0x00, 0xf8, 0xbb, 0xa3, 0xe9, 0xd6, 0x01,
+	0xc8, 0xd2, 0x1d, 0xc3, 0x38, 0x13, 0x35, 0x7f, 0x2a, 0x03, 0xa2, 0x9f,
+	0xd3, 0x94, 0xfc, 0xf5, 0xca, 0x30, 0x16, 0x48, 0x46, 0xba, 0x96, 0x26,
+	0xc5, 0x58, 0x62, 0x0d, 0xe1, 0xb5, 0xce, 0xb4, 0xda, 0xbf, 0xdd, 0x84,
+	0xf5, 0x2d, 0x76, 0xc0, 0x62, 0xbd, 0x80, 0xf5, 0xe0, 0x9f, 0x6e, 0x96,
+	0x1e, 0xd6, 0x0b, 0x98, 0x37, 0xec, 0xc7, 0x37, 0x73, 0x87, 0x4b, 0x4d,
+	0xe4, 0x7a, 0x9b, 0x19, 0x5f, 0x73, 0x35, 0xde, 0x8f, 0x46, 0x44, 0x78,
+	0x8f, 0x7e, 0xa3, 0x57, 0xda, 0xbe, 0x35, 0x08, 0x5f, 0xf1, 0x34, 0xb0,
+	0x37, 0xe8, 0x9e, 0x1c, 0x90, 0x80, 0x7b, 0x66, 0x42, 0xd5, 0x5b, 0xde,
+	0x58, 0x88, 0x7a, 0xef, 0x73, 0xc9, 0xb6, 0xcb, 0x71, 0xd6, 0x44, 0xfb,
+	0x58, 0xf3, 0x41, 0x3f, 0xd1, 0x97, 0x91, 0x9f, 0x5e, 0xaf, 0x59, 0x9b,
+	0x79, 0x7e, 0xf3, 0x86, 0x83, 0x6b, 0x62, 0xff, 0x90, 0xc2, 0x98, 0xde,
+	0x3d, 0xfe, 0x46, 0xbe, 0xf4, 0x8e, 0x77, 0x13, 0x98, 0x4f, 0x4d, 0x7a,
+	0x67, 0xe7, 0x1a, 0x99, 0xa3, 0x6b, 0x72, 0xaa, 0x41, 0x55, 0xef, 0x6d,
+	0x38, 0x16, 0xfc, 0xe3, 0x08, 0xec, 0x93, 0x6b, 0xa0, 0xa9, 0x3d, 0x01,
+	0x6c, 0x16, 0xe9, 0x55, 0x39, 0xd1, 0xf1, 0x27, 0xc4, 0xb5, 0x77, 0x58,
+	0x99, 0xf2, 0x65, 0x8d, 0xb2, 0x9b, 0x83, 0x2c, 0x97, 0x33, 0xf2, 0x47,
+	0xce, 0x15, 0x55, 0x6b, 0x9d, 0x47, 0x5e, 0x12, 0x38, 0xa5, 0x72, 0xb2,
+	0x16, 0x7c, 0x0b, 0xbf, 0xf7, 0xe2, 0xd7, 0xb1, 0x16, 0xa3, 0xea, 0x8c,
+	0x82, 0x7e, 0xae, 0xd9, 0x4c, 0xc1, 0x7f, 0xe8, 0x96, 0x65, 0x16, 0x10,
+	0x0f, 0x53, 0xea, 0x9c, 0x0b, 0xd7, 0xf1, 0x6f, 0x2b, 0xff, 0x2c, 0x15,
+	0xc8, 0xe6, 0x4c, 0x04, 0x74, 0x34, 0x65, 0x9f, 0x86, 0xd2, 0xc3, 0x13,
+	0x0a, 0xf3, 0x1a, 0xe7, 0xe0, 0xb0, 0x96, 0x06, 0x44, 0xce, 0x65, 0x64,
+	0x0e, 0x6b, 0x38, 0xb0, 0x44, 0x1d, 0x50, 0xb6, 0x93, 0xd2, 0x06, 0xd9,
+	0x1f, 0x01, 0xf6, 0x30, 0x4e, 0x51, 0xc6, 0x61, 0xac, 0x8b, 0x5e, 0x09,
+	0x9c, 0x81, 0x8c, 0x4f, 0x01, 0x23, 0x2c, 0xb4, 0xcb, 0xf7, 0x6a, 0xbe,
+	0x4c, 0x2f, 0xf1, 0x5c, 0xbf, 0x3e, 0x35, 0xd2, 0x47, 0x1c, 0x25, 0xd5,
+	0xda, 0x9c, 0xcc, 0x9d, 0x66, 0xce, 0x3e, 0xa9, 0xce, 0x0c, 0x04, 0xd4,
+	0x99, 0x15, 0x37, 0x67, 0x76, 0xbf, 0x5d, 0x8c, 0x59, 0x15, 0xee, 0xb5,
+	0x09, 0x6c, 0x67, 0x18, 0xe3, 0x6e, 0x24, 0x5f, 0x37, 0x57, 0x1d, 0x07,
+	0xbf, 0x97, 0xe7, 0xa3, 0x99, 0xbc, 0xc4, 0x79, 0x76, 0x7a, 0xc2, 0xc6,
+	0xfc, 0x97, 0xe1, 0x3f, 0xe7, 0x4a, 0x3c, 0x27, 0x5d, 0xc0, 0x0a, 0xcb,
+	0xc8, 0xe5, 0x22, 0x73, 0xc6, 0x8f, 0x43, 0x6f, 0xbc, 0x2e, 0x8c, 0x1a,
+	0xf0, 0x03, 0x2b, 0xea, 0xdd, 0xcf, 0xa8, 0xdd, 0x40, 0x0e, 0x1b, 0xd1,
+	0xf6, 0x43, 0xd7, 0x79, 0xb3, 0xcd, 0xb3, 0x07, 0x9e, 0xc5, 0x3f, 0x0b,
+	0x3f, 0x7a, 0x5e, 0xf8, 0x4e, 0xd6, 0xed, 0x26, 0xf3, 0xa5, 0xab, 0xf0,
+	0x7b, 0x99, 0x58, 0x06, 0x36, 0x94, 0x0f, 0x77, 0x80, 0xe7, 0xdf, 0xc4,
+	0xbd, 0x9c, 0xc3, 0x71, 0xa2, 0xf1, 0x15, 0x29, 0x44, 0x02, 0x32, 0x14,
+	0xb9, 0x22, 0x9b, 0xe1, 0xc9, 0x34, 0x79, 0xdd, 0x8a, 0x8e, 0x8a, 0xa6,
+	0xe8, 0x0d, 0xee, 0x86, 0x0d, 0xde, 0x84, 0xbf, 0x6b, 0xf7, 0x72, 0xfd,
+	0x54, 0x91, 0x18, 0xea, 0x59, 0x75, 0xb6, 0xe0, 0xaa, 0xc5, 0x3a, 0x20,
+	0xdf, 0xc5, 0xfe, 0x1f, 0x6a, 0x8c, 0xbb, 0x7b, 0x77, 0xac, 0x43, 0x93,
+	0x3f, 0x77, 0x8e, 0xbb, 0x2c, 0x97, 0x47, 0xd2, 0x69, 0x6b, 0xa1, 0x73,
+	0xd9, 0xa3, 0x73, 0xd6, 0xa3, 0x53, 0xf1, 0xe8, 0x5c, 0x5d, 0xa5, 0xb3,
+	0x07, 0x76, 0xd0, 0x6c, 0x9e, 0x00, 0xde, 0x48, 0xc6, 0x9b, 0xcd, 0x34,
+	0xf2, 0xb2, 0xd9, 0xe1, 0x69, 0xb5, 0xe7, 0xaa, 0x27, 0x46, 0xc7, 0x93,
+	0x96, 0x2b, 0x7f, 0x58, 0x81, 0x4c, 0xc3, 0x1e, 0xf3, 0xe2, 0x62, 0x75,
+	0xee, 0x07, 0xba, 0xfb, 0x85, 0x5d, 0xf0, 0x03, 0x4f, 0x23, 0x96, 0x5c,
+	0x1c, 0x3f, 0x6f, 0x49, 0x7e, 0xdb, 0x27, 0x75, 0xd8, 0x7b, 0x0f, 0xdf,
+	0x27, 0x35, 0xa5, 0xeb, 0xe2, 0x78, 0xb5, 0xf6, 0x34, 0xf2, 0x23, 0xf6,
+	0xdf, 0x4e, 0x0c, 0xb6, 0xab, 0x52, 0x8b, 0xec, 0x3a, 0xcb, 0xfd, 0x21,
+	0xf4, 0xab, 0xd4, 0xba, 0x21, 0xf7, 0x6e, 0x55, 0x57, 0xb9, 0x52, 0x0c,
+	0x41, 0x8f, 0x26, 0x6c, 0x3e, 0x84, 0xb6, 0x30, 0xec, 0xa0, 0x0f, 0xed,
+	0x3f, 0xc7, 0xda, 0x8e, 0xa0, 0x7d, 0xa5, 0x73, 0x5c, 0xe1, 0x58, 0x4b,
+	0xce, 0x39, 0x37, 0x11, 0x73, 0xdf, 0x84, 0x1f, 0x1d, 0x44, 0x9f, 0x61,
+	0xf4, 0xf9, 0x14, 0xc6, 0xe1, 0x3b, 0xcd, 0x1b, 0xf1, 0xd4, 0x00, 0x4f,
+	0x7a, 0x0b, 0x4f, 0x0d, 0xf0, 0x03, 0xdf, 0x79, 0x92, 0x35, 0xe8, 0x61,
+	0x39, 0x5a, 0xe4, 0x19, 0x29, 0xbe, 0x17, 0x6f, 0x4a, 0x00, 0x98, 0xb4,
+	0xed, 0x64, 0x34, 0xdc, 0x50, 0xb5, 0x1e, 0xda, 0xd6, 0x50, 0xbc, 0x2a,
+	0x2a, 0xce, 0x44, 0x8e, 0x22, 0x7e, 0xdd, 0x74, 0xba, 0xe5, 0x75, 0x6f,
+	0xac, 0x15, 0xe1, 0xfe, 0xe5, 0xda, 0xb1, 0x8e, 0x95, 0xae, 0x8d, 0xbf,
+	0x6a, 0x19, 0xde, 0xbc, 0x7a, 0x31, 0xd6, 0xaf, 0xa2, 0xef, 0xb5, 0xf1,
+	0xcb, 0xb5, 0x8d, 0xfa, 0xde, 0x44, 0xdf, 0xb6, 0x96, 0xbe, 0x37, 0xd1,
+	0xaf, 0x1b, 0x71, 0xb0, 0x5b, 0xcd, 0x69, 0x16, 0x7c, 0x5d, 0x2f, 0xaa,
+	0xf7, 0xb4, 0x21, 0x77, 0x8e, 0x69, 0x12, 0x53, 0x67, 0xdc, 0x5a, 0x49,
+	0xd4, 0x8c, 0x68, 0xef, 0xa8, 0xf7, 0x28, 0x1b, 0x18, 0xb3, 0x80, 0x7b,
+	0xe7, 0x27, 0xb4, 0x54, 0x35, 0x87, 0x98, 0xf5, 0x30, 0xf1, 0x53, 0xdc,
+	0x46, 0xcc, 0xac, 0x80, 0x5e, 0xad, 0xd8, 0xe0, 0x79, 0x6a, 0xd8, 0xc5,
+	0x2d, 0xe2, 0xec, 0x87, 0x0d, 0x75, 0xae, 0x21, 0xad, 0x6a, 0x76, 0x95,
+	0xa2, 0x98, 0xc9, 0x11, 0x9e, 0x65, 0xf8, 0x0c, 0xd6, 0xe5, 0x57, 0xd0,
+	0x96, 0x44, 0x7c, 0x3c, 0xa0, 0x25, 0xcf, 0x8f, 0xe3, 0xfa, 0x49, 0x5c,
+	0xc3, 0x1f, 0x2f, 0x64, 0x71, 0xff, 0x49, 0x5c, 0x4f, 0x6b, 0xa9, 0x7a,
+	0x16, 0xd7, 0x4f, 0xe1, 0x7a, 0xca, 0x64, 0x9e, 0xf2, 0xaa, 0x95, 0xd1,
+	0x6c, 0xd0, 0xb2, 0xcf, 0x8f, 0xe3, 0xd3, 0x4a, 0x8f, 0xf7, 0xa0, 0xa7,
+	0x22, 0xf7, 0xda, 0x62, 0xe0, 0x69, 0x9f, 0x96, 0xae, 0x76, 0x81, 0xc6,
+	0x00, 0x9e, 0xa7, 0x4d, 0xed, 0xf7, 0xc6, 0x67, 0xcd, 0xe9, 0x63, 0xaa,
+	0xe6, 0x64, 0x24, 0x32, 0xc0, 0xc9, 0x87, 0x91, 0x07, 0x68, 0x92, 0xb6,
+	0x9e, 0x93, 0x42, 0x1c, 0x7e, 0xa5, 0x6a, 0x48, 0x2a, 0x94, 0xc7, 0xef,
+	0xbc, 0x24, 0x47, 0x71, 0xbf, 0x4a, 0x5b, 0x60, 0xbf, 0x3f, 0x95, 0x42,
+	0x99, 0xb8, 0x9f, 0x75, 0x26, 0xd6, 0xa6, 0x58, 0x5f, 0xca, 0x41, 0x06,
+	0x21, 0xda, 0xef, 0x06, 0x35, 0x31, 0xf7, 0x8c, 0x34, 0xe2, 0xb2, 0x96,
+	0xac, 0x72, 0xdf, 0xaf, 0x91, 0xb9, 0x6c, 0xf1, 0xfd, 0xb1, 0x69, 0xee,
+	0x23, 0x16, 0x8c, 0x04, 0xeb, 0x23, 0xaa, 0xbe, 0x1e, 0x77, 0xf7, 0x07,
+	0x5b, 0xcf, 0xa4, 0xf8, 0xeb, 0x85, 0xe3, 0x7e, 0x0d, 0xcf, 0xbb, 0xf5,
+	0xac, 0x54, 0xfd, 0x9d, 0xba, 0xe0, 0x3b, 0x00, 0xe7, 0xa0, 0x8b, 0xcb,
+	0x2a, 0x37, 0xe6, 0x1e, 0xee, 0xbb, 0xe5, 0x54, 0xc8, 0x61, 0x8a, 0xac,
+	0x91, 0xf9, 0xfb, 0x76, 0xbe, 0x1c, 0xd7, 0xf3, 0x4a, 0x3e, 0x67, 0x40,
+	0x53, 0xe2, 0xf4, 0xbb, 0xd9, 0x10, 0xf7, 0xdf, 0xf8, 0x8c, 0x7c, 0xf3,
+	0x2e, 0xdf, 0xe4, 0x99, 0xf2, 0x38, 0x0c, 0xff, 0xc9, 0xf7, 0x2b, 0x9e,
+	0x93, 0x5c, 0x9c, 0x35, 0x1e, 0x03, 0xb1, 0x31, 0x8f, 0xdf, 0x77, 0xe5,
+	0x37, 0xeb, 0xc9, 0x2f, 0x57, 0xfe, 0x2f, 0x4a, 0x87, 0x15, 0x8b, 0xe3,
+	0xf9, 0xb5, 0x8f, 0xbd, 0x4a, 0x77, 0x15, 0x75, 0x7e, 0xd7, 0x97, 0x81,
+	0x5f, 0xbf, 0xdb, 0xd8, 0xf6, 0xc6, 0x2d, 0xf2, 0xf6, 0x10, 0xcf, 0x43,
+	0x0c, 0xda, 0x42, 0xfe, 0x39, 0x0f, 0xc6, 0x30, 0x7f, 0xaf, 0xd5, 0x9f,
+	0x83, 0x3f, 0xcf, 0xfb, 0x95, 0x0f, 0xf9, 0xfd, 0xe4, 0x16, 0xe9, 0xca,
+	0x98, 0x86, 0xc5, 0xd8, 0xf0, 0xb8, 0xb7, 0x3f, 0xf0, 0x7f, 0x43, 0xce,
+	0xae, 0x2c, 0x02, 0x09, 0x99, 0xf5, 0xde, 0xbf, 0xde, 0xc0, 0x1e, 0xd6,
+	0xef, 0x35, 0x37, 0x32, 0x67, 0xad, 0xbb, 0xf3, 0xae, 0x6c, 0x30, 0xef,
+	0x8a, 0x37, 0xef, 0xea, 0x7d, 0xf2, 0x5b, 0x99, 0xb7, 0x31, 0x67, 0xda,
+	0xdc, 0x46, 0xf6, 0x28, 0xea, 0xdd, 0xb0, 0x15, 0x23, 0x18, 0xb4, 0x9d,
+	0x7b, 0xd5, 0x50, 0x99, 0x57, 0xbb, 0x76, 0x79, 0x16, 0xb1, 0xb0, 0x5c,
+	0x76, 0x73, 0xec, 0xb2, 0xc3, 0x5a, 0xf6, 0xbb, 0xf1, 0xc0, 0x77, 0xb9,
+	0xbe, 0xa8, 0xce, 0xbb, 0xcc, 0x3a, 0x6e, 0xdd, 0xab, 0x5c, 0x6e, 0x8d,
+	0xa9, 0x0f, 0x32, 0x9e, 0x0e, 0xe6, 0x65, 0x82, 0xef, 0x94, 0xe3, 0xfa,
+	0x11, 0xb9, 0xb2, 0xa0, 0xf6, 0xac, 0xbc, 0xbd, 0x21, 0xee, 0xf9, 0xa8,
+	0xfd, 0x6f, 0xf8, 0xb5, 0x49, 0xe5, 0xd7, 0x97, 0x17, 0xd4, 0x3d, 0x17,
+	0x2b, 0x39, 0x13, 0xf0, 0xfb, 0xc8, 0x25, 0xac, 0x07, 0xa4, 0x80, 0x9c,
+	0xfb, 0xac, 0x75, 0x78, 0x0b, 0x71, 0x0e, 0x69, 0x2d, 0x83, 0xd6, 0xe5,
+	0x05, 0xd9, 0xc2, 0x33, 0x25, 0x65, 0xb5, 0xcf, 0xe6, 0xd6, 0xc5, 0xa7,
+	0xc5, 0xff, 0x7f, 0x1d, 0x41, 0x2f, 0x16, 0xf2, 0x5c, 0x0b, 0xdf, 0x73,
+	0xa6, 0xaf, 0x40, 0x1e, 0x34, 0xc1, 0x7d, 0x9c, 0x66, 0xd3, 0xad, 0x9b,
+	0x37, 0xb1, 0x2e, 0xda, 0xf8, 0x0e, 0x05, 0xfe, 0x0e, 0xc3, 0x7e, 0xb0,
+	0x4e, 0x56, 0xdb, 0x79, 0xcd, 0xdc, 0xc3, 0xbf, 0x66, 0x60, 0xfb, 0x3f,
+	0xe8, 0xf3, 0x49, 0x14, 0x38, 0x46, 0x00, 0x00, 0x00 };
+
+static const u32 bnx2_TXP_b09FwData[(0xd0/4) + 1] = {
 	0x00000000, 0x00000014, 0x00000014, 0x00000014, 0x00000014, 0x00000010,
 	0x00000030, 0x00000030, 0x00000000, 0x00000000, 0x00000000, 0x00000010,
 	0x00008000, 0x00000000, 0x00000000, 0x00000000, 0x00008002, 0x00000000,
@@ -4043,42 +4051,42 @@
 	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000000,
 	0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
 	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 };
-static u32 bnx2_TXP_b09FwRodata[(0x30/4) + 1] = {
-	0x08003be8, 0x08003c14, 0x08003c5c, 0x08003c5c, 0x08003ae8, 0x08003b14,
-	0x08003b14, 0x08003c5c, 0x08003c5c, 0x08003c5c, 0x08003b7c, 0x00000000,
+static const u32 bnx2_TXP_b09FwRodata[(0x30/4) + 1] = {
+	0x08004060, 0x0800408c, 0x080040d4, 0x080040d4, 0x08003f60, 0x08003f8c,
+	0x08003f8c, 0x080040d4, 0x080040d4, 0x080040d4, 0x08003ff4, 0x00000000,
 	0x00000000 };
-static u32 bnx2_TXP_b09FwBss[(0xa20/4) + 1] = { 0x0 };
-static u32 bnx2_TXP_b09FwSbss[(0x80/4) + 1] = { 0x0 };
+static const u32 bnx2_TXP_b09FwBss[(0xa20/4) + 1] = { 0x0 };
+static const u32 bnx2_TXP_b09FwSbss[(0x8c/4) + 1] = { 0x0 };
 
 static struct fw_info bnx2_txp_fw_09 = {
-	.ver_major			= 0x1,
-	.ver_minor			= 0x0,
-	.ver_fix			= 0x0,
+	.ver_major			= 0x3,
+	.ver_minor			= 0x4,
+	.ver_fix			= 0x3,
 
 	.start_addr			= 0x08000060,
 
 	.text_addr			= 0x08000000,
-	.text_len			= 0x4194,
+	.text_len			= 0x4634,
 	.text_index			= 0x0,
 	.gz_text			= bnx2_TXP_b09FwText,
 	.gz_text_len			= sizeof(bnx2_TXP_b09FwText),
 
-	.data_addr			= 0x080041e0,
+	.data_addr			= 0x08004680,
 	.data_len			= 0xd0,
 	.data_index			= 0x0,
 	.data				= bnx2_TXP_b09FwData,
 
-	.sbss_addr			= 0x080042b0,
-	.sbss_len			= 0x80,
+	.sbss_addr			= 0x08004750,
+	.sbss_len			= 0x8c,
 	.sbss_index			= 0x0,
 	.sbss				= bnx2_TXP_b09FwSbss,
 
-	.bss_addr			= 0x08004330,
+	.bss_addr			= 0x080047e0,
 	.bss_len			= 0xa20,
 	.bss_index			= 0x0,
 	.bss				= bnx2_TXP_b09FwBss,
 
-	.rodata_addr			= 0x08004198,
+	.rodata_addr			= 0x08004638,
 	.rodata_len			= 0x30,
 	.rodata_index			= 0x0,
 	.rodata				= bnx2_TXP_b09FwRodata,
diff --git a/drivers/net/fec_8xx/fec_main.c b/drivers/net/fec_8xx/fec_main.c
index e824d5d..88efe97 100644
--- a/drivers/net/fec_8xx/fec_main.c
+++ b/drivers/net/fec_8xx/fec_main.c
@@ -19,7 +19,6 @@
 #include <linux/ioport.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
-#include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/netdevice.h>
diff --git a/drivers/net/fec_8xx/fec_mii.c b/drivers/net/fec_8xx/fec_mii.c
index e79700a..b3fa0d6 100644
--- a/drivers/net/fec_8xx/fec_mii.c
+++ b/drivers/net/fec_8xx/fec_mii.c
@@ -19,7 +19,6 @@
 #include <linux/ioport.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
-#include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/netdevice.h>
diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c
index e2ddd61..a4a2a0e 100644
--- a/drivers/net/fs_enet/fs_enet-main.c
+++ b/drivers/net/fs_enet/fs_enet-main.c
@@ -24,7 +24,6 @@
 #include <linux/ioport.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
-#include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/netdevice.h>
diff --git a/drivers/net/fs_enet/mac-fcc.c b/drivers/net/fs_enet/mac-fcc.c
index 8545e84..5603121 100644
--- a/drivers/net/fs_enet/mac-fcc.c
+++ b/drivers/net/fs_enet/mac-fcc.c
@@ -21,7 +21,6 @@
 #include <linux/ioport.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
-#include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/netdevice.h>
diff --git a/drivers/net/fs_enet/mac-fec.c b/drivers/net/fs_enet/mac-fec.c
index cdcfb96..04b4f80 100644
--- a/drivers/net/fs_enet/mac-fec.c
+++ b/drivers/net/fs_enet/mac-fec.c
@@ -21,7 +21,6 @@
 #include <linux/ioport.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
-#include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/netdevice.h>
diff --git a/drivers/net/fs_enet/mac-scc.c b/drivers/net/fs_enet/mac-scc.c
index 65925b5..d0f2898 100644
--- a/drivers/net/fs_enet/mac-scc.c
+++ b/drivers/net/fs_enet/mac-scc.c
@@ -21,7 +21,6 @@
 #include <linux/ioport.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
-#include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/netdevice.h>
diff --git a/drivers/net/fs_enet/mii-bitbang.c b/drivers/net/fs_enet/mii-bitbang.c
index f914478..d384010 100644
--- a/drivers/net/fs_enet/mii-bitbang.c
+++ b/drivers/net/fs_enet/mii-bitbang.c
@@ -22,7 +22,6 @@
 #include <linux/ioport.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
-#include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/netdevice.h>
diff --git a/drivers/net/fs_enet/mii-fec.c b/drivers/net/fs_enet/mii-fec.c
index 235b177..0a563a8 100644
--- a/drivers/net/fs_enet/mii-fec.c
+++ b/drivers/net/fs_enet/mii-fec.c
@@ -21,7 +21,6 @@
 #include <linux/ioport.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
-#include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/netdevice.h>
diff --git a/drivers/net/ibm_emac/ibm_emac_core.c b/drivers/net/ibm_emac/ibm_emac_core.c
index 3d82d46..50035eb 100644
--- a/drivers/net/ibm_emac/ibm_emac_core.c
+++ b/drivers/net/ibm_emac/ibm_emac_core.c
@@ -27,7 +27,6 @@
 #include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/types.h>
-#include <linux/pci.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
diff --git a/drivers/net/ixgb/ixgb_osdep.h b/drivers/net/ixgb/ixgb_osdep.h
index 8434d75..9e04a6b 100644
--- a/drivers/net/ixgb/ixgb_osdep.h
+++ b/drivers/net/ixgb/ixgb_osdep.h
@@ -34,7 +34,6 @@
 #define _IXGB_OSDEP_H_
 
 #include <linux/types.h>
-#include <linux/pci.h>
 #include <linux/delay.h>
 #include <asm/io.h>
 #include <linux/interrupt.h>
diff --git a/drivers/net/jazzsonic.c b/drivers/net/jazzsonic.c
index d34afb5..75f6f44 100644
--- a/drivers/net/jazzsonic.c
+++ b/drivers/net/jazzsonic.c
@@ -88,6 +88,23 @@
 	0xffff			/* end of list */
 };
 
+static int jazzsonic_open(struct net_device* dev)
+{
+	if (request_irq(dev->irq, &sonic_interrupt, IRQF_DISABLED, "sonic", dev)) {
+		printk(KERN_ERR "%s: unable to get IRQ %d.\n", dev->name, dev->irq);
+		return -EAGAIN;
+	}
+	return sonic_open(dev);
+}
+
+static int jazzsonic_close(struct net_device* dev)
+{
+	int err;
+	err = sonic_close(dev);
+	free_irq(dev->irq, dev);
+	return err;
+}
+
 static int __init sonic_probe1(struct net_device *dev)
 {
 	static unsigned version_printed;
@@ -169,8 +186,8 @@
 	lp->rra_laddr = lp->rda_laddr + (SIZEOF_SONIC_RD * SONIC_NUM_RDS
 	                     * SONIC_BUS_SCALE(lp->dma_bitmode));
 
-	dev->open = sonic_open;
-	dev->stop = sonic_close;
+	dev->open = jazzsonic_open;
+	dev->stop = jazzsonic_close;
 	dev->hard_start_xmit = sonic_send_packet;
 	dev->get_stats = sonic_get_stats;
 	dev->set_multicast_list = &sonic_multicast_list;
@@ -260,8 +277,6 @@
 module_param(sonic_debug, int, 0);
 MODULE_PARM_DESC(sonic_debug, "jazzsonic debug level (1-4)");
 
-#define SONIC_IRQ_FLAG IRQF_DISABLED
-
 #include "sonic.c"
 
 static int __devexit jazz_sonic_device_remove (struct platform_device *pdev)
@@ -269,11 +284,11 @@
 	struct net_device *dev = platform_get_drvdata(pdev);
 	struct sonic_local* lp = netdev_priv(dev);
 
-	unregister_netdev (dev);
+	unregister_netdev(dev);
 	dma_free_coherent(lp->device, SIZEOF_SONIC_DESC * SONIC_BUS_SCALE(lp->dma_bitmode),
 	                  lp->descriptors, lp->descriptors_laddr);
 	release_region (dev->base_addr, SONIC_MEM_SIZE);
-	free_netdev (dev);
+	free_netdev(dev);
 
 	return 0;
 }
diff --git a/drivers/net/lasi_82596.c b/drivers/net/lasi_82596.c
index 0edcd12..6b49fc4 100644
--- a/drivers/net/lasi_82596.c
+++ b/drivers/net/lasi_82596.c
@@ -81,7 +81,6 @@
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/init.h>
-#include <linux/pci.h>
 #include <linux/types.h>
 #include <linux/bitops.h>
 
diff --git a/drivers/net/mac8390.c b/drivers/net/mac8390.c
index a12bb64..90b0c3e 100644
--- a/drivers/net/mac8390.c
+++ b/drivers/net/mac8390.c
@@ -14,6 +14,8 @@
 /* 2001-05-15: support for Cabletron ported from old daynaport driver
  * and fixed access to Sonic Sys card which masquerades as a Farallon
  * by rayk@knightsmanor.org */
+/* 2002-12-30: Try to support more cards, some clues from NetBSD driver */
+/* 2003-12-26: Make sure Asante cards always work. */
 
 #include <linux/module.h>
 #include <linux/kernel.h>
@@ -61,25 +63,21 @@
 #define DAYNA_8390_BASE		0x80000
 #define DAYNA_8390_MEM		0x00000
 
-#define KINETICS_8390_BASE	0x80000
-#define KINETICS_8390_MEM	0x00000
-
 #define CABLETRON_8390_BASE	0x90000
 #define CABLETRON_8390_MEM	0x00000
 
+#define INTERLAN_8390_BASE	0xE0000
+#define INTERLAN_8390_MEM	0xD0000
+
 enum mac8390_type {
 	MAC8390_NONE = -1,
 	MAC8390_APPLE,
 	MAC8390_ASANTE,
-	MAC8390_FARALLON,  /* Apple, Asante, and Farallon are all compatible */
+	MAC8390_FARALLON,
 	MAC8390_CABLETRON,
 	MAC8390_DAYNA,
 	MAC8390_INTERLAN,
 	MAC8390_KINETICS,
-	MAC8390_FOCUS,
-	MAC8390_SONICSYS,
-	MAC8390_DAYNA2,
-	MAC8390_DAYNA3,
 };
 
 static const char * cardname[] = {
@@ -90,10 +88,6 @@
 	"dayna",
 	"interlan",
 	"kinetics",
-	"focus",
-	"sonic systems",
-	"dayna2",
-	"dayna_lc",
 };
 
 static int word16[] = {
@@ -104,10 +98,6 @@
 	0, /* dayna */
 	1, /* interlan */
 	0, /* kinetics */
-	1, /* focus (??) */
-	1, /* sonic systems  */
-	1, /* dayna2 */
-	1, /* dayna-lc */
 };
 
 /* on which cards do we use NuBus resources? */
@@ -119,10 +109,12 @@
 	0, /* dayna */
 	0, /* interlan */
 	0, /* kinetics */
-	0, /* focus (??) */
-	1, /* sonic systems */
-	1, /* dayna2 */
-	1, /* dayna-lc */
+};
+
+enum mac8390_access {
+	ACCESS_UNKNOWN = 0,
+	ACCESS_32,
+	ACCESS_16,
 };
 
 extern enum mac8390_type mac8390_ident(struct nubus_dev * dev);
@@ -134,8 +126,9 @@
 static int mac8390_open(struct net_device * dev);
 static int mac8390_close(struct net_device * dev);
 static void mac8390_no_reset(struct net_device *dev);
+static void interlan_reset(struct net_device *dev);
 
-/* Sane (32-bit chunk memory read/write) - Apple/Asante/Farallon do this*/
+/* Sane (32-bit chunk memory read/write) - Some Farallon and Apple do this*/
 static void sane_get_8390_hdr(struct net_device *dev,
 			      struct e8390_pkt_hdr *hdr, int ring_page);
 static void sane_block_input(struct net_device * dev, int count,
@@ -172,23 +165,93 @@
 
 enum mac8390_type __init mac8390_ident(struct nubus_dev * dev)
 {
-	if (dev->dr_sw == NUBUS_DRSW_ASANTE)
-		return MAC8390_ASANTE;
-	if (dev->dr_sw == NUBUS_DRSW_FARALLON)
-		return MAC8390_FARALLON;
-	if (dev->dr_sw == NUBUS_DRSW_KINETICS)
-		return MAC8390_KINETICS;
-	if (dev->dr_sw == NUBUS_DRSW_DAYNA)
-		return MAC8390_DAYNA;
-	if (dev->dr_sw == NUBUS_DRSW_DAYNA2)
-		return MAC8390_DAYNA2;
-	if (dev->dr_sw == NUBUS_DRSW_DAYNA_LC)
-		return MAC8390_DAYNA3;
-	if (dev->dr_hw == NUBUS_DRHW_CABLETRON)
-		return MAC8390_CABLETRON;
+	switch (dev->dr_sw) {
+		case NUBUS_DRSW_3COM:
+			switch (dev->dr_hw) {
+				case NUBUS_DRHW_APPLE_SONIC_NB:
+				case NUBUS_DRHW_APPLE_SONIC_LC:
+				case NUBUS_DRHW_SONNET:
+					return MAC8390_NONE;
+					break;
+				default:
+					return MAC8390_APPLE;
+					break;
+			}
+			break;
+
+		case NUBUS_DRSW_APPLE:
+			switch (dev->dr_hw) {
+				case NUBUS_DRHW_ASANTE_LC:
+					return MAC8390_NONE;
+					break;
+				case NUBUS_DRHW_CABLETRON:
+					return MAC8390_CABLETRON;
+					break;
+				default:
+					return MAC8390_APPLE;
+					break;
+			}
+			break;
+
+		case NUBUS_DRSW_ASANTE:
+			return MAC8390_ASANTE;
+			break;
+
+		case NUBUS_DRSW_TECHWORKS:
+		case NUBUS_DRSW_DAYNA2:
+		case NUBUS_DRSW_DAYNA_LC:
+			if (dev->dr_hw == NUBUS_DRHW_CABLETRON)
+				return MAC8390_CABLETRON;
+			else
+				return MAC8390_APPLE;
+			break;
+
+		case NUBUS_DRSW_FARALLON:
+			return MAC8390_FARALLON;
+			break;
+
+		case NUBUS_DRSW_KINETICS:
+			switch (dev->dr_hw) {
+				case NUBUS_DRHW_INTERLAN:
+					return MAC8390_INTERLAN;
+					break;
+				default:
+					return MAC8390_KINETICS;
+					break;
+			}
+			break;
+
+		case NUBUS_DRSW_DAYNA:
+			// These correspond to Dayna Sonic cards
+			// which use the macsonic driver
+			if (dev->dr_hw == NUBUS_DRHW_SMC9194 ||
+				dev->dr_hw == NUBUS_DRHW_INTERLAN )
+				return MAC8390_NONE;
+			else
+				return MAC8390_DAYNA;
+			break;
+	}
 	return MAC8390_NONE;
 }
 
+enum mac8390_access __init mac8390_testio(volatile unsigned long membase)
+{
+	unsigned long outdata = 0xA5A0B5B0;
+	unsigned long indata =  0x00000000;
+	/* Try writing 32 bits */
+	memcpy((char *)membase, (char *)&outdata, 4);
+	/* Now compare them */
+	if (memcmp((char *)&outdata, (char *)membase, 4) == 0)
+		return ACCESS_32;
+	/* Write 16 bit output */
+	word_memcpy_tocard((char *)membase, (char *)&outdata, 4);
+	/* Now read it back */
+	word_memcpy_fromcard((char *)&indata, (char *)membase, 4);
+	if (outdata == indata)
+		return ACCESS_16;
+	return ACCESS_UNKNOWN;
+}
+
 int __init mac8390_memsize(unsigned long membase)
 {
 	unsigned long flags;
@@ -287,14 +350,6 @@
 			continue;
 		} else {
 			nubus_get_rsrc_mem(dev->dev_addr, &ent, 6);
-			/* Some Sonic Sys cards masquerade as Farallon */
-			if (cardtype == MAC8390_FARALLON &&
-					dev->dev_addr[0] == 0x0 &&
-					dev->dev_addr[1] == 0x40 &&
-					dev->dev_addr[2] == 0x10) {
-				/* This is really Sonic Sys card */
-				cardtype = MAC8390_SONICSYS;
-			}
 		}
 
 		if (useresources[cardtype] == 1) {
@@ -334,6 +389,17 @@
 						dev->mem_start +
 						mac8390_memsize(dev->mem_start);
 					break;
+				case MAC8390_INTERLAN:
+					dev->base_addr =
+						(int)(ndev->board->slot_addr +
+						INTERLAN_8390_BASE);
+					dev->mem_start =
+						(int)(ndev->board->slot_addr +
+						INTERLAN_8390_MEM);
+					dev->mem_end =
+						dev->mem_start +
+						mac8390_memsize(dev->mem_start);
+					break;
 				case MAC8390_CABLETRON:
 					dev->base_addr =
 						(int)(ndev->board->slot_addr +
@@ -356,8 +422,8 @@
 
 				default:
 					printk(KERN_ERR "Card type %s is"
-							" unsupported, sorry\n",
-					       cardname[cardtype]);
+					       " unsupported, sorry\n",
+					       ndev->board->name);
 					continue;
 			}
 		}
@@ -438,7 +504,7 @@
 		24,    26,     28,     30
 	};
 
-	int access_bitmode;
+	int access_bitmode = 0;
 
 	/* Now fill in our stuff */
 	dev->open = &mac8390_open;
@@ -468,29 +534,47 @@
 
 	/* Fill in model-specific information and functions */
 	switch(type) {
-	case MAC8390_SONICSYS:
-		/* 16 bit card, register map is reversed */
+	case MAC8390_FARALLON:
+	case MAC8390_APPLE:
+		switch(mac8390_testio(dev->mem_start)) {
+			case ACCESS_UNKNOWN:
+				printk("Don't know how to access card memory!\n");
+				return -ENODEV;
+				break;
+
+			case ACCESS_16:
+				/* 16 bit card, register map is reversed */
+				ei_status.reset_8390 = &mac8390_no_reset;
+				ei_status.block_input = &slow_sane_block_input;
+				ei_status.block_output = &slow_sane_block_output;
+				ei_status.get_8390_hdr = &slow_sane_get_8390_hdr;
+				ei_status.reg_offset = back4_offsets;
+				break;
+
+			case ACCESS_32:
+				/* 32 bit card, register map is reversed */
+				ei_status.reset_8390 = &mac8390_no_reset;
+				ei_status.block_input = &sane_block_input;
+				ei_status.block_output = &sane_block_output;
+				ei_status.get_8390_hdr = &sane_get_8390_hdr;
+				ei_status.reg_offset = back4_offsets;
+				access_bitmode = 1;
+				break;
+		}
+		break;
+
+	case MAC8390_ASANTE:
+		/* Some Asante cards pass the 32 bit test
+		 * but overwrite system memory when run at 32 bit.
+		 * so we run them all at 16 bit.
+		 */
 		ei_status.reset_8390 = &mac8390_no_reset;
 		ei_status.block_input = &slow_sane_block_input;
 		ei_status.block_output = &slow_sane_block_output;
 		ei_status.get_8390_hdr = &slow_sane_get_8390_hdr;
 		ei_status.reg_offset = back4_offsets;
-		access_bitmode = 0;
 		break;
-	case MAC8390_FARALLON:
-	case MAC8390_APPLE:
-	case MAC8390_ASANTE:
-	case MAC8390_DAYNA2:
-	case MAC8390_DAYNA3:
-		/* 32 bit card, register map is reversed */
-		/* sane */
-		ei_status.reset_8390 = &mac8390_no_reset;
-		ei_status.block_input = &sane_block_input;
-		ei_status.block_output = &sane_block_output;
-		ei_status.get_8390_hdr = &sane_get_8390_hdr;
-		ei_status.reg_offset = back4_offsets;
-		access_bitmode = 1;
-		break;
+
 	case MAC8390_CABLETRON:
 		/* 16 bit card, register map is short forward */
 		ei_status.reset_8390 = &mac8390_no_reset;
@@ -498,21 +582,30 @@
 		ei_status.block_output = &slow_sane_block_output;
 		ei_status.get_8390_hdr = &slow_sane_get_8390_hdr;
 		ei_status.reg_offset = fwrd2_offsets;
-		access_bitmode = 0;
 		break;
+
 	case MAC8390_DAYNA:
 	case MAC8390_KINETICS:
-		/* 16 bit memory */
+		/* 16 bit memory, register map is forward */
 		/* dayna and similar */
 		ei_status.reset_8390 = &mac8390_no_reset;
 		ei_status.block_input = &dayna_block_input;
 		ei_status.block_output = &dayna_block_output;
 		ei_status.get_8390_hdr = &dayna_get_8390_hdr;
 		ei_status.reg_offset = fwrd4_offsets;
-		access_bitmode = 0;
 		break;
+
+	case MAC8390_INTERLAN:
+		/* 16 bit memory, register map is forward */
+		ei_status.reset_8390 = &interlan_reset;
+		ei_status.block_input = &slow_sane_block_input;
+		ei_status.block_output = &slow_sane_block_output;
+		ei_status.get_8390_hdr = &slow_sane_get_8390_hdr;
+	        ei_status.reg_offset = fwrd4_offsets;
+	        break;
+
 	default:
-		printk(KERN_ERR "Card type %s is unsupported, sorry\n", cardname[type]);
+		printk(KERN_ERR "Card type %s is unsupported, sorry\n", ndev->board->name);
 		return -ENODEV;
 	}
 
@@ -530,9 +623,9 @@
 				printk(":");
 		}
 	}
-	printk(" IRQ %d, shared memory at %#lx-%#lx,  %d-bit access.\n",
-		   dev->irq, dev->mem_start, dev->mem_end-1,
-		   access_bitmode?32:16);
+	printk(" IRQ %d, %d KB shared memory at %#lx,  %d-bit access.\n",
+		   dev->irq, (int)((dev->mem_end - dev->mem_start)/0x1000) * 4,
+		   dev->mem_start, access_bitmode?32:16);
 	return 0;
 }
 
@@ -561,6 +654,18 @@
 	return;
 }
 
+static void interlan_reset(struct net_device *dev)
+{
+	unsigned char *target=nubus_slot_addr(IRQ2SLOT(dev->irq));
+	if (ei_debug > 1)
+		printk("Need to reset the NS8390 t=%lu...", jiffies);
+	ei_status.txing = 0;
+	target[0xC0000] = 0;
+	if (ei_debug > 1)
+		printk("reset complete\n");
+	return;
+}
+
 /* dayna_memcpy_fromio/dayna_memcpy_toio */
 /* directly from daynaport.c by Alan Cox */
 static void dayna_memcpy_fromcard(struct net_device *dev, void *to, int from, int count)
diff --git a/drivers/net/mac89x0.c b/drivers/net/mac89x0.c
index 90e695d..26a3b45 100644
--- a/drivers/net/mac89x0.c
+++ b/drivers/net/mac89x0.c
@@ -128,7 +128,7 @@
 extern void reset_chip(struct net_device *dev);
 #endif
 static int net_open(struct net_device *dev);
-static int	net_send_packet(struct sk_buff *skb, 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);
 static void set_multicast_list(struct net_device *dev);
 static void net_rx(struct net_device *dev);
@@ -374,56 +374,39 @@
 static int
 net_send_packet(struct sk_buff *skb, struct net_device *dev)
 {
-	if (dev->tbusy) {
-		/* If we get here, some higher level has decided we are broken.
-		   There should really be a "kick me" function call instead. */
-		int tickssofar = jiffies - dev->trans_start;
-		if (tickssofar < 5)
-			return 1;
-		if (net_debug > 0) printk("%s: transmit timed out, %s?\n", dev->name,
-			   tx_done(dev) ? "IRQ conflict" : "network cable problem");
-		/* Try to restart the adaptor. */
-		dev->tbusy=0;
-		dev->trans_start = jiffies;
-	}
+	struct net_local *lp = netdev_priv(dev);
+	unsigned long flags;
 
-	/* Block a timer-based transmit from overlapping.  This could better be
-	   done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
-	if (test_and_set_bit(0, (void*)&dev->tbusy) != 0)
-		printk("%s: Transmitter access conflict.\n", dev->name);
-	else {
-		struct net_local *lp = netdev_priv(dev);
-		unsigned long flags;
+	if (net_debug > 3)
+		printk("%s: sent %d byte packet of type %x\n",
+		       dev->name, skb->len,
+		       (skb->data[ETH_ALEN+ETH_ALEN] << 8)
+		       | skb->data[ETH_ALEN+ETH_ALEN+1]);
 
-		if (net_debug > 3)
-			printk("%s: sent %d byte packet of type %x\n",
-			       dev->name, skb->len,
-			       (skb->data[ETH_ALEN+ETH_ALEN] << 8)
-			       | skb->data[ETH_ALEN+ETH_ALEN+1]);
+	/* keep the upload from being interrupted, since we
+	   ask the chip to start transmitting before the
+	   whole packet has been completely uploaded. */
+	local_irq_save(flags);
+	netif_stop_queue(dev);
 
-		/* keep the upload from being interrupted, since we
-                   ask the chip to start transmitting before the
-                   whole packet has been completely uploaded. */
-		local_irq_save(flags);
+	/* initiate a transmit sequence */
+	writereg(dev, PP_TxCMD, lp->send_cmd);
+	writereg(dev, PP_TxLength, skb->len);
 
-		/* initiate a transmit sequence */
-		writereg(dev, PP_TxCMD, lp->send_cmd);
-		writereg(dev, PP_TxLength, skb->len);
-
-		/* Test to see if the chip has allocated memory for the packet */
-		if ((readreg(dev, PP_BusST) & READY_FOR_TX_NOW) == 0) {
-			/* Gasp!  It hasn't.  But that shouldn't happen since
-			   we're waiting for TxOk, so return 1 and requeue this packet. */
-			local_irq_restore(flags);
-			return 1;
-		}
-
-		/* Write the contents of the packet */
-		memcpy_toio(dev->mem_start + PP_TxFrame, skb->data, skb->len+1);
-
+	/* Test to see if the chip has allocated memory for the packet */
+	if ((readreg(dev, PP_BusST) & READY_FOR_TX_NOW) == 0) {
+		/* Gasp!  It hasn't.  But that shouldn't happen since
+		   we're waiting for TxOk, so return 1 and requeue this packet. */
 		local_irq_restore(flags);
-		dev->trans_start = jiffies;
+		return 1;
 	}
+
+	/* Write the contents of the packet */
+	skb_copy_from_linear_data(skb, (void *)(dev->mem_start + PP_TxFrame),
+				  skb->len+1);
+
+	local_irq_restore(flags);
+	dev->trans_start = jiffies;
 	dev_kfree_skb (skb);
 
 	return 0;
@@ -441,9 +424,6 @@
 		printk ("net_interrupt(): irq %d for unknown device.\n", irq);
 		return IRQ_NONE;
 	}
-	if (dev->interrupt)
-		printk("%s: Re-entering the interrupt handler.\n", dev->name);
-	dev->interrupt = 1;
 
 	ioaddr = dev->base_addr;
 	lp = netdev_priv(dev);
@@ -464,8 +444,7 @@
 			break;
 		case ISQ_TRANSMITTER_EVENT:
 			lp->stats.tx_packets++;
-			dev->tbusy = 0;
-			mark_bh(NET_BH);	/* Inform upper layers. */
+			netif_wake_queue(dev);
 			if ((status & TX_OK) == 0) lp->stats.tx_errors++;
 			if (status & TX_LOST_CRS) lp->stats.tx_carrier_errors++;
 			if (status & TX_SQE_ERROR) lp->stats.tx_heartbeat_errors++;
@@ -479,8 +458,7 @@
                                    That shouldn't happen since we only ever
                                    load one packet.  Shrug.  Do the right
                                    thing anyway. */
-				dev->tbusy = 0;
-				mark_bh(NET_BH);	/* Inform upper layers. */
+				netif_wake_queue(dev);
 			}
 			if (status & TX_UNDERRUN) {
 				if (net_debug > 0) printk("%s: transmit underrun\n", dev->name);
@@ -497,7 +475,6 @@
 			break;
 		}
 	}
-	dev->interrupt = 0;
 	return IRQ_HANDLED;
 }
 
@@ -531,7 +508,8 @@
 	}
 	skb_put(skb, length);
 
-	memcpy_fromio(skb->data, dev->mem_start + PP_RxFrame, length);
+	skb_copy_to_linear_data(skb, (void *)(dev->mem_start + PP_RxFrame),
+				length);
 
 	if (net_debug > 3)printk("%s: received %d byte packet of type %x\n",
                                  dev->name, length,
@@ -610,8 +588,6 @@
 static int set_mac_address(struct net_device *dev, void *addr)
 {
 	int i;
-	if (dev->start)
-		return -EBUSY;
 	printk("%s: Setting MAC address to ", dev->name);
 	for (i = 0; i < 6; i++)
 		printk(" %2.2x", dev->dev_addr[i] = ((unsigned char *)addr)[i]);
diff --git a/drivers/net/macmace.c b/drivers/net/macmace.c
index 27911c0..fef3193 100644
--- a/drivers/net/macmace.c
+++ b/drivers/net/macmace.c
@@ -12,6 +12,11 @@
  *	Copyright (C) 1998 Alan Cox <alan@redhat.com>
  *
  *	Modified heavily by Joshua M. Thompson based on Dave Huang's NetBSD driver
+ *
+ *	Copyright (C) 2007 Finn Thain
+ *
+ *	Converted to DMA API, converted to unified driver model,
+ *	sync'd some routines with mace.c and fixed various bugs.
  */
 
 
@@ -23,8 +28,9 @@
 #include <linux/string.h>
 #include <linux/crc32.h>
 #include <linux/bitrev.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
 #include <asm/io.h>
-#include <asm/pgtable.h>
 #include <asm/irq.h>
 #include <asm/macintosh.h>
 #include <asm/macints.h>
@@ -32,13 +38,20 @@
 #include <asm/page.h>
 #include "mace.h"
 
-#define N_TX_RING	1
-#define N_RX_RING	8
-#define N_RX_PAGES	((N_RX_RING * 0x0800 + PAGE_SIZE - 1) / PAGE_SIZE)
+static char mac_mace_string[] = "macmace";
+static struct platform_device *mac_mace_device;
+
+#define N_TX_BUFF_ORDER	0
+#define N_TX_RING	(1 << N_TX_BUFF_ORDER)
+#define N_RX_BUFF_ORDER	3
+#define N_RX_RING	(1 << N_RX_BUFF_ORDER)
+
 #define TX_TIMEOUT	HZ
 
-/* Bits in transmit DMA status */
-#define TX_DMA_ERR	0x80
+#define MACE_BUFF_SIZE	0x800
+
+/* Chip rev needs workaround on HW & multicast addr change */
+#define BROKEN_ADDRCHG_REV	0x0941
 
 /* The MACE is simply wired down on a Mac68K box */
 
@@ -47,40 +60,46 @@
 
 struct mace_data {
 	volatile struct mace *mace;
-	volatile unsigned char *tx_ring;
-	volatile unsigned char *tx_ring_phys;
-	volatile unsigned char *rx_ring;
-	volatile unsigned char *rx_ring_phys;
+	unsigned char *tx_ring;
+	dma_addr_t tx_ring_phys;
+	unsigned char *rx_ring;
+	dma_addr_t rx_ring_phys;
 	int dma_intr;
 	struct net_device_stats stats;
 	int rx_slot, rx_tail;
 	int tx_slot, tx_sloti, tx_count;
+	int chipid;
+	struct device *device;
 };
 
 struct mace_frame {
-	u16	len;
-	u16	status;
-	u16	rntpc;
-	u16	rcvcc;
-	u32	pad1;
-	u32	pad2;
+	u8	rcvcnt;
+	u8	pad1;
+	u8	rcvsts;
+	u8	pad2;
+	u8	rntpc;
+	u8	pad3;
+	u8	rcvcc;
+	u8	pad4;
+	u32	pad5;
+	u32	pad6;
 	u8	data[1];
 	/* And frame continues.. */
 };
 
 #define PRIV_BYTES	sizeof(struct mace_data)
 
-extern void psc_debug_dump(void);
-
 static int mace_open(struct net_device *dev);
 static int mace_close(struct net_device *dev);
 static int mace_xmit_start(struct sk_buff *skb, struct net_device *dev);
 static struct net_device_stats *mace_stats(struct net_device *dev);
 static void mace_set_multicast(struct net_device *dev);
 static int mace_set_address(struct net_device *dev, void *addr);
+static void mace_reset(struct net_device *dev);
 static irqreturn_t mace_interrupt(int irq, void *dev_id);
 static irqreturn_t mace_dma_intr(int irq, void *dev_id);
 static void mace_tx_timeout(struct net_device *dev);
+static void __mace_set_address(struct net_device *dev, void *addr);
 
 /*
  * Load a receive DMA channel with a base address and ring length
@@ -88,7 +107,7 @@
 
 static void mace_load_rxdma_base(struct net_device *dev, int set)
 {
-	struct mace_data *mp = (struct mace_data *) dev->priv;
+	struct mace_data *mp = netdev_priv(dev);
 
 	psc_write_word(PSC_ENETRD_CMD + set, 0x0100);
 	psc_write_long(PSC_ENETRD_ADDR + set, (u32) mp->rx_ring_phys);
@@ -103,7 +122,7 @@
 
 static void mace_rxdma_reset(struct net_device *dev)
 {
-	struct mace_data *mp = (struct mace_data *) dev->priv;
+	struct mace_data *mp = netdev_priv(dev);
 	volatile struct mace *mace = mp->mace;
 	u8 maccc = mace->maccc;
 
@@ -130,7 +149,7 @@
 
 static void mace_txdma_reset(struct net_device *dev)
 {
-	struct mace_data *mp = (struct mace_data *) dev->priv;
+	struct mace_data *mp = netdev_priv(dev);
 	volatile struct mace *mace = mp->mace;
 	u8 maccc;
 
@@ -168,7 +187,7 @@
  * model of Macintrash has a MACE (AV macintoshes)
  */
 
-struct net_device *mace_probe(int unit)
+static int __devinit mace_probe(struct platform_device *pdev)
 {
 	int j;
 	struct mace_data *mp;
@@ -179,24 +198,28 @@
 	int err;
 
 	if (found || macintosh_config->ether_type != MAC_ETHER_MACE)
-		return ERR_PTR(-ENODEV);
+		return -ENODEV;
 
 	found = 1;	/* prevent 'finding' one on every device probe */
 
 	dev = alloc_etherdev(PRIV_BYTES);
 	if (!dev)
-		return ERR_PTR(-ENOMEM);
+		return -ENOMEM;
 
-	if (unit >= 0)
-		sprintf(dev->name, "eth%d", unit);
+	mp = netdev_priv(dev);
 
-	mp = (struct mace_data *) dev->priv;
+	mp->device = &pdev->dev;
+	SET_NETDEV_DEV(dev, &pdev->dev);
+ 	SET_MODULE_OWNER(dev);
+
 	dev->base_addr = (u32)MACE_BASE;
 	mp->mace = (volatile struct mace *) MACE_BASE;
 
 	dev->irq = IRQ_MAC_MACE;
 	mp->dma_intr = IRQ_MAC_MACE_DMA;
 
+	mp->chipid = mp->mace->chipid_hi << 8 | mp->mace->chipid_lo;
+
 	/*
 	 * The PROM contains 8 bytes which total 0xFF when XOR'd
 	 * together. Due to the usual peculiar apple brain damage
@@ -217,7 +240,7 @@
 
 	if (checksum != 0xFF) {
 		free_netdev(dev);
-		return ERR_PTR(-ENODEV);
+		return -ENODEV;
 	}
 
 	memset(&mp->stats, 0, sizeof(mp->stats));
@@ -237,22 +260,98 @@
 
 	err = register_netdev(dev);
 	if (!err)
-		return dev;
+		return 0;
 
 	free_netdev(dev);
-	return ERR_PTR(err);
+	return err;
+}
+
+/*
+ * Reset the chip.
+ */
+
+static void mace_reset(struct net_device *dev)
+{
+	struct mace_data *mp = netdev_priv(dev);
+	volatile struct mace *mb = mp->mace;
+	int i;
+
+	/* soft-reset the chip */
+	i = 200;
+	while (--i) {
+		mb->biucc = SWRST;
+		if (mb->biucc & SWRST) {
+			udelay(10);
+			continue;
+		}
+		break;
+	}
+	if (!i) {
+		printk(KERN_ERR "macmace: cannot reset chip!\n");
+		return;
+	}
+
+	mb->maccc = 0;	/* turn off tx, rx */
+	mb->imr = 0xFF;	/* disable all intrs for now */
+	i = mb->ir;
+
+	mb->biucc = XMTSP_64;
+	mb->utr = RTRD;
+	mb->fifocc = XMTFW_8 | RCVFW_64 | XMTFWU | RCVFWU;
+
+	mb->xmtfc = AUTO_PAD_XMIT; /* auto-pad short frames */
+	mb->rcvfc = 0;
+
+	/* load up the hardware address */
+	__mace_set_address(dev, dev->dev_addr);
+
+	/* clear the multicast filter */
+	if (mp->chipid == BROKEN_ADDRCHG_REV)
+		mb->iac = LOGADDR;
+	else {
+		mb->iac = ADDRCHG | LOGADDR;
+		while ((mb->iac & ADDRCHG) != 0)
+			;
+	}
+	for (i = 0; i < 8; ++i)
+		mb->ladrf = 0;
+
+	/* done changing address */
+	if (mp->chipid != BROKEN_ADDRCHG_REV)
+		mb->iac = 0;
+
+	mb->plscc = PORTSEL_AUI;
 }
 
 /*
  * Load the address on a mace controller.
  */
 
+static void __mace_set_address(struct net_device *dev, void *addr)
+{
+	struct mace_data *mp = netdev_priv(dev);
+	volatile struct mace *mb = mp->mace;
+	unsigned char *p = addr;
+	int i;
+
+	/* load up the hardware address */
+	if (mp->chipid == BROKEN_ADDRCHG_REV)
+		mb->iac = PHYADDR;
+	else {
+		mb->iac = ADDRCHG | PHYADDR;
+		while ((mb->iac & ADDRCHG) != 0)
+			;
+	}
+	for (i = 0; i < 6; ++i)
+		mb->padr = dev->dev_addr[i] = p[i];
+	if (mp->chipid != BROKEN_ADDRCHG_REV)
+		mb->iac = 0;
+}
+
 static int mace_set_address(struct net_device *dev, void *addr)
 {
-	unsigned char *p = addr;
-	struct mace_data *mp = (struct mace_data *) dev->priv;
+	struct mace_data *mp = netdev_priv(dev);
 	volatile struct mace *mb = mp->mace;
-	int i;
 	unsigned long flags;
 	u8 maccc;
 
@@ -260,15 +359,10 @@
 
 	maccc = mb->maccc;
 
-	/* load up the hardware address */
-	mb->iac = ADDRCHG | PHYADDR;
-	while ((mb->iac & ADDRCHG) != 0);
-
-	for (i = 0; i < 6; ++i) {
-		mb->padr = dev->dev_addr[i] = p[i];
-	}
+	__mace_set_address(dev, addr);
 
 	mb->maccc = maccc;
+
 	local_irq_restore(flags);
 
 	return 0;
@@ -281,31 +375,11 @@
 
 static int mace_open(struct net_device *dev)
 {
-	struct mace_data *mp = (struct mace_data *) dev->priv;
+	struct mace_data *mp = netdev_priv(dev);
 	volatile struct mace *mb = mp->mace;
-#if 0
-	int i;
 
-	i = 200;
-	while (--i) {
-		mb->biucc = SWRST;
-		if (mb->biucc & SWRST) {
-			udelay(10);
-			continue;
-		}
-		break;
-	}
-	if (!i) {
-		printk(KERN_ERR "%s: software reset failed!!\n", dev->name);
-		return -EAGAIN;
-	}
-#endif
-
-	mb->biucc = XMTSP_64;
-	mb->fifocc = XMTFW_16 | RCVFW_64 | XMTFWU | RCVFWU | XMTBRST | RCVBRST;
-	mb->xmtfc = AUTO_PAD_XMIT;
-	mb->plscc = PORTSEL_AUI;
-	/* mb->utr = RTRD; */
+	/* reset the chip */
+	mace_reset(dev);
 
 	if (request_irq(dev->irq, mace_interrupt, 0, dev->name, dev)) {
 		printk(KERN_ERR "%s: can't get irq %d\n", dev->name, dev->irq);
@@ -319,25 +393,21 @@
 
 	/* Allocate the DMA ring buffers */
 
-	mp->rx_ring = (void *) __get_free_pages(GFP_KERNEL | GFP_DMA, N_RX_PAGES);
-	mp->tx_ring = (void *) __get_free_pages(GFP_KERNEL | GFP_DMA, 0);
-
-	if (mp->tx_ring==NULL || mp->rx_ring==NULL) {
-		if (mp->rx_ring) free_pages((u32) mp->rx_ring, N_RX_PAGES);
-		if (mp->tx_ring) free_pages((u32) mp->tx_ring, 0);
-		free_irq(dev->irq, dev);
-		free_irq(mp->dma_intr, dev);
-		printk(KERN_ERR "%s: unable to allocate DMA buffers\n", dev->name);
-		return -ENOMEM;
+	mp->tx_ring = dma_alloc_coherent(mp->device,
+			N_TX_RING * MACE_BUFF_SIZE,
+			&mp->tx_ring_phys, GFP_KERNEL);
+	if (mp->tx_ring == NULL) {
+		printk(KERN_ERR "%s: unable to allocate DMA tx buffers\n", dev->name);
+		goto out1;
 	}
 
-	mp->rx_ring_phys = (unsigned char *) virt_to_bus((void *)mp->rx_ring);
-	mp->tx_ring_phys = (unsigned char *) virt_to_bus((void *)mp->tx_ring);
-
-	/* We want the Rx buffer to be uncached and the Tx buffer to be writethrough */
-
-	kernel_set_cachemode((void *)mp->rx_ring, N_RX_PAGES * PAGE_SIZE, IOMAP_NOCACHE_NONSER);
-	kernel_set_cachemode((void *)mp->tx_ring, PAGE_SIZE, IOMAP_WRITETHROUGH);
+	mp->rx_ring = dma_alloc_coherent(mp->device,
+			N_RX_RING * MACE_BUFF_SIZE,
+			&mp->rx_ring_phys, GFP_KERNEL);
+	if (mp->rx_ring == NULL) {
+		printk(KERN_ERR "%s: unable to allocate DMA rx buffers\n", dev->name);
+		goto out2;
+	}
 
 	mace_dma_off(dev);
 
@@ -348,34 +418,22 @@
 	psc_write_word(PSC_ENETWR_CTL, 0x0400);
 	psc_write_word(PSC_ENETRD_CTL, 0x0400);
 
-#if 0
-	/* load up the hardware address */
-
-	mb->iac = ADDRCHG | PHYADDR;
-
-	while ((mb->iac & ADDRCHG) != 0);
-
-	for (i = 0; i < 6; ++i)
-		mb->padr = dev->dev_addr[i];
-
-	/* clear the multicast filter */
-	mb->iac = ADDRCHG | LOGADDR;
-
-	while ((mb->iac & ADDRCHG) != 0);
-
-	for (i = 0; i < 8; ++i)
-		mb->ladrf = 0;
-
-	mb->plscc = PORTSEL_GPSI + ENPLSIO;
-
-	mb->maccc = ENXMT | ENRCV;
-	mb->imr = RCVINT;
-#endif
-
 	mace_rxdma_reset(dev);
 	mace_txdma_reset(dev);
 
+	/* turn it on! */
+	mb->maccc = ENXMT | ENRCV;
+	/* enable all interrupts except receive interrupts */
+	mb->imr = RCVINT;
 	return 0;
+
+out2:
+	dma_free_coherent(mp->device, N_TX_RING * MACE_BUFF_SIZE,
+	                  mp->tx_ring, mp->tx_ring_phys);
+out1:
+	free_irq(dev->irq, dev);
+	free_irq(mp->dma_intr, dev);
+	return -ENOMEM;
 }
 
 /*
@@ -384,19 +442,13 @@
 
 static int mace_close(struct net_device *dev)
 {
-	struct mace_data *mp = (struct mace_data *) dev->priv;
+	struct mace_data *mp = netdev_priv(dev);
 	volatile struct mace *mb = mp->mace;
 
 	mb->maccc = 0;		/* disable rx and tx	 */
 	mb->imr = 0xFF;		/* disable all irqs	 */
 	mace_dma_off(dev);	/* disable rx and tx dma */
 
-	free_irq(dev->irq, dev);
-	free_irq(IRQ_MAC_MACE_DMA, dev);
-
-	free_pages((u32) mp->rx_ring, N_RX_PAGES);
-	free_pages((u32) mp->tx_ring, 0);
-
 	return 0;
 }
 
@@ -406,15 +458,20 @@
 
 static int mace_xmit_start(struct sk_buff *skb, struct net_device *dev)
 {
-	struct mace_data *mp = (struct mace_data *) dev->priv;
+	struct mace_data *mp = netdev_priv(dev);
+	unsigned long flags;
 
-	/* Stop the queue if the buffer is full */
+	/* Stop the queue since there's only the one buffer */
 
+	local_irq_save(flags);
+	netif_stop_queue(dev);
 	if (!mp->tx_count) {
-		netif_stop_queue(dev);
-		return 1;
+		printk(KERN_ERR "macmace: tx queue running but no free buffers.\n");
+		local_irq_restore(flags);
+		return NETDEV_TX_BUSY;
 	}
 	mp->tx_count--;
+	local_irq_restore(flags);
 
 	mp->stats.tx_packets++;
 	mp->stats.tx_bytes += skb->len;
@@ -432,23 +489,26 @@
 
 	dev_kfree_skb(skb);
 
-	return 0;
+	dev->trans_start = jiffies;
+	return NETDEV_TX_OK;
 }
 
 static struct net_device_stats *mace_stats(struct net_device *dev)
 {
-	struct mace_data *p = (struct mace_data *) dev->priv;
-	return &p->stats;
+	struct mace_data *mp = netdev_priv(dev);
+	return &mp->stats;
 }
 
 static void mace_set_multicast(struct net_device *dev)
 {
-	struct mace_data *mp = (struct mace_data *) dev->priv;
+	struct mace_data *mp = netdev_priv(dev);
 	volatile struct mace *mb = mp->mace;
 	int i, j;
 	u32 crc;
 	u8 maccc;
+	unsigned long flags;
 
+	local_irq_save(flags);
 	maccc = mb->maccc;
 	mb->maccc &= ~PROM;
 
@@ -473,116 +533,122 @@
 			}
 		}
 
-		mb->iac = ADDRCHG | LOGADDR;
-		while (mb->iac & ADDRCHG);
-
-		for (i = 0; i < 8; ++i) {
-			mb->ladrf = multicast_filter[i];
+		if (mp->chipid == BROKEN_ADDRCHG_REV)
+			mb->iac = LOGADDR;
+		else {
+			mb->iac = ADDRCHG | LOGADDR;
+			while ((mb->iac & ADDRCHG) != 0)
+				;
 		}
+		for (i = 0; i < 8; ++i)
+			mb->ladrf = multicast_filter[i];
+		if (mp->chipid != BROKEN_ADDRCHG_REV)
+			mb->iac = 0;
 	}
 
 	mb->maccc = maccc;
+	local_irq_restore(flags);
 }
 
-/*
- * Miscellaneous interrupts are handled here. We may end up
- * having to bash the chip on the head for bad errors
- */
-
 static void mace_handle_misc_intrs(struct mace_data *mp, int intr)
 {
 	volatile struct mace *mb = mp->mace;
 	static int mace_babbles, mace_jabbers;
 
-	if (intr & MPCO) {
+	if (intr & MPCO)
 		mp->stats.rx_missed_errors += 256;
-	}
-	mp->stats.rx_missed_errors += mb->mpc;	/* reading clears it */
-
-	if (intr & RNTPCO) {
+	mp->stats.rx_missed_errors += mb->mpc;   /* reading clears it */
+	if (intr & RNTPCO)
 		mp->stats.rx_length_errors += 256;
-	}
-	mp->stats.rx_length_errors += mb->rntpc;	/* reading clears it */
-
-	if (intr & CERR) {
+	mp->stats.rx_length_errors += mb->rntpc; /* reading clears it */
+	if (intr & CERR)
 		++mp->stats.tx_heartbeat_errors;
-	}
-	if (intr & BABBLE) {
-		if (mace_babbles++ < 4) {
-			printk(KERN_DEBUG "mace: babbling transmitter\n");
-		}
-	}
-	if (intr & JABBER) {
-		if (mace_jabbers++ < 4) {
-			printk(KERN_DEBUG "mace: jabbering transceiver\n");
-		}
-	}
+	if (intr & BABBLE)
+		if (mace_babbles++ < 4)
+			printk(KERN_DEBUG "macmace: babbling transmitter\n");
+	if (intr & JABBER)
+		if (mace_jabbers++ < 4)
+			printk(KERN_DEBUG "macmace: jabbering transceiver\n");
 }
 
-/*
- *	A transmit error has occurred. (We kick the transmit side from
- *	the DMA completion)
- */
-
-static void mace_xmit_error(struct net_device *dev)
-{
-	struct mace_data *mp = (struct mace_data *) dev->priv;
-	volatile struct mace *mb = mp->mace;
-	u8 xmtfs, xmtrc;
-
-	xmtfs = mb->xmtfs;
-	xmtrc = mb->xmtrc;
-
-	if (xmtfs & XMTSV) {
-		if (xmtfs & UFLO) {
-			printk("%s: DMA underrun.\n", dev->name);
-			mp->stats.tx_errors++;
-			mp->stats.tx_fifo_errors++;
-			mace_txdma_reset(dev);
-		}
-		if (xmtfs & RTRY) {
-			mp->stats.collisions++;
-		}
-	}
-}
-
-/*
- *	A receive interrupt occurred.
- */
-
-static void mace_recv_interrupt(struct net_device *dev)
-{
-/*	struct mace_data *mp = (struct mace_data *) dev->priv; */
-//	volatile struct mace *mb = mp->mace;
-}
-
-/*
- * Process the chip interrupt
- */
-
 static irqreturn_t mace_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = (struct net_device *) dev_id;
-	struct mace_data *mp = (struct mace_data *) dev->priv;
+	struct mace_data *mp = netdev_priv(dev);
 	volatile struct mace *mb = mp->mace;
-	u8 ir;
+	int intr, fs;
+	unsigned int flags;
 
-	ir = mb->ir;
-	mace_handle_misc_intrs(mp, ir);
+	/* don't want the dma interrupt handler to fire */
+	local_irq_save(flags);
 
-	if (ir & XMTINT) {
-		mace_xmit_error(dev);
+	intr = mb->ir; /* read interrupt register */
+	mace_handle_misc_intrs(mp, intr);
+
+	if (intr & XMTINT) {
+		fs = mb->xmtfs;
+		if ((fs & XMTSV) == 0) {
+			printk(KERN_ERR "macmace: xmtfs not valid! (fs=%x)\n", fs);
+			mace_reset(dev);
+			/*
+			 * XXX mace likes to hang the machine after a xmtfs error.
+			 * This is hard to reproduce, reseting *may* help
+			 */
+		}
+		/* dma should have finished */
+		if (!mp->tx_count) {
+			printk(KERN_DEBUG "macmace: tx ring ran out? (fs=%x)\n", fs);
+		}
+		/* Update stats */
+		if (fs & (UFLO|LCOL|LCAR|RTRY)) {
+			++mp->stats.tx_errors;
+			if (fs & LCAR)
+				++mp->stats.tx_carrier_errors;
+			else if (fs & (UFLO|LCOL|RTRY)) {
+				++mp->stats.tx_aborted_errors;
+				if (mb->xmtfs & UFLO) {
+					printk(KERN_ERR "%s: DMA underrun.\n", dev->name);
+					mp->stats.tx_fifo_errors++;
+					mace_txdma_reset(dev);
+				}
+			}
+		}
 	}
-	if (ir & RCVINT) {
-		mace_recv_interrupt(dev);
-	}
+
+	if (mp->tx_count)
+		netif_wake_queue(dev);
+
+	local_irq_restore(flags);
+
 	return IRQ_HANDLED;
 }
 
 static void mace_tx_timeout(struct net_device *dev)
 {
-/*	struct mace_data *mp = (struct mace_data *) dev->priv; */
-//	volatile struct mace *mb = mp->mace;
+	struct mace_data *mp = netdev_priv(dev);
+	volatile struct mace *mb = mp->mace;
+	unsigned long flags;
+
+	local_irq_save(flags);
+
+	/* turn off both tx and rx and reset the chip */
+	mb->maccc = 0;
+	printk(KERN_ERR "macmace: transmit timeout - resetting\n");
+	mace_txdma_reset(dev);
+	mace_reset(dev);
+
+	/* restart rx dma */
+	mace_rxdma_reset(dev);
+
+	mp->tx_count = N_TX_RING;
+	netif_wake_queue(dev);
+
+	/* turn it on! */
+	mb->maccc = ENXMT | ENRCV;
+	/* enable all interrupts except receive interrupts */
+	mb->imr = RCVINT;
+
+	local_irq_restore(flags);
 }
 
 /*
@@ -591,40 +657,39 @@
 
 static void mace_dma_rx_frame(struct net_device *dev, struct mace_frame *mf)
 {
-	struct mace_data *mp = (struct mace_data *) dev->priv;
+	struct mace_data *mp = netdev_priv(dev);
 	struct sk_buff *skb;
+	unsigned int frame_status = mf->rcvsts;
 
-	if (mf->status & RS_OFLO) {
-		printk("%s: fifo overflow.\n", dev->name);
+	if (frame_status & (RS_OFLO | RS_CLSN | RS_FRAMERR | RS_FCSERR)) {
 		mp->stats.rx_errors++;
-		mp->stats.rx_fifo_errors++;
-	}
-	if (mf->status&(RS_CLSN|RS_FRAMERR|RS_FCSERR))
-		mp->stats.rx_errors++;
+		if (frame_status & RS_OFLO) {
+			printk(KERN_DEBUG "%s: fifo overflow.\n", dev->name);
+			mp->stats.rx_fifo_errors++;
+		}
+		if (frame_status & RS_CLSN)
+			mp->stats.collisions++;
+		if (frame_status & RS_FRAMERR)
+			mp->stats.rx_frame_errors++;
+		if (frame_status & RS_FCSERR)
+			mp->stats.rx_crc_errors++;
+	} else {
+		unsigned int frame_length = mf->rcvcnt + ((frame_status & 0x0F) << 8 );
 
-	if (mf->status&RS_CLSN) {
-		mp->stats.collisions++;
-	}
-	if (mf->status&RS_FRAMERR) {
-		mp->stats.rx_frame_errors++;
-	}
-	if (mf->status&RS_FCSERR) {
-		mp->stats.rx_crc_errors++;
-	}
+		skb = dev_alloc_skb(frame_length + 2);
+		if (!skb) {
+			mp->stats.rx_dropped++;
+			return;
+		}
+		skb_reserve(skb, 2);
+		memcpy(skb_put(skb, frame_length), mf->data, frame_length);
 
-	skb = dev_alloc_skb(mf->len+2);
-	if (!skb) {
-		mp->stats.rx_dropped++;
-		return;
+		skb->protocol = eth_type_trans(skb, dev);
+		netif_rx(skb);
+		dev->last_rx = jiffies;
+		mp->stats.rx_packets++;
+		mp->stats.rx_bytes += frame_length;
 	}
-	skb_reserve(skb,2);
-	memcpy(skb_put(skb, mf->len), mf->data, mf->len);
-
-	skb->protocol = eth_type_trans(skb, dev);
-	netif_rx(skb);
-	dev->last_rx = jiffies;
-	mp->stats.rx_packets++;
-	mp->stats.rx_bytes += mf->len;
 }
 
 /*
@@ -634,7 +699,7 @@
 static irqreturn_t mace_dma_intr(int irq, void *dev_id)
 {
 	struct net_device *dev = (struct net_device *) dev_id;
-	struct mace_data *mp = (struct mace_data *) dev->priv;
+	struct mace_data *mp = netdev_priv(dev);
 	int left, head;
 	u16 status;
 	u32 baka;
@@ -661,7 +726,8 @@
 		/* Loop through the ring buffer and process new packages */
 
 		while (mp->rx_tail < head) {
-			mace_dma_rx_frame(dev, (struct mace_frame *) (mp->rx_ring + (mp->rx_tail * 0x0800)));
+			mace_dma_rx_frame(dev, (struct mace_frame*) (mp->rx_ring
+				+ (mp->rx_tail * MACE_BUFF_SIZE)));
 			mp->rx_tail++;
 		}
 
@@ -688,9 +754,76 @@
 		psc_write_word(PSC_ENETWR_CMD + mp->tx_sloti, 0x0100);
 		mp->tx_sloti ^= 0x10;
 		mp->tx_count++;
-		netif_wake_queue(dev);
 	}
 	return IRQ_HANDLED;
 }
 
 MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Macintosh MACE ethernet driver");
+
+static int __devexit mac_mace_device_remove (struct platform_device *pdev)
+{
+	struct net_device *dev = platform_get_drvdata(pdev);
+	struct mace_data *mp = netdev_priv(dev);
+
+	unregister_netdev(dev);
+
+	free_irq(dev->irq, dev);
+	free_irq(IRQ_MAC_MACE_DMA, dev);
+
+	dma_free_coherent(mp->device, N_RX_RING * MACE_BUFF_SIZE,
+	                  mp->rx_ring, mp->rx_ring_phys);
+	dma_free_coherent(mp->device, N_TX_RING * MACE_BUFF_SIZE,
+	                  mp->tx_ring, mp->tx_ring_phys);
+
+	free_netdev(dev);
+
+	return 0;
+}
+
+static struct platform_driver mac_mace_driver = {
+	.probe  = mace_probe,
+	.remove = __devexit_p(mac_mace_device_remove),
+	.driver	= {
+		.name = mac_mace_string,
+	},
+};
+
+static int __init mac_mace_init_module(void)
+{
+	int err;
+
+	if ((err = platform_driver_register(&mac_mace_driver))) {
+		printk(KERN_ERR "Driver registration failed\n");
+		return err;
+	}
+
+	mac_mace_device = platform_device_alloc(mac_mace_string, 0);
+	if (!mac_mace_device)
+		goto out_unregister;
+
+	if (platform_device_add(mac_mace_device)) {
+		platform_device_put(mac_mace_device);
+		mac_mace_device = NULL;
+	}
+
+	return 0;
+
+out_unregister:
+	platform_driver_unregister(&mac_mace_driver);
+
+	return -ENOMEM;
+}
+
+static void __exit mac_mace_cleanup_module(void)
+{
+	platform_driver_unregister(&mac_mace_driver);
+
+	if (mac_mace_device) {
+		platform_device_unregister(mac_mace_device);
+		mac_mace_device = NULL;
+	}
+}
+
+module_init(mac_mace_init_module);
+module_exit(mac_mace_cleanup_module);
diff --git a/drivers/net/macsonic.c b/drivers/net/macsonic.c
index 8ca57a0..e9ecdbf 100644
--- a/drivers/net/macsonic.c
+++ b/drivers/net/macsonic.c
@@ -130,6 +130,46 @@
 		addr[i] = bitrev8(addr[i]);
 }
 
+static irqreturn_t macsonic_interrupt(int irq, void *dev_id)
+{
+	irqreturn_t result;
+	unsigned long flags;
+
+	local_irq_save(flags);
+	result = sonic_interrupt(irq, dev_id);
+	local_irq_restore(flags);
+	return result;
+}
+
+static int macsonic_open(struct net_device* dev)
+{
+	if (request_irq(dev->irq, &sonic_interrupt, IRQ_FLG_FAST, "sonic", dev)) {
+		printk(KERN_ERR "%s: unable to get IRQ %d.\n", dev->name, dev->irq);
+		return -EAGAIN;
+	}
+	/* Under the A/UX interrupt scheme, the onboard SONIC interrupt comes
+	 * in at priority level 3. However, we sometimes get the level 2 inter-
+	 * rupt as well, which must prevent re-entrance of the sonic handler.
+	 */
+	if (dev->irq == IRQ_AUTO_3)
+		if (request_irq(IRQ_NUBUS_9, &macsonic_interrupt, IRQ_FLG_FAST, "sonic", dev)) {
+			printk(KERN_ERR "%s: unable to get IRQ %d.\n", dev->name, IRQ_NUBUS_9);
+			free_irq(dev->irq, dev);
+			return -EAGAIN;
+		}
+	return sonic_open(dev);
+}
+
+static int macsonic_close(struct net_device* dev)
+{
+	int err;
+	err = sonic_close(dev);
+	free_irq(dev->irq, dev);
+	if (dev->irq == IRQ_AUTO_3)
+		free_irq(IRQ_NUBUS_9, dev);
+	return err;
+}
+
 int __init macsonic_init(struct net_device* dev)
 {
 	struct sonic_local* lp = netdev_priv(dev);
@@ -160,8 +200,8 @@
 	lp->rra_laddr = lp->rda_laddr + (SIZEOF_SONIC_RD * SONIC_NUM_RDS
 	                     * SONIC_BUS_SCALE(lp->dma_bitmode));
 
-	dev->open = sonic_open;
-	dev->stop = sonic_close;
+	dev->open = macsonic_open;
+	dev->stop = macsonic_close;
 	dev->hard_start_xmit = sonic_send_packet;
 	dev->get_stats = sonic_get_stats;
 	dev->set_multicast_list = &sonic_multicast_list;
@@ -402,7 +442,7 @@
 	    ndev->dr_sw == NUBUS_DRSW_DAYNA)
 		return MACSONIC_DAYNA;
 
-	if (ndev->dr_hw == NUBUS_DRHW_SONIC_LC &&
+	if (ndev->dr_hw == NUBUS_DRHW_APPLE_SONIC_LC &&
 	    ndev->dr_sw == 0) { /* huh? */
 		return MACSONIC_APPLE16;
 	}
@@ -522,7 +562,7 @@
 	return macsonic_init(dev);
 }
 
-static int __init mac_sonic_probe(struct platform_device *device)
+static int __init mac_sonic_probe(struct platform_device *pdev)
 {
 	struct net_device *dev;
 	struct sonic_local *lp;
@@ -534,8 +574,8 @@
 		return -ENOMEM;
 
 	lp = netdev_priv(dev);
-	lp->device = &device->dev;
-	SET_NETDEV_DEV(dev, &device->dev);
+	lp->device = &pdev->dev;
+	SET_NETDEV_DEV(dev, &pdev->dev);
  	SET_MODULE_OWNER(dev);
 
 	/* This will catch fatal stuff like -ENOMEM as well as success */
@@ -572,19 +612,17 @@
 module_param(sonic_debug, int, 0);
 MODULE_PARM_DESC(sonic_debug, "macsonic debug level (1-4)");
 
-#define SONIC_IRQ_FLAG IRQ_FLG_FAST
-
 #include "sonic.c"
 
-static int __devexit mac_sonic_device_remove (struct platform_device *device)
+static int __devexit mac_sonic_device_remove (struct platform_device *pdev)
 {
-	struct net_device *dev = platform_get_drvdata(device);
+	struct net_device *dev = platform_get_drvdata(pdev);
 	struct sonic_local* lp = netdev_priv(dev);
 
-	unregister_netdev (dev);
+	unregister_netdev(dev);
 	dma_free_coherent(lp->device, SIZEOF_SONIC_DESC * SONIC_BUS_SCALE(lp->dma_bitmode),
 	                  lp->descriptors, lp->descriptors_laddr);
-	free_netdev (dev);
+	free_netdev(dev);
 
 	return 0;
 }
@@ -607,9 +645,8 @@
 	}
 
 	mac_sonic_device = platform_device_alloc(mac_sonic_string, 0);
-	if (!mac_sonic_device) {
+	if (!mac_sonic_device)
 		goto out_unregister;
-	}
 
 	if (platform_device_add(mac_sonic_device)) {
 		platform_device_put(mac_sonic_device);
diff --git a/drivers/net/sonic.c b/drivers/net/sonic.c
index c6320c7..8069f3e 100644
--- a/drivers/net/sonic.c
+++ b/drivers/net/sonic.c
@@ -50,29 +50,6 @@
 	if (sonic_debug > 2)
 		printk("sonic_open: initializing sonic driver.\n");
 
-	/*
-	 * We don't need to deal with auto-irq stuff since we
-	 * hardwire the sonic interrupt.
-	 */
-/*
- * XXX Horrible work around:  We install sonic_interrupt as fast interrupt.
- * This means that during execution of the handler interrupt are disabled
- * covering another bug otherwise corrupting data.  This doesn't mean
- * this glue works ok under all situations.
- *
- * Note (dhd): this also appears to prevent lockups on the Macintrash
- * when more than one Ethernet card is installed (knock on wood)
- *
- * Note (fthain): whether the above is still true is anyones guess. Certainly
- * the buffer handling algorithms will not tolerate re-entrance without some
- * mutual exclusion added. Anyway, the memcpy has now been eliminated from the
- * rx code to make this a faster "fast interrupt".
- */
-	if (request_irq(dev->irq, &sonic_interrupt, SONIC_IRQ_FLAG, "sonic", dev)) {
-		printk(KERN_ERR "\n%s: unable to get IRQ %d .\n", dev->name, dev->irq);
-		return -EAGAIN;
-	}
-
 	for (i = 0; i < SONIC_NUM_RRS; i++) {
 		struct sk_buff *skb = dev_alloc_skb(SONIC_RBSIZE + 2);
 		if (skb == NULL) {
@@ -169,8 +146,6 @@
 		}
 	}
 
-	free_irq(dev->irq, dev);	/* release the IRQ */
-
 	return 0;
 }
 
@@ -178,8 +153,13 @@
 {
 	struct sonic_local *lp = netdev_priv(dev);
 	int i;
-	/* Stop the interrupts for this */
+	/*
+	 * put the Sonic into software-reset mode and
+	 * disable all interrupts before releasing DMA buffers
+	 */
 	SONIC_WRITE(SONIC_IMR, 0);
+	SONIC_WRITE(SONIC_ISR, 0x7fff);
+	SONIC_WRITE(SONIC_CMD, SONIC_CR_RST);
 	/* We could resend the original skbs. Easier to re-initialise. */
 	for (i = 0; i < SONIC_NUM_TDS; i++) {
 		if(lp->tx_laddr[i]) {
diff --git a/drivers/net/sun3_82586.c b/drivers/net/sun3_82586.c
index 396c3d9..a123ea8 100644
--- a/drivers/net/sun3_82586.c
+++ b/drivers/net/sun3_82586.c
@@ -1023,10 +1023,11 @@
 	{
 		len = skb->len;
 		if (len < ETH_ZLEN) {
-			memset((char *)p->xmit_cbuffs[p->xmit_count], 0, ETH_ZLEN);
+			memset((void *)p->xmit_cbuffs[p->xmit_count], 0,
+			       ETH_ZLEN);
 			len = ETH_ZLEN;
 		}
-		skb_copy_from_linear_data(skb, p->xmit_cbuffs[p->xmit_count], skb->len);
+		skb_copy_from_linear_data(skb, (void *)p->xmit_cbuffs[p->xmit_count], skb->len);
 
 #if (NUM_XMIT_BUFFS == 1)
 #	ifdef NO_NOPCOMMANDS
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 9488f49ea..59d6e74 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -1300,9 +1300,11 @@
 			msleep(1);
 		}
 	}
-	tg3_write_mem(tp, NIC_SRAM_WOL_MBOX, WOL_SIGNATURE |
-					     WOL_DRV_STATE_SHUTDOWN |
-					     WOL_DRV_WOL | WOL_SET_MAGIC_PKT);
+	if (tp->tg3_flags & TG3_FLAG_WOL_CAP)
+		tg3_write_mem(tp, NIC_SRAM_WOL_MBOX, WOL_SIGNATURE |
+						     WOL_DRV_STATE_SHUTDOWN |
+						     WOL_DRV_WOL |
+						     WOL_SET_MAGIC_PKT);
 
 	pci_read_config_word(tp->pdev, pm + PCI_PM_PMC, &power_caps);
 
@@ -2593,10 +2595,8 @@
 {
 	int current_link_up = 0;
 
- 	if (!(mac_status & MAC_STATUS_PCS_SYNCED)) {
-		tp->tg3_flags &= ~TG3_FLAG_GOT_SERDES_FLOWCTL;
+	if (!(mac_status & MAC_STATUS_PCS_SYNCED))
 		goto out;
-	}
 
 	if (tp->link_config.autoneg == AUTONEG_ENABLE) {
 		u32 flags;
@@ -2614,7 +2614,6 @@
 
 			tg3_setup_flow_control(tp, local_adv, remote_adv);
 
-			tp->tg3_flags |= TG3_FLAG_GOT_SERDES_FLOWCTL;
 			current_link_up = 1;
 		}
 		for (i = 0; i < 30; i++) {
@@ -2637,7 +2636,6 @@
 	} else {
 		/* Forcing 1000FD link up. */
 		current_link_up = 1;
-		tp->tg3_flags |= TG3_FLAG_GOT_SERDES_FLOWCTL;
 
 		tw32_f(MAC_MODE, (tp->mac_mode | MAC_MODE_SEND_CONFIGS));
 		udelay(40);
@@ -3895,8 +3893,7 @@
 	entry = tp->tx_prod;
 	base_flags = 0;
 	mss = 0;
-	if (skb->len > (tp->dev->mtu + ETH_HLEN) &&
-	    (mss = skb_shinfo(skb)->gso_size) != 0) {
+	if ((mss = skb_shinfo(skb)->gso_size) != 0) {
 		int tcp_opt_len, ip_tcp_len;
 
 		if (skb_header_cloned(skb) &&
@@ -4053,8 +4050,7 @@
 	if (skb->ip_summed == CHECKSUM_PARTIAL)
 		base_flags |= TXD_FLAG_TCPUDP_CSUM;
 	mss = 0;
-	if (skb->len > (tp->dev->mtu + ETH_HLEN) &&
-	    (mss = skb_shinfo(skb)->gso_size) != 0) {
+	if ((mss = skb_shinfo(skb)->gso_size) != 0) {
 		struct iphdr *iph;
 		int tcp_opt_len, ip_tcp_len, hdr_len;
 
@@ -5934,7 +5930,7 @@
 
 
 /* tp->lock is held. */
-static void __tg3_set_mac_addr(struct tg3 *tp)
+static void __tg3_set_mac_addr(struct tg3 *tp, int skip_mac_1)
 {
 	u32 addr_high, addr_low;
 	int i;
@@ -5946,6 +5942,8 @@
 		    (tp->dev->dev_addr[4] <<  8) |
 		    (tp->dev->dev_addr[5] <<  0));
 	for (i = 0; i < 4; i++) {
+		if (i == 1 && skip_mac_1)
+			continue;
 		tw32(MAC_ADDR_0_HIGH + (i * 8), addr_high);
 		tw32(MAC_ADDR_0_LOW + (i * 8), addr_low);
 	}
@@ -5972,7 +5970,7 @@
 {
 	struct tg3 *tp = netdev_priv(dev);
 	struct sockaddr *addr = p;
-	int err = 0;
+	int err = 0, skip_mac_1 = 0;
 
 	if (!is_valid_ether_addr(addr->sa_data))
 		return -EINVAL;
@@ -5983,22 +5981,21 @@
 		return 0;
 
 	if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) {
-		/* Reset chip so that ASF can re-init any MAC addresses it
-		 * needs.
-		 */
-		tg3_netif_stop(tp);
-		tg3_full_lock(tp, 1);
+		u32 addr0_high, addr0_low, addr1_high, addr1_low;
 
-		tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
-		err = tg3_restart_hw(tp, 0);
-		if (!err)
-			tg3_netif_start(tp);
-		tg3_full_unlock(tp);
-	} else {
-		spin_lock_bh(&tp->lock);
-		__tg3_set_mac_addr(tp);
-		spin_unlock_bh(&tp->lock);
+		addr0_high = tr32(MAC_ADDR_0_HIGH);
+		addr0_low = tr32(MAC_ADDR_0_LOW);
+		addr1_high = tr32(MAC_ADDR_1_HIGH);
+		addr1_low = tr32(MAC_ADDR_1_LOW);
+
+		/* Skip MAC addr 1 if ASF is using it. */
+		if ((addr0_high != addr1_high || addr0_low != addr1_low) &&
+		    !(addr1_high == 0 && addr1_low == 0))
+			skip_mac_1 = 1;
 	}
+	spin_lock_bh(&tp->lock);
+	__tg3_set_mac_addr(tp, skip_mac_1);
+	spin_unlock_bh(&tp->lock);
 
 	return err;
 }
@@ -6315,7 +6312,7 @@
 		     tp->rx_jumbo_ptr);
 
 	/* Initialize MAC address and backoff seed. */
-	__tg3_set_mac_addr(tp);
+	__tg3_set_mac_addr(tp, 0);
 
 	/* MTU + ethernet header + FCS + optional VLAN tag */
 	tw32(MAC_RX_MTU_SIZE, tp->dev->mtu + ETH_HLEN + 8);
@@ -6346,8 +6343,7 @@
 	     tp->pci_chip_rev_id != CHIPREV_ID_5705_A0) ||
 	    (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750)) {
 		if (tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE &&
-		    (tp->pci_chip_rev_id == CHIPREV_ID_5705_A1 ||
-		     tp->pci_chip_rev_id == CHIPREV_ID_5705_A2)) {
+		    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) {
 			rdmac_mode |= RDMAC_MODE_FIFO_SIZE_128;
 		} else if (!(tr32(TG3PCI_PCISTATE) & PCISTATE_BUS_SPEED_HIGH) &&
 			   !(tp->tg3_flags2 & TG3_FLG2_IS_5788)) {
@@ -6457,6 +6453,7 @@
 		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755)
 			gpio_mask |= GRC_LCLCTRL_GPIO_UART_SEL;
 
+		tp->grc_local_ctrl &= ~gpio_mask;
 		tp->grc_local_ctrl |= tr32(GRC_LOCAL_CTRL) & gpio_mask;
 
 		/* GPIO1 must be driven high for eeprom write protect */
@@ -7036,11 +7033,7 @@
 	if (err)
 		return err;
 
-	if ((tp->tg3_flags2 & TG3_FLG2_5750_PLUS) &&
-	    (GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5750_AX) &&
-	    (GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5750_BX) &&
-	    !((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714) &&
-	      (tp->pdev_peer == tp->pdev))) {
+	if (tp->tg3_flags & TG3_FLAG_SUPPORT_MSI) {
 		/* All MSI supporting chips should support tagged
 		 * status.  Assert that this is the case.
 		 */
@@ -7399,9 +7392,7 @@
 
 	tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
 	tg3_free_rings(tp);
-	tp->tg3_flags &=
-		~(TG3_FLAG_INIT_COMPLETE |
-		  TG3_FLAG_GOT_SERDES_FLOWCTL);
+	tp->tg3_flags &= ~TG3_FLAG_INIT_COMPLETE;
 
 	tg3_full_unlock(tp);
 
@@ -8036,7 +8027,10 @@
 {
 	struct tg3 *tp = netdev_priv(dev);
 
-	wol->supported = WAKE_MAGIC;
+	if (tp->tg3_flags & TG3_FLAG_WOL_CAP)
+		wol->supported = WAKE_MAGIC;
+	else
+		wol->supported = 0;
 	wol->wolopts = 0;
 	if (tp->tg3_flags & TG3_FLAG_WOL_ENABLE)
 		wol->wolopts = WAKE_MAGIC;
@@ -8050,8 +8044,7 @@
 	if (wol->wolopts & ~WAKE_MAGIC)
 		return -EINVAL;
 	if ((wol->wolopts & WAKE_MAGIC) &&
-	    tp->tg3_flags2 & TG3_FLG2_ANY_SERDES &&
-	    !(tp->tg3_flags & TG3_FLAG_SERDES_WOL_CAP))
+	    !(tp->tg3_flags & TG3_FLAG_WOL_CAP))
 		return -EINVAL;
 
 	spin_lock_bh(&tp->lock);
@@ -9289,7 +9282,7 @@
 			return;
 		}
 	}
-	tp->nvram_size = 0x20000;
+	tp->nvram_size = 0x80000;
 }
 
 static void __devinit tg3_get_nvram_info(struct tg3 *tp)
@@ -9408,33 +9401,31 @@
 
 static void __devinit tg3_get_5755_nvram_info(struct tg3 *tp)
 {
-	u32 nvcfg1;
+	u32 nvcfg1, protect = 0;
 
 	nvcfg1 = tr32(NVRAM_CFG1);
 
 	/* NVRAM protection for TPM */
-	if (nvcfg1 & (1 << 27))
+	if (nvcfg1 & (1 << 27)) {
 		tp->tg3_flags2 |= TG3_FLG2_PROTECTED_NVRAM;
+		protect = 1;
+	}
 
-	switch (nvcfg1 & NVRAM_CFG1_5752VENDOR_MASK) {
-		case FLASH_5755VENDOR_ATMEL_EEPROM_64KHZ:
-		case FLASH_5755VENDOR_ATMEL_EEPROM_376KHZ:
-			tp->nvram_jedecnum = JEDEC_ATMEL;
-			tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED;
-			tp->nvram_pagesize = ATMEL_AT24C512_CHIP_SIZE;
-
-			nvcfg1 &= ~NVRAM_CFG1_COMPAT_BYPASS;
-			tw32(NVRAM_CFG1, nvcfg1);
-			break;
-		case FLASH_5752VENDOR_ATMEL_FLASH_BUFFERED:
+	nvcfg1 &= NVRAM_CFG1_5752VENDOR_MASK;
+	switch (nvcfg1) {
 		case FLASH_5755VENDOR_ATMEL_FLASH_1:
 		case FLASH_5755VENDOR_ATMEL_FLASH_2:
 		case FLASH_5755VENDOR_ATMEL_FLASH_3:
-		case FLASH_5755VENDOR_ATMEL_FLASH_4:
 			tp->nvram_jedecnum = JEDEC_ATMEL;
 			tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED;
 			tp->tg3_flags2 |= TG3_FLG2_FLASH;
 			tp->nvram_pagesize = 264;
+			if (nvcfg1 == FLASH_5755VENDOR_ATMEL_FLASH_1)
+				tp->nvram_size = (protect ? 0x3e200 : 0x80000);
+			else if (nvcfg1 == FLASH_5755VENDOR_ATMEL_FLASH_2)
+				tp->nvram_size = (protect ? 0x1f200 : 0x40000);
+			else
+				tp->nvram_size = (protect ? 0x1f200 : 0x20000);
 			break;
 		case FLASH_5752VENDOR_ST_M45PE10:
 		case FLASH_5752VENDOR_ST_M45PE20:
@@ -9443,6 +9434,12 @@
 			tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED;
 			tp->tg3_flags2 |= TG3_FLG2_FLASH;
 			tp->nvram_pagesize = 256;
+			if (nvcfg1 == FLASH_5752VENDOR_ST_M45PE10)
+				tp->nvram_size = (protect ? 0x10000 : 0x20000);
+			else if (nvcfg1 == FLASH_5752VENDOR_ST_M45PE20)
+				tp->nvram_size = (protect ? 0x10000 : 0x40000);
+			else
+				tp->nvram_size = (protect ? 0x20000 : 0x80000);
 			break;
 	}
 }
@@ -9518,6 +9515,8 @@
 		}
 		tg3_enable_nvram_access(tp);
 
+		tp->nvram_size = 0;
+
 		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752)
 			tg3_get_5752_nvram_info(tp);
 		else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755)
@@ -9529,7 +9528,8 @@
 		else
 			tg3_get_nvram_info(tp);
 
-		tg3_get_nvram_size(tp);
+		if (tp->nvram_size == 0)
+			tg3_get_nvram_size(tp);
 
 		tg3_disable_nvram_access(tp);
 		tg3_nvram_unlock(tp);
@@ -9996,8 +9996,8 @@
 	tp->phy_id = PHY_ID_INVALID;
 	tp->led_ctrl = LED_CTRL_MODE_PHY_1;
 
-	/* Assume an onboard device by default.  */
-	tp->tg3_flags |= TG3_FLAG_EEPROM_WRITE_PROT;
+	/* Assume an onboard device and WOL capable by default.  */
+	tp->tg3_flags |= TG3_FLAG_EEPROM_WRITE_PROT | TG3_FLAG_WOL_CAP;
 
 	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
 		if (!(tr32(PCIE_TRANSACTION_CFG) & PCIE_TRANS_CFG_LOM)) {
@@ -10120,8 +10120,9 @@
 			if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS)
 				tp->tg3_flags2 |= TG3_FLG2_ASF_NEW_HANDSHAKE;
 		}
-		if (nic_cfg & NIC_SRAM_DATA_CFG_FIBER_WOL)
-			tp->tg3_flags |= TG3_FLAG_SERDES_WOL_CAP;
+		if (tp->tg3_flags2 & TG3_FLG2_ANY_SERDES &&
+		    !(nic_cfg & NIC_SRAM_DATA_CFG_FIBER_WOL))
+			tp->tg3_flags &= ~TG3_FLAG_WOL_CAP;
 
 		if (cfg2 & (1 << 17))
 			tp->tg3_flags2 |= TG3_FLG2_CAPACITIVE_COUPLING;
@@ -10399,6 +10400,8 @@
 	}
 }
 
+static struct pci_dev * __devinit tg3_find_peer(struct tg3 *);
+
 static int __devinit tg3_get_invariants(struct tg3 *tp)
 {
 	static struct pci_device_id write_reorder_chipsets[] = {
@@ -10554,6 +10557,10 @@
 	tp->pci_hdr_type     = (cacheline_sz_reg >> 16) & 0xff;
 	tp->pci_bist         = (cacheline_sz_reg >> 24) & 0xff;
 
+	if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) ||
+	    (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714))
+		tp->pdev_peer = tg3_find_peer(tp);
+
 	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750 ||
 	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752 ||
 	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
@@ -10567,6 +10574,14 @@
 		tp->tg3_flags2 |= TG3_FLG2_5705_PLUS;
 
 	if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS) {
+		tp->tg3_flags |= TG3_FLAG_SUPPORT_MSI;
+		if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5750_AX ||
+		    GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5750_BX ||
+		    (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714 &&
+		     tp->pci_chip_rev_id <= CHIPREV_ID_5714_A2 &&
+		     tp->pdev_peer == tp->pdev))
+			tp->tg3_flags &= ~TG3_FLAG_SUPPORT_MSI;
+
 		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
 		    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 ||
 		    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
@@ -10668,17 +10683,6 @@
 	if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5700_BX)
 		tp->tg3_flags |= TG3_FLAG_TXD_MBOX_HWBUG;
 
-	/* Back to back register writes can cause problems on this chip,
-	 * the workaround is to read back all reg writes except those to
-	 * mailbox regs.  See tg3_write_indirect_reg32().
-	 *
-	 * PCI Express 5750_A0 rev chips need this workaround too.
-	 */
-	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701 ||
-	    ((tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) &&
-	     tp->pci_chip_rev_id == CHIPREV_ID_5750_A0))
-		tp->tg3_flags |= TG3_FLAG_5701_REG_WRITE_BUG;
-
 	if ((pci_state_reg & PCISTATE_BUS_SPEED_HIGH) != 0)
 		tp->tg3_flags |= TG3_FLAG_PCI_HIGH_SPEED;
 	if ((pci_state_reg & PCISTATE_BUS_32BIT) != 0)
@@ -10702,8 +10706,19 @@
 	/* Various workaround register access methods */
 	if (tp->tg3_flags & TG3_FLAG_PCIX_TARGET_HWBUG)
 		tp->write32 = tg3_write_indirect_reg32;
-	else if (tp->tg3_flags & TG3_FLAG_5701_REG_WRITE_BUG)
+	else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701 ||
+		 ((tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) &&
+		  tp->pci_chip_rev_id == CHIPREV_ID_5750_A0)) {
+		/*
+		 * Back to back register writes can cause problems on these
+		 * chips, the workaround is to read back all reg writes
+		 * except those to mailbox regs.
+		 *
+		 * See tg3_write_indirect_reg32().
+		 */
 		tp->write32 = tg3_write_flush_reg32;
+	}
+
 
 	if ((tp->tg3_flags & TG3_FLAG_TXD_MBOX_HWBUG) ||
 	    (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)) {
@@ -11892,10 +11907,6 @@
 		tp->rx_pending = 63;
 	}
 
-	if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) ||
-	    (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714))
-		tp->pdev_peer = tg3_find_peer(tp);
-
 	err = tg3_get_device_address(tp);
 	if (err) {
 		printk(KERN_ERR PFX "Could not obtain valid ethernet address, "
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index d515ed2..dcdfc08 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -131,6 +131,7 @@
 #define  CHIPREV_ID_5752_A0_HW		 0x5000
 #define  CHIPREV_ID_5752_A0		 0x6000
 #define  CHIPREV_ID_5752_A1		 0x6001
+#define  CHIPREV_ID_5714_A2		 0x9002
 #define  CHIPREV_ID_5906_A1		 0xc001
 #define  GET_ASIC_REV(CHIP_REV_ID)	((CHIP_REV_ID) >> 12)
 #define   ASIC_REV_5700			 0x07
@@ -2199,7 +2200,6 @@
 #define TG3_FLAG_USE_LINKCHG_REG	0x00000008
 #define TG3_FLAG_USE_MI_INTERRUPT	0x00000010
 #define TG3_FLAG_ENABLE_ASF		0x00000020
-#define TG3_FLAG_5701_REG_WRITE_BUG	0x00000040
 #define TG3_FLAG_POLL_SERDES		0x00000080
 #define TG3_FLAG_MBOX_WRITE_REORDER	0x00000100
 #define TG3_FLAG_PCIX_TARGET_HWBUG	0x00000200
@@ -2215,14 +2215,14 @@
 #define TG3_FLAG_PCI_32BIT		0x00080000
 #define TG3_FLAG_SRAM_USE_CONFIG	0x00100000
 #define TG3_FLAG_TX_RECOVERY_PENDING	0x00200000
-#define TG3_FLAG_SERDES_WOL_CAP		0x00400000
+#define TG3_FLAG_WOL_CAP		0x00400000
 #define TG3_FLAG_JUMBO_RING_ENABLE	0x00800000
 #define TG3_FLAG_10_100_ONLY		0x01000000
 #define TG3_FLAG_PAUSE_AUTONEG		0x02000000
 #define TG3_FLAG_IN_RESET_TASK		0x04000000
 #define TG3_FLAG_40BIT_DMA_BUG		0x08000000
 #define TG3_FLAG_BROKEN_CHECKSUMS	0x10000000
-#define TG3_FLAG_GOT_SERDES_FLOWCTL	0x20000000
+#define TG3_FLAG_SUPPORT_MSI		0x20000000
 #define TG3_FLAG_CHIP_RESETTING		0x40000000
 #define TG3_FLAG_INIT_COMPLETE		0x80000000
 	u32				tg3_flags2;
diff --git a/drivers/net/tokenring/madgemc.c b/drivers/net/tokenring/madgemc.c
index ed274d6..f8f4d74 100644
--- a/drivers/net/tokenring/madgemc.c
+++ b/drivers/net/tokenring/madgemc.c
@@ -23,7 +23,6 @@
 #include <linux/mca.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
-#include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/netdevice.h>
 #include <linux/trdevice.h>
diff --git a/drivers/net/tokenring/smctr.c b/drivers/net/tokenring/smctr.c
index 9bbea5c..58d7e5d 100644
--- a/drivers/net/tokenring/smctr.c
+++ b/drivers/net/tokenring/smctr.c
@@ -41,7 +41,6 @@
 #include <linux/time.h>
 #include <linux/errno.h>
 #include <linux/init.h>
-#include <linux/pci.h>
 #include <linux/mca-legacy.h>
 #include <linux/delay.h>
 #include <linux/netdevice.h>
diff --git a/drivers/net/tulip/21142.c b/drivers/net/tulip/21142.c
index 942b839..6c400cc 100644
--- a/drivers/net/tulip/21142.c
+++ b/drivers/net/tulip/21142.c
@@ -14,7 +14,6 @@
 
 */
 
-#include <linux/pci.h>
 #include <linux/delay.h>
 #include "tulip.h"
 
diff --git a/drivers/net/tulip/pnic.c b/drivers/net/tulip/pnic.c
index 85a521e..be82a2e 100644
--- a/drivers/net/tulip/pnic.c
+++ b/drivers/net/tulip/pnic.c
@@ -15,7 +15,6 @@
 */
 
 #include <linux/kernel.h>
-#include <linux/pci.h>
 #include <linux/jiffies.h>
 #include "tulip.h"
 
diff --git a/drivers/net/tulip/pnic2.c b/drivers/net/tulip/pnic2.c
index c31be0e..4e4a879 100644
--- a/drivers/net/tulip/pnic2.c
+++ b/drivers/net/tulip/pnic2.c
@@ -76,7 +76,6 @@
 
 
 
-#include <linux/pci.h>
 #include "tulip.h"
 #include <linux/delay.h>
 
diff --git a/drivers/net/tulip/timer.c b/drivers/net/tulip/timer.c
index df326fe..d2c1f42 100644
--- a/drivers/net/tulip/timer.c
+++ b/drivers/net/tulip/timer.c
@@ -14,7 +14,6 @@
 
 */
 
-#include <linux/pci.h>
 #include "tulip.h"
 
 
diff --git a/drivers/net/tulip/tulip.h b/drivers/net/tulip/tulip.h
index c840d2e..16f26a8 100644
--- a/drivers/net/tulip/tulip.h
+++ b/drivers/net/tulip/tulip.h
@@ -22,6 +22,7 @@
 #include <linux/netdevice.h>
 #include <linux/timer.h>
 #include <linux/delay.h>
+#include <linux/pci.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 
diff --git a/drivers/net/wan/lmc/lmc_media.c b/drivers/net/wan/lmc/lmc_media.c
index ae01555..574737b 100644
--- a/drivers/net/wan/lmc/lmc_media.c
+++ b/drivers/net/wan/lmc/lmc_media.c
@@ -8,7 +8,6 @@
 #include <linux/ioport.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
-#include <linux/pci.h>
 #include <linux/in.h>
 #include <linux/if_arp.h>
 #include <linux/netdevice.h>
diff --git a/drivers/net/wan/lmc/lmc_proto.c b/drivers/net/wan/lmc/lmc_proto.c
index 74876c0..31e17995 100644
--- a/drivers/net/wan/lmc/lmc_proto.c
+++ b/drivers/net/wan/lmc/lmc_proto.c
@@ -27,7 +27,6 @@
 #include <linux/ioport.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
-#include <linux/pci.h>
 #include <linux/in.h>
 #include <linux/if_arp.h>
 #include <linux/netdevice.h>
diff --git a/drivers/net/wan/pc300_tty.c b/drivers/net/wan/pc300_tty.c
index 07dbdfb..e24a7b0 100644
--- a/drivers/net/wan/pc300_tty.c
+++ b/drivers/net/wan/pc300_tty.c
@@ -38,7 +38,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/pci.h>
 #include <linux/errno.h>
 #include <linux/string.h>
 #include <linux/init.h>
diff --git a/drivers/net/wireless/strip.c b/drivers/net/wireless/strip.c
index 2a299a0..ef32a5c 100644
--- a/drivers/net/wireless/strip.c
+++ b/drivers/net/wireless/strip.c
@@ -1971,8 +1971,7 @@
 		      sizeof(zero_address))) {
 		struct net_device *dev;
 		read_lock_bh(&dev_base_lock);
-		dev = dev_base;
-		while (dev) {
+		for_each_netdev(dev) {
 			if (dev->type == strip_info->dev->type &&
 			    !memcmp(dev->dev_addr,
 				    &strip_info->true_dev_addr,
@@ -1983,7 +1982,6 @@
 				read_unlock_bh(&dev_base_lock);
 				return (dev);
 			}
-			dev = dev->next;
 		}
 		read_unlock_bh(&dev_base_lock);
 	}
diff --git a/drivers/parisc/hppb.c b/drivers/parisc/hppb.c
index 9bb4db5..a68b3b3 100644
--- a/drivers/parisc/hppb.c
+++ b/drivers/parisc/hppb.c
@@ -22,8 +22,6 @@
 #include <asm/hardware.h>
 #include <asm/parisc-device.h>
 
-#include <linux/pci.h>
-
 struct hppb_card {
 	unsigned long hpa;
 	struct resource mmio_region;
diff --git a/drivers/parisc/led.c b/drivers/parisc/led.c
index 3df82fe..98be288 100644
--- a/drivers/parisc/led.c
+++ b/drivers/parisc/led.c
@@ -365,7 +365,7 @@
 	 * for reading should be OK */
 	read_lock(&dev_base_lock);
 	rcu_read_lock();
-	for (dev = dev_base; dev; dev = dev->next) {
+	for_each_netdev(dev) {
 	    struct net_device_stats *stats;
 	    struct in_device *in_dev = __in_dev_get_rcu(dev);
 	    if (!in_dev || !in_dev->ifa_list)
diff --git a/drivers/parisc/pdc_stable.c b/drivers/parisc/pdc_stable.c
index ea1b7a6..815e445 100644
--- a/drivers/parisc/pdc_stable.c
+++ b/drivers/parisc/pdc_stable.c
@@ -520,17 +520,17 @@
 
 /**
  * pdcs_size_read - Stable Storage size output.
- * @entry: An allocated and populated subsytem struct. We don't use it tho.
+ * @kset: An allocated and populated struct kset. We don't use it tho.
  * @buf: The output buffer to write to.
  */
 static ssize_t
-pdcs_size_read(struct subsystem *entry, char *buf)
+pdcs_size_read(struct kset *kset, char *buf)
 {
 	char *out = buf;
-	
-	if (!entry || !buf)
+
+	if (!kset || !buf)
 		return -EINVAL;
-		
+
 	/* show the size of the stable storage */
 	out += sprintf(out, "%ld\n", pdcs_size);
 
@@ -539,17 +539,17 @@
 
 /**
  * pdcs_auto_read - Stable Storage autoboot/search flag output.
- * @entry: An allocated and populated subsytem struct. We don't use it tho.
+ * @kset: An allocated and populated struct kset. We don't use it tho.
  * @buf: The output buffer to write to.
  * @knob: The PF_AUTOBOOT or PF_AUTOSEARCH flag
  */
 static ssize_t
-pdcs_auto_read(struct subsystem *entry, char *buf, int knob)
+pdcs_auto_read(struct kset *kset, char *buf, int knob)
 {
 	char *out = buf;
 	struct pdcspath_entry *pathentry;
 
-	if (!entry || !buf)
+	if (!kset || !buf)
 		return -EINVAL;
 
 	/* Current flags are stored in primary boot path entry */
@@ -565,40 +565,40 @@
 
 /**
  * pdcs_autoboot_read - Stable Storage autoboot flag output.
- * @entry: An allocated and populated subsytem struct. We don't use it tho.
+ * @kset: An allocated and populated struct kset. We don't use it tho.
  * @buf: The output buffer to write to.
  */
 static inline ssize_t
-pdcs_autoboot_read(struct subsystem *entry, char *buf)
+pdcs_autoboot_read(struct kset *kset, char *buf)
 {
-	return pdcs_auto_read(entry, buf, PF_AUTOBOOT);
+	return pdcs_auto_read(kset, buf, PF_AUTOBOOT);
 }
 
 /**
  * pdcs_autosearch_read - Stable Storage autoboot flag output.
- * @entry: An allocated and populated subsytem struct. We don't use it tho.
+ * @kset: An allocated and populated struct kset. We don't use it tho.
  * @buf: The output buffer to write to.
  */
 static inline ssize_t
-pdcs_autosearch_read(struct subsystem *entry, char *buf)
+pdcs_autosearch_read(struct kset *kset, char *buf)
 {
-	return pdcs_auto_read(entry, buf, PF_AUTOSEARCH);
+	return pdcs_auto_read(kset, buf, PF_AUTOSEARCH);
 }
 
 /**
  * pdcs_timer_read - Stable Storage timer count output (in seconds).
- * @entry: An allocated and populated subsytem struct. We don't use it tho.
+ * @kset: An allocated and populated struct kset. We don't use it tho.
  * @buf: The output buffer to write to.
  *
  * The value of the timer field correponds to a number of seconds in powers of 2.
  */
 static ssize_t
-pdcs_timer_read(struct subsystem *entry, char *buf)
+pdcs_timer_read(struct kset *kset, char *buf)
 {
 	char *out = buf;
 	struct pdcspath_entry *pathentry;
 
-	if (!entry || !buf)
+	if (!kset || !buf)
 		return -EINVAL;
 
 	/* Current flags are stored in primary boot path entry */
@@ -615,15 +615,15 @@
 
 /**
  * pdcs_osid_read - Stable Storage OS ID register output.
- * @entry: An allocated and populated subsytem struct. We don't use it tho.
+ * @kset: An allocated and populated struct kset. We don't use it tho.
  * @buf: The output buffer to write to.
  */
 static ssize_t
-pdcs_osid_read(struct subsystem *entry, char *buf)
+pdcs_osid_read(struct kset *kset, char *buf)
 {
 	char *out = buf;
 
-	if (!entry || !buf)
+	if (!kset || !buf)
 		return -EINVAL;
 
 	out += sprintf(out, "%s dependent data (0x%.4x)\n",
@@ -634,18 +634,18 @@
 
 /**
  * pdcs_osdep1_read - Stable Storage OS-Dependent data area 1 output.
- * @entry: An allocated and populated subsytem struct. We don't use it tho.
+ * @kset: An allocated and populated struct kset. We don't use it tho.
  * @buf: The output buffer to write to.
  *
  * This can hold 16 bytes of OS-Dependent data.
  */
 static ssize_t
-pdcs_osdep1_read(struct subsystem *entry, char *buf)
+pdcs_osdep1_read(struct kset *kset, char *buf)
 {
 	char *out = buf;
 	u32 result[4];
 
-	if (!entry || !buf)
+	if (!kset || !buf)
 		return -EINVAL;
 
 	if (pdc_stable_read(PDCS_ADDR_OSD1, &result, sizeof(result)) != PDC_OK)
@@ -661,18 +661,18 @@
 
 /**
  * pdcs_diagnostic_read - Stable Storage Diagnostic register output.
- * @entry: An allocated and populated subsytem struct. We don't use it tho.
+ * @kset: An allocated and populated struct kset. We don't use it tho.
  * @buf: The output buffer to write to.
  *
  * I have NFC how to interpret the content of that register ;-).
  */
 static ssize_t
-pdcs_diagnostic_read(struct subsystem *entry, char *buf)
+pdcs_diagnostic_read(struct kset *kset, char *buf)
 {
 	char *out = buf;
 	u32 result;
 
-	if (!entry || !buf)
+	if (!kset || !buf)
 		return -EINVAL;
 
 	/* get diagnostic */
@@ -686,18 +686,18 @@
 
 /**
  * pdcs_fastsize_read - Stable Storage FastSize register output.
- * @entry: An allocated and populated subsytem struct. We don't use it tho.
+ * @kset: An allocated and populated struct kset. We don't use it tho.
  * @buf: The output buffer to write to.
  *
  * This register holds the amount of system RAM to be tested during boot sequence.
  */
 static ssize_t
-pdcs_fastsize_read(struct subsystem *entry, char *buf)
+pdcs_fastsize_read(struct kset *kset, char *buf)
 {
 	char *out = buf;
 	u32 result;
 
-	if (!entry || !buf)
+	if (!kset || !buf)
 		return -EINVAL;
 
 	/* get fast-size */
@@ -715,13 +715,13 @@
 
 /**
  * pdcs_osdep2_read - Stable Storage OS-Dependent data area 2 output.
- * @entry: An allocated and populated subsytem struct. We don't use it tho.
+ * @kset: An allocated and populated struct kset. We don't use it tho.
  * @buf: The output buffer to write to.
  *
  * This can hold pdcs_size - 224 bytes of OS-Dependent data, when available.
  */
 static ssize_t
-pdcs_osdep2_read(struct subsystem *entry, char *buf)
+pdcs_osdep2_read(struct kset *kset, char *buf)
 {
 	char *out = buf;
 	unsigned long size;
@@ -733,7 +733,7 @@
 
 	size = pdcs_size - 224;
 
-	if (!entry || !buf)
+	if (!kset || !buf)
 		return -EINVAL;
 
 	for (i=0; i<size; i+=4) {
@@ -748,7 +748,7 @@
 
 /**
  * pdcs_auto_write - This function handles autoboot/search flag modifying.
- * @entry: An allocated and populated subsytem struct. We don't use it tho.
+ * @kset: An allocated and populated struct kset. We don't use it tho.
  * @buf: The input buffer to read from.
  * @count: The number of bytes to be read.
  * @knob: The PF_AUTOBOOT or PF_AUTOSEARCH flag
@@ -758,7 +758,7 @@
  *	\"n\" (n == 0 or 1) to toggle AutoBoot Off or On
  */
 static ssize_t
-pdcs_auto_write(struct subsystem *entry, const char *buf, size_t count, int knob)
+pdcs_auto_write(struct kset *kset, const char *buf, size_t count, int knob)
 {
 	struct pdcspath_entry *pathentry;
 	unsigned char flags;
@@ -768,7 +768,7 @@
 	if (!capable(CAP_SYS_ADMIN))
 		return -EACCES;
 
-	if (!entry || !buf || !count)
+	if (!kset || !buf || !count)
 		return -EINVAL;
 
 	/* We'll use a local copy of buf */
@@ -823,7 +823,7 @@
 
 /**
  * pdcs_autoboot_write - This function handles autoboot flag modifying.
- * @entry: An allocated and populated subsytem struct. We don't use it tho.
+ * @kset: An allocated and populated struct kset. We don't use it tho.
  * @buf: The input buffer to read from.
  * @count: The number of bytes to be read.
  *
@@ -832,14 +832,14 @@
  *	\"n\" (n == 0 or 1) to toggle AutoSearch Off or On
  */
 static inline ssize_t
-pdcs_autoboot_write(struct subsystem *entry, const char *buf, size_t count)
+pdcs_autoboot_write(struct kset *kset, const char *buf, size_t count)
 {
-	return pdcs_auto_write(entry, buf, count, PF_AUTOBOOT);
+	return pdcs_auto_write(kset, buf, count, PF_AUTOBOOT);
 }
 
 /**
  * pdcs_autosearch_write - This function handles autosearch flag modifying.
- * @entry: An allocated and populated subsytem struct. We don't use it tho.
+ * @kset: An allocated and populated struct kset. We don't use it tho.
  * @buf: The input buffer to read from.
  * @count: The number of bytes to be read.
  *
@@ -848,14 +848,14 @@
  *	\"n\" (n == 0 or 1) to toggle AutoSearch Off or On
  */
 static inline ssize_t
-pdcs_autosearch_write(struct subsystem *entry, const char *buf, size_t count)
+pdcs_autosearch_write(struct kset *kset, const char *buf, size_t count)
 {
-	return pdcs_auto_write(entry, buf, count, PF_AUTOSEARCH);
+	return pdcs_auto_write(kset, buf, count, PF_AUTOSEARCH);
 }
 
 /**
  * pdcs_osdep1_write - Stable Storage OS-Dependent data area 1 input.
- * @entry: An allocated and populated subsytem struct. We don't use it tho.
+ * @kset: An allocated and populated struct kset. We don't use it tho.
  * @buf: The input buffer to read from.
  * @count: The number of bytes to be read.
  *
@@ -864,14 +864,14 @@
  * its input buffer.
  */
 static ssize_t
-pdcs_osdep1_write(struct subsystem *entry, const char *buf, size_t count)
+pdcs_osdep1_write(struct kset *kset, const char *buf, size_t count)
 {
 	u8 in[16];
 
 	if (!capable(CAP_SYS_ADMIN))
 		return -EACCES;
 
-	if (!entry || !buf || !count)
+	if (!kset || !buf || !count)
 		return -EINVAL;
 
 	if (unlikely(pdcs_osid != OS_ID_LINUX))
@@ -892,7 +892,7 @@
 
 /**
  * pdcs_osdep2_write - Stable Storage OS-Dependent data area 2 input.
- * @entry: An allocated and populated subsytem struct. We don't use it tho.
+ * @kset: An allocated and populated struct kset. We don't use it tho.
  * @buf: The input buffer to read from.
  * @count: The number of bytes to be read.
  *
@@ -901,7 +901,7 @@
  * constructing its input buffer.
  */
 static ssize_t
-pdcs_osdep2_write(struct subsystem *entry, const char *buf, size_t count)
+pdcs_osdep2_write(struct kset *kset, const char *buf, size_t count)
 {
 	unsigned long size;
 	unsigned short i;
@@ -910,7 +910,7 @@
 	if (!capable(CAP_SYS_ADMIN))
 		return -EACCES;
 
-	if (!entry || !buf || !count)
+	if (!kset || !buf || !count)
 		return -EINVAL;
 
 	if (unlikely(pdcs_size <= 224))
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
index 5ea5bc7..7a1d6d5 100644
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -1,10 +1,14 @@
 #
 # PCI configuration
 #
+config ARCH_SUPPORTS_MSI
+	bool
+	default n
+
 config PCI_MSI
 	bool "Message Signaled Interrupts (MSI and MSI-X)"
 	depends on PCI
-	depends on (X86_LOCAL_APIC && X86_IO_APIC) || IA64 || SPARC64
+	depends on ARCH_SUPPORTS_MSI
 	help
 	   This allows device drivers to enable MSI (Message Signaled
 	   Interrupts).  Message Signaled Interrupts enable a device to
@@ -17,31 +21,6 @@
 
 	   If you don't know what to do here, say N.
 
-config PCI_MULTITHREAD_PROBE
-	bool "PCI Multi-threaded probe (EXPERIMENTAL)"
-	depends on PCI && EXPERIMENTAL && BROKEN
-	help
-	  Say Y here if you want the PCI core to spawn a new thread for
-	  every PCI device that is probed.  This can cause a huge
-	  speedup in boot times on multiprocessor machines, and even a
-	  smaller speedup on single processor machines.
-
-	  But it can also cause lots of bad things to happen.  A number
-	  of PCI drivers cannot properly handle running in this way,
-	  some will just not work properly at all, while others might
-	  decide to blow up power supplies with a huge load all at once,
-	  so use this option at your own risk.
-
-	  It is very unwise to use this option if you are not using a
-	  boot process that can handle devices being created in any
-	  order.  A program that can create persistent block and network
-	  device names (like udev) is a good idea if you wish to use
-	  this option.
-
-	  Again, use this option at your own risk, you have been warned!
-
-	  When in doubt, say N.
-
 config PCI_DEBUG
 	bool "PCI Debugging"
 	depends on PCI && DEBUG_KERNEL
diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c
index aadaa3c..9e5ea07 100644
--- a/drivers/pci/bus.c
+++ b/drivers/pci/bus.c
@@ -77,7 +77,7 @@
  * This adds a single pci device to the global
  * device list and adds sysfs and procfs entries
  */
-int __devinit pci_bus_add_device(struct pci_dev *dev)
+int pci_bus_add_device(struct pci_dev *dev)
 {
 	int retval;
 	retval = device_add(&dev->dev);
@@ -105,7 +105,7 @@
  *
  * Call hotplug for each new devices.
  */
-void __devinit pci_bus_add_devices(struct pci_bus *bus)
+void pci_bus_add_devices(struct pci_bus *bus)
 {
 	struct pci_dev *dev;
 	int retval;
diff --git a/drivers/pci/hotplug/Kconfig b/drivers/pci/hotplug/Kconfig
index be92695..63d6275 100644
--- a/drivers/pci/hotplug/Kconfig
+++ b/drivers/pci/hotplug/Kconfig
@@ -2,9 +2,7 @@
 # PCI Hotplug support
 #
 
-menu "PCI Hotplug Support"
-
-config HOTPLUG_PCI
+menuconfig HOTPLUG_PCI
 	tristate "Support for PCI Hotplug (EXPERIMENTAL)"
 	depends on PCI && EXPERIMENTAL && HOTPLUG
 	---help---
@@ -17,9 +15,10 @@
 
 	  When in doubt, say N.
 
+if HOTPLUG_PCI
+
 config HOTPLUG_PCI_FAKE
 	tristate "Fake PCI Hotplug driver"
-	depends on HOTPLUG_PCI
 	help
 	  Say Y here if you want to use the fake PCI hotplug driver. It can
 	  be used to simulate PCI hotplug events if even if your system is
@@ -42,7 +41,7 @@
 
 config HOTPLUG_PCI_COMPAQ
 	tristate "Compaq PCI Hotplug driver"
-	depends on HOTPLUG_PCI && X86 && PCI_BIOS
+	depends on X86 && PCI_BIOS
 	help
 	  Say Y here if you have a motherboard with a Compaq PCI Hotplug
 	  controller.
@@ -64,7 +63,7 @@
 
 config HOTPLUG_PCI_IBM
 	tristate "IBM PCI Hotplug driver"
-	depends on HOTPLUG_PCI && X86_IO_APIC && X86 && PCI_BIOS
+	depends on X86_IO_APIC && X86 && PCI_BIOS
 	help
 	  Say Y here if you have a motherboard with a IBM PCI Hotplug
 	  controller.
@@ -76,7 +75,6 @@
 
 config HOTPLUG_PCI_ACPI
 	tristate "ACPI PCI Hotplug driver"
-	depends on HOTPLUG_PCI
 	depends on (!ACPI_DOCK && ACPI) || (ACPI_DOCK)
 	help
 	  Say Y here if you have a system that supports PCI Hotplug using
@@ -101,7 +99,6 @@
 
 config HOTPLUG_PCI_CPCI
 	bool "CompactPCI Hotplug driver"
-	depends on HOTPLUG_PCI
 	help
 	  Say Y here if you have a CompactPCI system card with CompactPCI
 	  hotswap support per the PICMG 2.1 specification.
@@ -110,7 +107,7 @@
 
 config HOTPLUG_PCI_CPCI_ZT5550
 	tristate "Ziatech ZT5550 CompactPCI Hotplug driver"
-	depends on HOTPLUG_PCI && HOTPLUG_PCI_CPCI && X86
+	depends on HOTPLUG_PCI_CPCI && X86
 	help
 	  Say Y here if you have an Performance Technologies (formerly Intel,
           formerly just Ziatech) Ziatech ZT5550 CompactPCI system card.
@@ -122,7 +119,7 @@
 
 config HOTPLUG_PCI_CPCI_GENERIC
 	tristate "Generic port I/O CompactPCI Hotplug driver"
-	depends on HOTPLUG_PCI && HOTPLUG_PCI_CPCI && X86
+	depends on HOTPLUG_PCI_CPCI && X86
 	help
 	  Say Y here if you have a CompactPCI system card that exposes the #ENUM
 	  hotswap signal as a bit in a system register that can be read through
@@ -135,7 +132,6 @@
 
 config HOTPLUG_PCI_SHPC
 	tristate "SHPC PCI Hotplug driver"
-	depends on HOTPLUG_PCI
 	help
 	  Say Y here if you have a motherboard with a SHPC PCI Hotplug
 	  controller.
@@ -147,7 +143,7 @@
 
 config HOTPLUG_PCI_RPA
 	tristate "RPA PCI Hotplug driver"
-	depends on HOTPLUG_PCI && PPC_PSERIES && PPC64 && !HOTPLUG_PCI_FAKE
+	depends on PPC_PSERIES && PPC64 && !HOTPLUG_PCI_FAKE
 	help
 	  Say Y here if you have a RPA system that supports PCI Hotplug.
 
@@ -170,12 +166,11 @@
 
 config HOTPLUG_PCI_SGI
 	tristate "SGI PCI Hotplug Support"
-	depends on HOTPLUG_PCI && (IA64_SGI_SN2 || IA64_GENERIC)
+	depends on IA64_SGI_SN2 || IA64_GENERIC
 	help
 	  Say Y here if you want to use the SGI Altix Hotplug
 	  Driver for PCI devices.
 
 	  When in doubt, say N.
 
-endmenu
-
+endif # HOTPLUG_PCI
diff --git a/drivers/pci/hotplug/acpiphp_ibm.c b/drivers/pci/hotplug/acpiphp_ibm.c
index 7f03881..e7322c2 100644
--- a/drivers/pci/hotplug/acpiphp_ibm.c
+++ b/drivers/pci/hotplug/acpiphp_ibm.c
@@ -424,7 +424,7 @@
 	int retval = 0;
 	acpi_status status;
 	struct acpi_device *device;
-	struct kobject *sysdir = &pci_hotplug_slots_subsys.kset.kobj;
+	struct kobject *sysdir = &pci_hotplug_slots_subsys.kobj;
 
 	dbg("%s\n", __FUNCTION__);
 
@@ -471,7 +471,7 @@
 static void __exit ibm_acpiphp_exit(void)
 {
 	acpi_status status;
-	struct kobject *sysdir = &pci_hotplug_slots_subsys.kset.kobj;
+	struct kobject *sysdir = &pci_hotplug_slots_subsys.kobj;
 
 	dbg("%s\n", __FUNCTION__);
 
diff --git a/drivers/pci/hotplug/cpcihp_zt5550.c b/drivers/pci/hotplug/cpcihp_zt5550.c
index 1c12e91..41f6a8d 100644
--- a/drivers/pci/hotplug/cpcihp_zt5550.c
+++ b/drivers/pci/hotplug/cpcihp_zt5550.c
@@ -296,13 +296,17 @@
 static int __init zt5550_init(void)
 {
 	struct resource* r;
+	int rc;
 
 	info(DRIVER_DESC " version: " DRIVER_VERSION);
 	r = request_region(ENUM_PORT, 1, "#ENUM hotswap signal register");
 	if(!r)
 		return -EBUSY;
 
-	return pci_register_driver(&zt5550_hc_driver);
+	rc = pci_register_driver(&zt5550_hc_driver);
+	if(rc < 0)
+		release_region(ENUM_PORT, 1);
+	return rc;
 }
 
 static void __exit
diff --git a/drivers/pci/hotplug/fakephp.c b/drivers/pci/hotplug/fakephp.c
index e27907c..027f686 100644
--- a/drivers/pci/hotplug/fakephp.c
+++ b/drivers/pci/hotplug/fakephp.c
@@ -238,7 +238,7 @@
 {
 	unsigned int devfn;
 	struct pci_dev *dev;
-	dev = kzalloc(sizeof(struct pci_dev), GFP_KERNEL);
+	dev = alloc_pci_dev();
 	if (!dev)
 		return;
 
diff --git a/drivers/pci/hotplug/pci_hotplug_core.c b/drivers/pci/hotplug/pci_hotplug_core.c
index f5d632e..63f3bd1 100644
--- a/drivers/pci/hotplug/pci_hotplug_core.c
+++ b/drivers/pci/hotplug/pci_hotplug_core.c
@@ -62,7 +62,7 @@
 
 static LIST_HEAD(pci_hotplug_slot_list);
 
-struct subsystem pci_hotplug_slots_subsys;
+struct kset pci_hotplug_slots_subsys;
 
 static ssize_t hotplug_slot_attr_show(struct kobject *kobj,
 		struct attribute *attr, char *buf)
@@ -764,7 +764,7 @@
 {
 	int result;
 
-	kset_set_kset_s(&pci_hotplug_slots_subsys, pci_bus_type.subsys);
+	kobj_set_kset_s(&pci_hotplug_slots_subsys, pci_bus_type.subsys);
 	result = subsystem_register(&pci_hotplug_slots_subsys);
 	if (result) {
 		err("Register subsys with error %d\n", result);
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h
index d19fcae..ccc5762 100644
--- a/drivers/pci/hotplug/pciehp.h
+++ b/drivers/pci/hotplug/pciehp.h
@@ -43,6 +43,7 @@
 extern int pciehp_poll_time;
 extern int pciehp_debug;
 extern int pciehp_force;
+extern struct workqueue_struct *pciehp_wq;
 
 #define dbg(format, arg...)						\
 	do {								\
@@ -70,14 +71,16 @@
 	struct list_head	slot_list;
 	char name[SLOT_NAME_SIZE];
 	unsigned long last_emi_toggle;
+	struct delayed_work work;	/* work for button event */
+	struct mutex lock;
 };
 
 struct event_info {
 	u32 event_type;
-	u8 hp_slot;
+	struct slot *p_slot;
+	struct work_struct work;
 };
 
-#define MAX_EVENTS		10
 struct controller {
 	struct controller *next;
 	struct mutex crit_sect;		/* critical section mutex */
@@ -86,11 +89,9 @@
 	int slot_num_inc;		/* 1 or -1 */
 	struct pci_dev *pci_dev;
 	struct list_head slot_list;
-	struct event_info event_queue[MAX_EVENTS];
 	struct slot *slot;
 	struct hpc_ops *hpc_ops;
 	wait_queue_head_t queue;	/* sleep & wake process */
-	u8 next_event;
 	u8 bus;
 	u8 device;
 	u8 function;
@@ -149,21 +150,17 @@
 #define HP_SUPR_RM(cap)		(cap & HP_SUPR_RM_SUP)
 #define EMI(cap)		(cap & EMI_PRSN)
 
-extern int pciehp_event_start_thread(void);
-extern void pciehp_event_stop_thread(void);
-extern int pciehp_enable_slot(struct slot *slot);
-extern int pciehp_disable_slot(struct slot *slot);
+extern int pciehp_sysfs_enable_slot(struct slot *slot);
+extern int pciehp_sysfs_disable_slot(struct slot *slot);
 extern u8 pciehp_handle_attention_button(u8 hp_slot, struct controller *ctrl);
 extern u8 pciehp_handle_switch_change(u8 hp_slot, struct controller *ctrl);
 extern u8 pciehp_handle_presence_change(u8 hp_slot, struct controller *ctrl);
 extern u8 pciehp_handle_power_fault(u8 hp_slot, struct controller *ctrl);
 extern int pciehp_configure_device(struct slot *p_slot);
 extern int pciehp_unconfigure_device(struct slot *p_slot);
+extern void pciehp_queue_pushbutton_work(struct work_struct *work);
 int pcie_init(struct controller *ctrl, struct pcie_device *dev);
 
-/* Global variables */
-extern struct controller *pciehp_ctrl_list;
-
 static inline struct slot *pciehp_find_slot(struct controller *ctrl, u8 device)
 {
 	struct slot *slot;
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c
index a92eda6..e5d3f0b 100644
--- a/drivers/pci/hotplug/pciehp_core.c
+++ b/drivers/pci/hotplug/pciehp_core.c
@@ -41,7 +41,7 @@
 int pciehp_poll_mode;
 int pciehp_poll_time;
 int pciehp_force;
-struct controller *pciehp_ctrl_list;
+struct workqueue_struct *pciehp_wq;
 
 #define DRIVER_VERSION	"0.4"
 #define DRIVER_AUTHOR	"Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>, Dely Sy <dely.l.sy@intel.com>"
@@ -62,7 +62,6 @@
 
 #define PCIE_MODULE_NAME "pciehp"
 
-static int pcie_start_thread (void);
 static int set_attention_status (struct hotplug_slot *slot, u8 value);
 static int enable_slot		(struct hotplug_slot *slot);
 static int disable_slot		(struct hotplug_slot *slot);
@@ -229,6 +228,8 @@
 		slot->device = ctrl->slot_device_offset + i;
 		slot->hpc_ops = ctrl->hpc_ops;
 		slot->number = ctrl->first_slot;
+		mutex_init(&slot->lock);
+		INIT_DELAYED_WORK(&slot->work, pciehp_queue_pushbutton_work);
 
 		/* register this slot with the hotplug pci core */
 		hotplug_slot->private = slot;
@@ -286,6 +287,9 @@
 		if (EMI(ctrl->ctrlcap))
 			sysfs_remove_file(&slot->hotplug_slot->kobj,
 				&hotplug_slot_attr_lock.attr);
+		cancel_delayed_work(&slot->work);
+		flush_scheduled_work();
+		flush_workqueue(pciehp_wq);
 		pci_hp_deregister(slot->hotplug_slot);
 	}
 }
@@ -314,7 +318,7 @@
 
 	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
 
-	return pciehp_enable_slot(slot);
+	return pciehp_sysfs_enable_slot(slot);
 }
 
 
@@ -324,7 +328,7 @@
 
 	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
 
-	return pciehp_disable_slot(slot);
+	return pciehp_sysfs_disable_slot(slot);
 }
 
 static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value)
@@ -466,17 +470,6 @@
 
 	t_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset);
 
-	/*	Finish setting up the hot plug ctrl device */
-	ctrl->next_event = 0;
-
-	if (!pciehp_ctrl_list) {
-		pciehp_ctrl_list = ctrl;
-		ctrl->next = NULL;
-	} else {
-		ctrl->next = pciehp_ctrl_list;
-		pciehp_ctrl_list = ctrl;
-	}
-
 	t_slot->hpc_ops->get_adapter_status(t_slot, &value); /* Check if slot is occupied */
 	if ((POWER_CTRL(ctrl->ctrlcap)) && !value) {
 		rc = t_slot->hpc_ops->power_off_slot(t_slot); /* Power off slot if not occupied*/
@@ -496,48 +489,14 @@
 	return -ENODEV;
 }
 
-
-static int pcie_start_thread(void)
+static void pciehp_remove (struct pcie_device *dev)
 {
-	int retval = 0;
-	
-	dbg("Initialize + Start the notification/polling mechanism \n");
+	struct pci_dev *pdev = dev->port;
+	struct controller *ctrl = pci_get_drvdata(pdev);
 
-	retval = pciehp_event_start_thread();
-	if (retval) {
-		dbg("pciehp_event_start_thread() failed\n");
-		return retval;
-	}
-
-	return retval;
-}
-
-static void __exit unload_pciehpd(void)
-{
-	struct controller *ctrl;
-	struct controller *tctrl;
-
-	ctrl = pciehp_ctrl_list;
-
-	while (ctrl) {
-		cleanup_slots(ctrl);
-
-		ctrl->hpc_ops->release_ctlr(ctrl);
-
-		tctrl = ctrl;
-		ctrl = ctrl->next;
-
-		kfree(tctrl);
-	}
-
-	/* Stop the notification mechanism */
-	pciehp_event_stop_thread();
-
-}
-
-static void pciehp_remove (struct pcie_device *device)
-{
-	/* XXX - Needs to be adapted to device driver model */
+	cleanup_slots(ctrl);
+	ctrl->hpc_ops->release_ctlr(ctrl);
+	kfree(ctrl);
 }
 
 #ifdef CONFIG_PM
@@ -585,31 +544,18 @@
 	pciehp_poll_mode = 1;
 #endif
 
-	retval = pcie_start_thread();
-	if (retval)
-		goto error_hpc_init;
-
 	retval = pcie_port_service_register(&hpdriver_portdrv);
  	dbg("pcie_port_service_register = %d\n", retval);
   	info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
  	if (retval)
 		dbg("%s: Failure to register service\n", __FUNCTION__);
-
-error_hpc_init:
-	if (retval) {
-		pciehp_event_stop_thread();
-	};
-
 	return retval;
 }
 
 static void __exit pcied_cleanup(void)
 {
 	dbg("unload_pciehpd()\n");
-	unload_pciehpd();
-
 	pcie_port_service_unregister(&hpdriver_portdrv);
-
 	info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n");
 }
 
diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c
index 4283ef5..7f22caa 100644
--- a/drivers/pci/hotplug/pciehp_ctrl.c
+++ b/drivers/pci/hotplug/pciehp_ctrl.c
@@ -32,92 +32,61 @@
 #include <linux/types.h>
 #include <linux/smp_lock.h>
 #include <linux/pci.h>
+#include <linux/workqueue.h>
 #include "../pci.h"
 #include "pciehp.h"
 
-static void interrupt_event_handler(struct controller *ctrl);
+static void interrupt_event_handler(struct work_struct *work);
+static int pciehp_enable_slot(struct slot *p_slot);
+static int pciehp_disable_slot(struct slot *p_slot);
 
-static struct semaphore event_semaphore;	/* mutex for process loop (up if something to process) */
-static struct semaphore event_exit;		/* guard ensure thread has exited before calling it quits */
-static int event_finished;
-static unsigned long pushbutton_pending;	/* = 0 */
-static unsigned long surprise_rm_pending;	/* = 0 */
-
-static inline char *slot_name(struct slot *p_slot)
+static int queue_interrupt_event(struct slot *p_slot, u32 event_type)
 {
-	return p_slot->hotplug_slot->name;
+	struct event_info *info;
+
+	info = kmalloc(sizeof(*info), GFP_ATOMIC);
+	if (!info)
+		return -ENOMEM;
+
+	info->event_type = event_type;
+	info->p_slot = p_slot;
+	INIT_WORK(&info->work, interrupt_event_handler);
+
+	schedule_work(&info->work);
+
+	return 0;
 }
 
 u8 pciehp_handle_attention_button(u8 hp_slot, struct controller *ctrl)
 {
 	struct slot *p_slot;
-	u8 rc = 0;
-	u8 getstatus;
-	struct event_info *taskInfo;
+	u32 event_type;
 
 	/* Attention Button Change */
 	dbg("pciehp:  Attention button interrupt received.\n");
-	
-	/* This is the structure that tells the worker thread what to do */
-	taskInfo = &(ctrl->event_queue[ctrl->next_event]);
+
 	p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
 
-	p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
-	
-	ctrl->next_event = (ctrl->next_event + 1) % MAX_EVENTS;
-	taskInfo->hp_slot = hp_slot;
-
-	rc++;
-
 	/*
 	 *  Button pressed - See if need to TAKE ACTION!!!
 	 */
-	info("Button pressed on Slot(%s)\n", slot_name(p_slot));
-	taskInfo->event_type = INT_BUTTON_PRESS;
+	info("Button pressed on Slot(%s)\n", p_slot->name);
+	event_type = INT_BUTTON_PRESS;
 
-	if ((p_slot->state == BLINKINGON_STATE)
-	    || (p_slot->state == BLINKINGOFF_STATE)) {
-		/* Cancel if we are still blinking; this means that we press the
-		 * attention again before the 5 sec. limit expires to cancel hot-add
-		 * or hot-remove
-		 */
-		taskInfo->event_type = INT_BUTTON_CANCEL;
-		info("Button cancel on Slot(%s)\n", slot_name(p_slot));
-	} else if ((p_slot->state == POWERON_STATE)
-		   || (p_slot->state == POWEROFF_STATE)) {
-		/* Ignore if the slot is on power-on or power-off state; this 
-		 * means that the previous attention button action to hot-add or
-		 * hot-remove is undergoing
-		 */
-		taskInfo->event_type = INT_BUTTON_IGNORE;
-		info("Button ignore on Slot(%s)\n", slot_name(p_slot));
-	}
-
-	if (rc)
-		up(&event_semaphore);	/* signal event thread that new event is posted */
+	queue_interrupt_event(p_slot, event_type);
 
 	return 0;
-
 }
 
 u8 pciehp_handle_switch_change(u8 hp_slot, struct controller *ctrl)
 {
 	struct slot *p_slot;
-	u8 rc = 0;
 	u8 getstatus;
-	struct event_info *taskInfo;
+	u32 event_type;
 
 	/* Switch Change */
 	dbg("pciehp:  Switch interrupt received.\n");
 
-	/* This is the structure that tells the worker thread
-	 * what to do
-	 */
-	taskInfo = &(ctrl->event_queue[ctrl->next_event]);
-	ctrl->next_event = (ctrl->next_event + 1) % MAX_EVENTS;
-	taskInfo->hp_slot = hp_slot;
-
-	rc++;
 	p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
 	p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
 
@@ -125,39 +94,30 @@
 		/*
 		 * Switch opened
 		 */
-		info("Latch open on Slot(%s)\n", slot_name(p_slot));
-		taskInfo->event_type = INT_SWITCH_OPEN;
+		info("Latch open on Slot(%s)\n", p_slot->name);
+		event_type = INT_SWITCH_OPEN;
 	} else {
 		/*
 		 *  Switch closed
 		 */
-		info("Latch close on Slot(%s)\n", slot_name(p_slot));
-		taskInfo->event_type = INT_SWITCH_CLOSE;
+		info("Latch close on Slot(%s)\n", p_slot->name);
+		event_type = INT_SWITCH_CLOSE;
 	}
 
-	if (rc)
-		up(&event_semaphore);	/* signal event thread that new event is posted */
+	queue_interrupt_event(p_slot, event_type);
 
-	return rc;
+	return 1;
 }
 
 u8 pciehp_handle_presence_change(u8 hp_slot, struct controller *ctrl)
 {
 	struct slot *p_slot;
-	u8 presence_save, rc = 0;
-	struct event_info *taskInfo;
+	u32 event_type;
+	u8 presence_save;
 
 	/* Presence Change */
 	dbg("pciehp:  Presence/Notify input change.\n");
 
-	/* This is the structure that tells the worker thread
-	 * what to do
-	 */
-	taskInfo = &(ctrl->event_queue[ctrl->next_event]);
-	ctrl->next_event = (ctrl->next_event + 1) % MAX_EVENTS;
-	taskInfo->hp_slot = hp_slot;
-
-	rc++;
 	p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
 
 	/* Switch is open, assume a presence change
@@ -168,59 +128,49 @@
 		/*
 		 * Card Present
 		 */
-		info("Card present on Slot(%s)\n", slot_name(p_slot));
-		taskInfo->event_type = INT_PRESENCE_ON;
+		info("Card present on Slot(%s)\n", p_slot->name);
+		event_type = INT_PRESENCE_ON;
 	} else {
 		/*
 		 * Not Present
 		 */
-		info("Card not present on Slot(%s)\n", slot_name(p_slot));
-		taskInfo->event_type = INT_PRESENCE_OFF;
+		info("Card not present on Slot(%s)\n", p_slot->name);
+		event_type = INT_PRESENCE_OFF;
 	}
 
-	if (rc)
-		up(&event_semaphore);	/* signal event thread that new event is posted */
+	queue_interrupt_event(p_slot, event_type);
 
-	return rc;
+	return 1;
 }
 
 u8 pciehp_handle_power_fault(u8 hp_slot, struct controller *ctrl)
 {
 	struct slot *p_slot;
-	u8 rc = 0;
-	struct event_info *taskInfo;
+	u32 event_type;
 
 	/* power fault */
 	dbg("pciehp:  Power fault interrupt received.\n");
 
-	/* this is the structure that tells the worker thread
-	 * what to do
-	 */
-	taskInfo = &(ctrl->event_queue[ctrl->next_event]);
-	ctrl->next_event = (ctrl->next_event + 1) % MAX_EVENTS;
-	taskInfo->hp_slot = hp_slot;
-
-	rc++;
 	p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
 
 	if ( !(p_slot->hpc_ops->query_power_fault(p_slot))) {
 		/*
 		 * power fault Cleared
 		 */
-		info("Power fault cleared on Slot(%s)\n", slot_name(p_slot));
-		taskInfo->event_type = INT_POWER_FAULT_CLEAR;
+		info("Power fault cleared on Slot(%s)\n", p_slot->name);
+		event_type = INT_POWER_FAULT_CLEAR;
 	} else {
 		/*
 		 *   power fault
 		 */
-		info("Power fault on Slot(%s)\n", slot_name(p_slot));
-		taskInfo->event_type = INT_POWER_FAULT;
+		info("Power fault on Slot(%s)\n", p_slot->name);
+		event_type = INT_POWER_FAULT;
 		info("power fault bit %x set\n", hp_slot);
 	}
-	if (rc)
-		up(&event_semaphore);	/* signal event thread that new event is posted */
 
-	return rc;
+	queue_interrupt_event(p_slot, event_type);
+
+	return 1;
 }
 
 /* The following routines constitute the bulk of the 
@@ -357,13 +307,10 @@
 	return 0;
 }
 
-
-static void pushbutton_helper_thread(unsigned long data)
-{
-	pushbutton_pending = data;
-
-	up(&event_semaphore);
-}
+struct power_work_info {
+	struct slot *p_slot;
+	struct work_struct work;
+};
 
 /**
  * pciehp_pushbutton_thread
@@ -372,276 +319,214 @@
  * Handles all pending events and exits.
  *
  */
-static void pciehp_pushbutton_thread(unsigned long slot)
+static void pciehp_power_thread(struct work_struct *work)
 {
-	struct slot *p_slot = (struct slot *) slot;
-	u8 getstatus;
-	
-	pushbutton_pending = 0;
+	struct power_work_info *info =
+		container_of(work, struct power_work_info, work);
+	struct slot *p_slot = info->p_slot;
 
-	if (!p_slot) {
-		dbg("%s: Error! slot NULL\n", __FUNCTION__);
-		return;
-	}
-
-	p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
-	if (getstatus) {
-		p_slot->state = POWEROFF_STATE;
-		dbg("%s: disabling bus:device(%x:%x)\n", __FUNCTION__,
-				p_slot->bus, p_slot->device);
-
+	mutex_lock(&p_slot->lock);
+	switch (p_slot->state) {
+	case POWEROFF_STATE:
+		mutex_unlock(&p_slot->lock);
+		dbg("%s: disabling bus:device(%x:%x)\n",
+		    __FUNCTION__, p_slot->bus, p_slot->device);
 		pciehp_disable_slot(p_slot);
+		mutex_lock(&p_slot->lock);
 		p_slot->state = STATIC_STATE;
-	} else {
-		p_slot->state = POWERON_STATE;
-		dbg("%s: adding bus:device(%x:%x)\n", __FUNCTION__,
-				p_slot->bus, p_slot->device);
-
+		break;
+	case POWERON_STATE:
+		mutex_unlock(&p_slot->lock);
 		if (pciehp_enable_slot(p_slot) &&
 		    PWR_LED(p_slot->ctrl->ctrlcap))
 			p_slot->hpc_ops->green_led_off(p_slot);
-
+		mutex_lock(&p_slot->lock);
 		p_slot->state = STATIC_STATE;
+		break;
+	default:
+		break;
 	}
+	mutex_unlock(&p_slot->lock);
 
-	return;
+	kfree(info);
 }
 
-/**
- * pciehp_surprise_rm_thread
- *
- * Scheduled procedure to handle blocking stuff for the surprise removal
- * Handles all pending events and exits.
- *
- */
-static void pciehp_surprise_rm_thread(unsigned long slot)
+void pciehp_queue_pushbutton_work(struct work_struct *work)
 {
-	struct slot *p_slot = (struct slot *) slot;
-	u8 getstatus;
-	
-	surprise_rm_pending = 0;
+	struct slot *p_slot = container_of(work, struct slot, work.work);
+	struct power_work_info *info;
 
-	if (!p_slot) {
-		dbg("%s: Error! slot NULL\n", __FUNCTION__);
+	info = kmalloc(sizeof(*info), GFP_KERNEL);
+	if (!info) {
+		err("%s: Cannot allocate memory\n", __FUNCTION__);
 		return;
 	}
+	info->p_slot = p_slot;
+	INIT_WORK(&info->work, pciehp_power_thread);
 
-	p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
-	if (!getstatus) {
+	mutex_lock(&p_slot->lock);
+	switch (p_slot->state) {
+	case BLINKINGOFF_STATE:
 		p_slot->state = POWEROFF_STATE;
-		dbg("%s: removing bus:device(%x:%x)\n",
-				__FUNCTION__, p_slot->bus, p_slot->device);
-
-		pciehp_disable_slot(p_slot);
-		p_slot->state = STATIC_STATE;
-	} else {
+		break;
+	case BLINKINGON_STATE:
 		p_slot->state = POWERON_STATE;
-		dbg("%s: adding bus:device(%x:%x)\n",
-				__FUNCTION__, p_slot->bus, p_slot->device);
-
-		if (pciehp_enable_slot(p_slot) &&
-		    PWR_LED(p_slot->ctrl->ctrlcap))
-			p_slot->hpc_ops->green_led_off(p_slot);
-
-		p_slot->state = STATIC_STATE;
+		break;
+	default:
+		goto out;
 	}
-
-	return;
+	queue_work(pciehp_wq, &info->work);
+ out:
+	mutex_unlock(&p_slot->lock);
 }
 
-
-
-/* this is the main worker thread */
-static int event_thread(void* data)
-{
-	struct controller *ctrl;
-	lock_kernel();
-	daemonize("pciehpd_event");
-
-	unlock_kernel();
-
-	while (1) {
-		dbg("!!!!event_thread sleeping\n");
-		down_interruptible (&event_semaphore);
-		dbg("event_thread woken finished = %d\n", event_finished);
-		if (event_finished || signal_pending(current))
-			break;
-		/* Do stuff here */
-		if (pushbutton_pending)
-			pciehp_pushbutton_thread(pushbutton_pending);
-		else if (surprise_rm_pending)
-			pciehp_surprise_rm_thread(surprise_rm_pending);
-		else
-			for (ctrl = pciehp_ctrl_list; ctrl; ctrl=ctrl->next)
-				interrupt_event_handler(ctrl);
-	}
-	dbg("event_thread signals exit\n");
-	up(&event_exit);
-	return 0;
-}
-
-int pciehp_event_start_thread(void)
-{
-	int pid;
-
-	/* initialize our semaphores */
-	init_MUTEX_LOCKED(&event_exit);
-	event_finished=0;
-
-	init_MUTEX_LOCKED(&event_semaphore);
-	pid = kernel_thread(event_thread, NULL, 0);
-
-	if (pid < 0) {
-		err ("Can't start up our event thread\n");
-		return -1;
-	}
-	return 0;
-}
-
-
-void pciehp_event_stop_thread(void)
-{
-	event_finished = 1;
-	up(&event_semaphore);
-	down(&event_exit);
-}
-
-
 static int update_slot_info(struct slot *slot)
 {
 	struct hotplug_slot_info *info;
-	/* char buffer[SLOT_NAME_SIZE]; */
 	int result;
 
-	info = kmalloc(sizeof(struct hotplug_slot_info), GFP_KERNEL);
+	info = kmalloc(sizeof(*info), GFP_KERNEL);
 	if (!info)
 		return -ENOMEM;
 
-	/* make_slot_name (&buffer[0], SLOT_NAME_SIZE, slot); */
-
 	slot->hpc_ops->get_power_status(slot, &(info->power_status));
 	slot->hpc_ops->get_attention_status(slot, &(info->attention_status));
 	slot->hpc_ops->get_latch_status(slot, &(info->latch_status));
 	slot->hpc_ops->get_adapter_status(slot, &(info->adapter_status));
 
-	/* result = pci_hp_change_slot_info(buffer, info); */
 	result = pci_hp_change_slot_info(slot->hotplug_slot, info);
 	kfree (info);
 	return result;
 }
 
-static void interrupt_event_handler(struct controller *ctrl)
+/*
+ * Note: This function must be called with slot->lock held
+ */
+static void handle_button_press_event(struct slot *p_slot)
 {
-	int loop = 0;
-	int change = 1;
-	u8 hp_slot;
+	struct controller *ctrl = p_slot->ctrl;
 	u8 getstatus;
-	struct slot *p_slot;
 
-	while (change) {
-		change = 0;
+	switch (p_slot->state) {
+	case STATIC_STATE:
+		p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
+		if (getstatus) {
+			p_slot->state = BLINKINGOFF_STATE;
+			info("PCI slot #%s - powering off due to button "
+			     "press.\n", p_slot->name);
+		} else {
+			p_slot->state = BLINKINGON_STATE;
+			info("PCI slot #%s - powering on due to button "
+			     "press.\n", p_slot->name);
+		}
+		/* blink green LED and turn off amber */
+		if (PWR_LED(ctrl->ctrlcap))
+			p_slot->hpc_ops->green_led_blink(p_slot);
+		if (ATTN_LED(ctrl->ctrlcap))
+			p_slot->hpc_ops->set_attention_status(p_slot, 0);
 
-		for (loop = 0; loop < MAX_EVENTS; loop++) {
-			if (ctrl->event_queue[loop].event_type != 0) {
-				hp_slot = ctrl->event_queue[loop].hp_slot;
-
-				p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
-
-				if (ctrl->event_queue[loop].event_type == INT_BUTTON_CANCEL) {
-					dbg("button cancel\n");
-					del_timer(&p_slot->task_event);
-
-					switch (p_slot->state) {
-					case BLINKINGOFF_STATE:
-						if (PWR_LED(ctrl->ctrlcap))
-							p_slot->hpc_ops->green_led_on(p_slot);
-
-						if (ATTN_LED(ctrl->ctrlcap))
-							p_slot->hpc_ops->set_attention_status(p_slot, 0);
-						break;
-					case BLINKINGON_STATE:
-						if (PWR_LED(ctrl->ctrlcap))
-							p_slot->hpc_ops->green_led_off(p_slot);
-
-						if (ATTN_LED(ctrl->ctrlcap))
-							p_slot->hpc_ops->set_attention_status(p_slot, 0);
-						break;
-					default:
-						warn("Not a valid state\n");
-						return;
-					}
-					info("PCI slot #%s - action canceled due to button press.\n", slot_name(p_slot));
-					p_slot->state = STATIC_STATE;
-				}
-				/* ***********Button Pressed (No action on 1st press...) */
-				else if (ctrl->event_queue[loop].event_type == INT_BUTTON_PRESS) {
-					
-					if (ATTN_BUTTN(ctrl->ctrlcap)) {
-						dbg("Button pressed\n");
-						p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
-						if (getstatus) {
-							/* slot is on */
-							dbg("slot is on\n");
-							p_slot->state = BLINKINGOFF_STATE;
-							info("PCI slot #%s - powering off due to button press.\n", slot_name(p_slot));
-						} else {
-							/* slot is off */
-							dbg("slot is off\n");
-							p_slot->state = BLINKINGON_STATE;
-							info("PCI slot #%s - powering on due to button press.\n", slot_name(p_slot));
-						}
-
-						/* blink green LED and turn off amber */
-						if (PWR_LED(ctrl->ctrlcap))
-							p_slot->hpc_ops->green_led_blink(p_slot);
-
-						if (ATTN_LED(ctrl->ctrlcap))
-							p_slot->hpc_ops->set_attention_status(p_slot, 0);
-
-						init_timer(&p_slot->task_event);
-						p_slot->task_event.expires = jiffies + 5 * HZ;   /* 5 second delay */
-						p_slot->task_event.function = (void (*)(unsigned long)) pushbutton_helper_thread;
-						p_slot->task_event.data = (unsigned long) p_slot;
-
-						add_timer(&p_slot->task_event);
-					}
-				}
-				/***********POWER FAULT********************/
-				else if (ctrl->event_queue[loop].event_type == INT_POWER_FAULT) {
-					if (POWER_CTRL(ctrl->ctrlcap)) {
-						dbg("power fault\n");
-						if (ATTN_LED(ctrl->ctrlcap))
-							p_slot->hpc_ops->set_attention_status(p_slot, 1);
-
-						if (PWR_LED(ctrl->ctrlcap))
-							p_slot->hpc_ops->green_led_off(p_slot);
-					}
-				}
-				/***********SURPRISE REMOVAL********************/
-				else if ((ctrl->event_queue[loop].event_type == INT_PRESENCE_ON) || 
-					(ctrl->event_queue[loop].event_type == INT_PRESENCE_OFF)) {
-					if (HP_SUPR_RM(ctrl->ctrlcap)) {
-						dbg("Surprise Removal\n");
-						if (p_slot) {
-							surprise_rm_pending = (unsigned long) p_slot;
-							up(&event_semaphore);
-							update_slot_info(p_slot);
-						}
-					}
-				} else {
-					/* refresh notification */
-					if (p_slot)
-						update_slot_info(p_slot);
-				}
-
-				ctrl->event_queue[loop].event_type = 0;
-
-				change = 1;
-			}
-		}		/* End of FOR loop */
+		schedule_delayed_work(&p_slot->work, 5*HZ);
+		break;
+	case BLINKINGOFF_STATE:
+	case BLINKINGON_STATE:
+		/*
+		 * Cancel if we are still blinking; this means that we
+		 * press the attention again before the 5 sec. limit
+		 * expires to cancel hot-add or hot-remove
+		 */
+		info("Button cancel on Slot(%s)\n", p_slot->name);
+		dbg("%s: button cancel\n", __FUNCTION__);
+		cancel_delayed_work(&p_slot->work);
+		if (p_slot->state == BLINKINGOFF_STATE) {
+			if (PWR_LED(ctrl->ctrlcap))
+				p_slot->hpc_ops->green_led_on(p_slot);
+		} else {
+			if (PWR_LED(ctrl->ctrlcap))
+				p_slot->hpc_ops->green_led_off(p_slot);
+		}
+		if (ATTN_LED(ctrl->ctrlcap))
+			p_slot->hpc_ops->set_attention_status(p_slot, 0);
+		info("PCI slot #%s - action canceled due to button press\n",
+		     p_slot->name);
+		p_slot->state = STATIC_STATE;
+		break;
+	case POWEROFF_STATE:
+	case POWERON_STATE:
+		/*
+		 * Ignore if the slot is on power-on or power-off state;
+		 * this means that the previous attention button action
+		 * to hot-add or hot-remove is undergoing
+		 */
+		info("Button ignore on Slot(%s)\n", p_slot->name);
+		update_slot_info(p_slot);
+		break;
+	default:
+		warn("Not a valid state\n");
+		break;
 	}
 }
 
+/*
+ * Note: This function must be called with slot->lock held
+ */
+static void handle_surprise_event(struct slot *p_slot)
+{
+	u8 getstatus;
+	struct power_work_info *info;
+
+	info = kmalloc(sizeof(*info), GFP_KERNEL);
+	if (!info) {
+		err("%s: Cannot allocate memory\n", __FUNCTION__);
+		return;
+	}
+	info->p_slot = p_slot;
+	INIT_WORK(&info->work, pciehp_power_thread);
+
+	p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
+	if (!getstatus)
+		p_slot->state = POWEROFF_STATE;
+	else
+		p_slot->state = POWERON_STATE;
+
+	queue_work(pciehp_wq, &info->work);
+}
+
+static void interrupt_event_handler(struct work_struct *work)
+{
+	struct event_info *info = container_of(work, struct event_info, work);
+	struct slot *p_slot = info->p_slot;
+	struct controller *ctrl = p_slot->ctrl;
+
+	mutex_lock(&p_slot->lock);
+	switch (info->event_type) {
+	case INT_BUTTON_PRESS:
+		handle_button_press_event(p_slot);
+		break;
+	case INT_POWER_FAULT:
+		if (!POWER_CTRL(ctrl->ctrlcap))
+			break;
+		if (ATTN_LED(ctrl->ctrlcap))
+			p_slot->hpc_ops->set_attention_status(p_slot, 1);
+		if (PWR_LED(ctrl->ctrlcap))
+			p_slot->hpc_ops->green_led_off(p_slot);
+		break;
+	case INT_PRESENCE_ON:
+	case INT_PRESENCE_OFF:
+		if (!HP_SUPR_RM(ctrl->ctrlcap))
+			break;
+		dbg("Surprise Removal\n");
+		update_slot_info(p_slot);
+		handle_surprise_event(p_slot);
+		break;
+	default:
+		update_slot_info(p_slot);
+		break;
+	}
+	mutex_unlock(&p_slot->lock);
+
+	kfree(info);
+}
+
 int pciehp_enable_slot(struct slot *p_slot)
 {
 	u8 getstatus = 0;
@@ -653,7 +538,7 @@
 	rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
 	if (rc || !getstatus) {
 		info("%s: no adapter on slot(%s)\n", __FUNCTION__,
-		     slot_name(p_slot));
+		     p_slot->name);
 		mutex_unlock(&p_slot->ctrl->crit_sect);
 		return -ENODEV;
 	}
@@ -661,7 +546,7 @@
 		rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
 		if (rc || getstatus) {
 			info("%s: latch open on slot(%s)\n", __FUNCTION__,
-			     slot_name(p_slot));
+			     p_slot->name);
 			mutex_unlock(&p_slot->ctrl->crit_sect);
 			return -ENODEV;
 		}
@@ -671,7 +556,7 @@
 		rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
 		if (rc || getstatus) {
 			info("%s: already enabled on slot(%s)\n", __FUNCTION__,
-			     slot_name(p_slot));
+			     p_slot->name);
 			mutex_unlock(&p_slot->ctrl->crit_sect);
 			return -EINVAL;
 		}
@@ -706,7 +591,7 @@
 		ret = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
 		if (ret || !getstatus) {
 			info("%s: no adapter on slot(%s)\n", __FUNCTION__,
-			     slot_name(p_slot));
+			     p_slot->name);
 			mutex_unlock(&p_slot->ctrl->crit_sect);
 			return -ENODEV;
 		}
@@ -716,7 +601,7 @@
 		ret = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
 		if (ret || getstatus) {
 			info("%s: latch open on slot(%s)\n", __FUNCTION__,
-			     slot_name(p_slot));
+			     p_slot->name);
 			mutex_unlock(&p_slot->ctrl->crit_sect);
 			return -ENODEV;
 		}
@@ -726,7 +611,7 @@
 		ret = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
 		if (ret || !getstatus) {
 			info("%s: already disabled slot(%s)\n", __FUNCTION__,
-			     slot_name(p_slot));
+			     p_slot->name);
 			mutex_unlock(&p_slot->ctrl->crit_sect);
 			return -EINVAL;
 		}
@@ -739,3 +624,66 @@
 	return ret;
 }
 
+int pciehp_sysfs_enable_slot(struct slot *p_slot)
+{
+	int retval = -ENODEV;
+
+	mutex_lock(&p_slot->lock);
+	switch (p_slot->state) {
+	case BLINKINGON_STATE:
+		cancel_delayed_work(&p_slot->work);
+	case STATIC_STATE:
+		p_slot->state = POWERON_STATE;
+		mutex_unlock(&p_slot->lock);
+		retval = pciehp_enable_slot(p_slot);
+		mutex_lock(&p_slot->lock);
+		p_slot->state = STATIC_STATE;
+		break;
+	case POWERON_STATE:
+		info("Slot %s is already in powering on state\n",
+		     p_slot->name);
+		break;
+	case BLINKINGOFF_STATE:
+	case POWEROFF_STATE:
+		info("Already enabled on slot %s\n", p_slot->name);
+		break;
+	default:
+		err("Not a valid state on slot %s\n", p_slot->name);
+		break;
+	}
+	mutex_unlock(&p_slot->lock);
+
+	return retval;
+}
+
+int pciehp_sysfs_disable_slot(struct slot *p_slot)
+{
+	int retval = -ENODEV;
+
+	mutex_lock(&p_slot->lock);
+	switch (p_slot->state) {
+	case BLINKINGOFF_STATE:
+		cancel_delayed_work(&p_slot->work);
+	case STATIC_STATE:
+		p_slot->state = POWEROFF_STATE;
+		mutex_unlock(&p_slot->lock);
+		retval = pciehp_disable_slot(p_slot);
+		mutex_lock(&p_slot->lock);
+		p_slot->state = STATIC_STATE;
+		break;
+	case POWEROFF_STATE:
+		info("Slot %s is already in powering off state\n",
+		     p_slot->name);
+		break;
+	case BLINKINGON_STATE:
+	case POWERON_STATE:
+		info("Already disabled on slot %s\n", p_slot->name);
+		break;
+	default:
+		err("Not a valid state on slot %s\n", p_slot->name);
+		break;
+	}
+	mutex_unlock(&p_slot->lock);
+
+	return retval;
+}
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c
index fbc64aa..9aac6a8 100644
--- a/drivers/pci/hotplug/pciehp_hpc.c
+++ b/drivers/pci/hotplug/pciehp_hpc.c
@@ -71,6 +71,8 @@
 #define DBG_LEAVE_ROUTINE
 #endif				/* DEBUG */
 
+static atomic_t pciehp_num_controllers = ATOMIC_INIT(0);
+
 struct ctrl_reg {
 	u8 cap_id;
 	u8 nxt_ptr;
@@ -219,10 +221,7 @@
 #define EMI_STATE		0x0080
 #define EMI_STATUS_BIT		7
 
-static spinlock_t hpc_event_lock;
-
 DEFINE_DBG_BUFFER		/* Debug string buffer for entire HPC defined here */
-static int ctlr_seq_num = 0;	/* Controller sequence # */
 
 static irqreturn_t pcie_isr(int irq, void *dev_id);
 static void start_int_poll_timer(struct controller *ctrl, int sec);
@@ -656,6 +655,13 @@
 	else
 		free_irq(ctrl->pci_dev->irq, ctrl);
 
+	/*
+	 * If this is the last controller to be released, destroy the
+	 * pciehp work queue
+	 */
+	if (atomic_dec_and_test(&pciehp_num_controllers))
+		destroy_workqueue(pciehp_wq);
+
 	DBG_LEAVE_ROUTINE
 }
 
@@ -1152,7 +1158,6 @@
 int pcie_init(struct controller * ctrl, struct pcie_device *dev)
 {
 	int rc;
-	static int first = 1;
 	u16 temp_word;
 	u16 cap_reg;
 	u16 intr_enable = 0;
@@ -1221,11 +1226,6 @@
 	dbg("%s: SLOTCTRL offset %x slot_ctrl %x\n",
 	    __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_ctrl);
 
-	if (first) {
-		spin_lock_init(&hpc_event_lock);
-		first = 0;
-	}
-
 	for ( rc = 0; rc < DEVICE_COUNT_RESOURCE; rc++)
 		if (pci_resource_len(pdev, rc) > 0)
 			dbg("pci resource[%d] start=0x%llx(len=0x%llx)\n", rc,
@@ -1286,7 +1286,8 @@
 		rc = request_irq(ctrl->pci_dev->irq, pcie_isr, IRQF_SHARED,
 				 MY_NAME, (void *)ctrl);
 		dbg("%s: request_irq %d for hpc%d (returns %d)\n",
-		    __FUNCTION__, ctrl->pci_dev->irq, ctlr_seq_num, rc);
+		    __FUNCTION__, ctrl->pci_dev->irq,
+		    atomic_read(&pciehp_num_controllers), rc);
 		if (rc) {
 			err("Can't get irq %d for the hotplug controller\n",
 			    ctrl->pci_dev->irq);
@@ -1296,6 +1297,18 @@
 	dbg("pciehp ctrl b:d:f:irq=0x%x:%x:%x:%x\n", pdev->bus->number,
 		PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), dev->irq);
 
+	/*
+	 * If this is the first controller to be initialized,
+	 * initialize the pciehp work queue
+	 */
+	if (atomic_add_return(1, &pciehp_num_controllers) == 1) {
+		pciehp_wq = create_singlethread_workqueue("pciehpd");
+		if (!pciehp_wq) {
+			rc = -ENOMEM;
+			goto abort_free_irq;
+		}
+	}
+
 	rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);
 	if (rc) {
 		err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
@@ -1349,7 +1362,6 @@
 			goto abort_disable_intr;
 	}
 
-	ctlr_seq_num++;
 	ctrl->hpc_ops = &pciehp_hpc_ops;
 
 	DBG_LEAVE_ROUTINE
diff --git a/drivers/pci/hotplug/rpadlpar_core.c b/drivers/pci/hotplug/rpadlpar_core.c
index 7238346..bb3c101 100644
--- a/drivers/pci/hotplug/rpadlpar_core.c
+++ b/drivers/pci/hotplug/rpadlpar_core.c
@@ -98,7 +98,15 @@
 	return NULL;
 }
 
-static struct slot *find_slot(struct device_node *dn)
+/**
+ * find_php_slot - return hotplug slot structure for device node
+ *
+ * This routine will return the hotplug slot structure
+ * for a given device node. Note that built-in PCI slots
+ * may be dlpar-able, but not hot-pluggable, so this routine
+ * will return NULL for built-in PCI slots.
+ */
+static struct slot *find_php_slot(struct device_node *dn)
 {
 	struct list_head *tmp, *n;
 	struct slot *slot;
@@ -224,9 +232,9 @@
 	if (!pcibios_find_pci_bus(dn))
 		return -EINVAL;
 
-	slot = find_slot(dn);
+	/* If pci slot is hotplugable, use hotplug to remove it */
+	slot = find_php_slot(dn);
 	if (slot) {
-		/* Remove hotplug slot */
 		if (rpaphp_deregister_slot(slot)) {
 			printk(KERN_ERR
 				"%s: unable to remove hotplug slot %s\n",
@@ -370,22 +378,17 @@
 	if (!bus)
 		return -EINVAL;
 
-	slot = find_slot(dn);
+	/* If pci slot is hotplugable, use hotplug to remove it */
+	slot = find_php_slot(dn);
 	if (slot) {
-		/* Remove hotplug slot */
 		if (rpaphp_deregister_slot(slot)) {
 			printk(KERN_ERR
 				"%s: unable to remove hotplug slot %s\n",
 				__FUNCTION__, drc_name);
 			return -EIO;
 		}
-	} else {
-		struct pci_dev *dev, *tmp;
-		list_for_each_entry_safe(dev, tmp, &bus->devices, bus_list) {
-			eeh_remove_bus_device(dev);
-			pci_remove_bus_device(dev);
-		}
-	}
+	} else
+		pcibios_remove_pci_devices(bus);
 
 	if (unmap_bus_range(bus)) {
 		printk(KERN_ERR "%s: failed to unmap bus range\n",
diff --git a/drivers/pci/hotplug/rpaphp.h b/drivers/pci/hotplug/rpaphp.h
index 2e7accf..c822a77 100644
--- a/drivers/pci/hotplug/rpaphp.h
+++ b/drivers/pci/hotplug/rpaphp.h
@@ -83,19 +83,15 @@
 
 extern struct hotplug_slot_ops rpaphp_hotplug_slot_ops;
 extern struct list_head rpaphp_slot_head;
-extern int num_slots;
 
 /* function prototypes */
 
 /* rpaphp_pci.c */
-extern int rpaphp_enable_pci_slot(struct slot *slot);
-extern int rpaphp_register_pci_slot(struct slot *slot);
-extern int rpaphp_get_pci_adapter_status(struct slot *slot, int is_init, u8 * value);
+extern int rpaphp_enable_slot(struct slot *slot);
 extern int rpaphp_get_sensor_state(struct slot *slot, int *state);
 
 /* rpaphp_core.c */
 extern int rpaphp_add_slot(struct device_node *dn);
-extern int rpaphp_remove_slot(struct slot *slot);
 extern int rpaphp_get_drc_props(struct device_node *dn, int *drc_index,
 		char **drc_name, char **drc_type, int *drc_power_domain);
 
@@ -104,7 +100,5 @@
 extern struct slot *alloc_slot_struct(struct device_node *dn, int drc_index, char *drc_name, int power_domain);
 extern int rpaphp_register_slot(struct slot *slot);
 extern int rpaphp_deregister_slot(struct slot *slot);
-extern int rpaphp_get_power_status(struct slot *slot, u8 * value);
-extern int rpaphp_set_attention_status(struct slot *slot, u8 status);
 	
 #endif				/* _PPC64PHP_H */
diff --git a/drivers/pci/hotplug/rpaphp_core.c b/drivers/pci/hotplug/rpaphp_core.c
index 71a2cb8..847936f 100644
--- a/drivers/pci/hotplug/rpaphp_core.c
+++ b/drivers/pci/hotplug/rpaphp_core.c
@@ -39,9 +39,7 @@
 #include "rpaphp.h"
 
 int debug;
-static struct semaphore rpaphp_sem;
 LIST_HEAD(rpaphp_slot_head);
-int num_slots;
 
 #define DRIVER_VERSION	"0.1"
 #define DRIVER_AUTHOR	"Linda Xie <lxie@us.ibm.com>"
@@ -55,11 +53,6 @@
 
 module_param(debug, bool, 0644);
 
-static int rpaphp_get_attention_status(struct slot *slot)
-{
-	return slot->hotplug_slot->info->attention_status;
-}
-
 /**
  * set_attention_status - set attention LED
  * echo 0 > attention -- set LED OFF
@@ -69,79 +62,75 @@
  */
 static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 value)
 {
-	int retval = 0;
+	int rc;
 	struct slot *slot = (struct slot *)hotplug_slot->private;
 
-	down(&rpaphp_sem);
 	switch (value) {
 	case 0:
-		retval = rpaphp_set_attention_status(slot, LED_OFF);
-		hotplug_slot->info->attention_status = 0;
-		break;
 	case 1:
-	default:
-		retval = rpaphp_set_attention_status(slot, LED_ON);
-		hotplug_slot->info->attention_status = 1;
-		break;
 	case 2:
-		retval = rpaphp_set_attention_status(slot, LED_ID);
-		hotplug_slot->info->attention_status = 2;
+		break;
+	default:
+		value = 1;
 		break;
 	}
-	up(&rpaphp_sem);
-	return retval;
+
+	rc = rtas_set_indicator(DR_INDICATOR, slot->index, value);
+	if (!rc)
+		hotplug_slot->info->attention_status = value;
+
+	return rc;
 }
 
 /**
  * get_power_status - get power status of a slot
  * @hotplug_slot: slot to get status
  * @value: pointer to store status
- *
- *
  */
 static int get_power_status(struct hotplug_slot *hotplug_slot, u8 * value)
 {
-	int retval;
+	int retval, level;
 	struct slot *slot = (struct slot *)hotplug_slot->private;
 
-	down(&rpaphp_sem);
-	retval = rpaphp_get_power_status(slot, value);
-	up(&rpaphp_sem);
+	retval = rtas_get_power_level (slot->power_domain, &level);
+	if (!retval)
+		*value = level;
 	return retval;
 }
 
 /**
  * get_attention_status - get attention LED status
- *
- *
  */
 static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 * value)
 {
-	int retval = 0;
 	struct slot *slot = (struct slot *)hotplug_slot->private;
-
-	down(&rpaphp_sem);
-	*value = rpaphp_get_attention_status(slot);
-	up(&rpaphp_sem);
-	return retval;
+	*value = slot->hotplug_slot->info->attention_status;
+	return 0;
 }
 
 static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 * value)
 {
 	struct slot *slot = (struct slot *)hotplug_slot->private;
-	int retval = 0;
+	int rc, state;
 
-	down(&rpaphp_sem);
-	retval = rpaphp_get_pci_adapter_status(slot, 0, value);
-	up(&rpaphp_sem);
-	return retval;
+	rc = rpaphp_get_sensor_state(slot, &state);
+
+	*value = NOT_VALID;
+	if (rc)
+		return rc;
+
+	if (state == EMPTY)
+		*value = EMPTY;
+	else if (state == PRESENT)
+		*value = slot->state;
+
+	return 0;
 }
 
 static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value)
 {
 	struct slot *slot = (struct slot *)hotplug_slot->private;
 
-	down(&rpaphp_sem);
 	switch (slot->type) {
 	case 1:
 	case 2:
@@ -172,7 +161,6 @@
 		break;
 
 	}
-	up(&rpaphp_sem);
 	return 0;
 }
 
@@ -265,6 +253,14 @@
 	return 1;
 }
 
+/**
+ * is_php_dn() - return 1 if this is a hotpluggable pci slot, else 0
+ *
+ * This routine will return true only if the device node is
+ * a hotpluggable slot. This routine will return false
+ * for built-in pci slots (even when the built-in slots are
+ * dlparable.)
+ */
 static int is_php_dn(struct device_node *dn, const int **indexes,
 		const int **names, const int **types, const int **power_domains)
 {
@@ -272,24 +268,31 @@
 	int rc;
 
 	rc = get_children_props(dn, indexes, names, &drc_types, power_domains);
-	if (rc >= 0) {
-		if (is_php_type((char *) &drc_types[1])) {
-			*types = drc_types;
-			return 1;
-		}
-	}
+	if (rc < 0)
+		return 0;
 
-	return 0;
+	if (!is_php_type((char *) &drc_types[1]))
+		return 0;
+
+	*types = drc_types;
+	return 1;
 }
 
 /**
- * rpaphp_add_slot -- add hotplug or dlpar slot
+ * rpaphp_add_slot -- declare a hotplug slot to the hotplug subsystem.
+ * @dn device node of slot
  *
- *	rpaphp not only registers PCI hotplug slots(HOTPLUG), 
- *	but also logical DR slots(EMBEDDED).
- *	HOTPLUG slot: An adapter can be physically added/removed. 
- *	EMBEDDED slot: An adapter can be logically removed/added
- *		  from/to a partition with the slot.
+ * This subroutine will register a hotplugable slot with the
+ * PCI hotplug infrastructure. This routine is typicaly called
+ * during boot time, if the hotplug slots are present at boot time,
+ * or is called later, by the dlpar add code, if the slot is
+ * being dynamically added during runtime.
+ *
+ * If the device node points at an embedded (built-in) slot, this
+ * routine will just return without doing anything, since embedded
+ * slots cannot be hotplugged.
+ *
+ * To remove a slot, it suffices to call rpaphp_deregister_slot()
  */
 int rpaphp_add_slot(struct device_node *dn)
 {
@@ -299,34 +302,42 @@
 	const int *indexes, *names, *types, *power_domains;
 	char *name, *type;
 
+	if (!dn->name || strcmp(dn->name, "pci"))
+		return 0;
+
+	/* If this is not a hotplug slot, return without doing anything. */
+	if (!is_php_dn(dn, &indexes, &names, &types, &power_domains))
+		return 0;
+
 	dbg("Entry %s: dn->full_name=%s\n", __FUNCTION__, dn->full_name);
 
 	/* register PCI devices */
-	if (dn->name != 0 && strcmp(dn->name, "pci") == 0) {
-		if (!is_php_dn(dn, &indexes, &names, &types, &power_domains))
-			goto exit;
+	name = (char *) &names[1];
+	type = (char *) &types[1];
+	for (i = 0; i < indexes[0]; i++) {
 
-		name = (char *) &names[1];
-		type = (char *) &types[1];
-		for (i = 0; i < indexes[0]; i++,
-	     		name += (strlen(name) + 1), type += (strlen(type) + 1)) 		{
+		slot = alloc_slot_struct(dn, indexes[i + 1], name, power_domains[i + 1]);
+		if (!slot)
+			return -ENOMEM;
 
-			if (!(slot = alloc_slot_struct(dn, indexes[i + 1], name,
-				       power_domains[i + 1]))) {
-				retval = -ENOMEM;
-				goto exit;
-			}
-			slot->type = simple_strtoul(type, NULL, 10);
+		slot->type = simple_strtoul(type, NULL, 10);
 				
-			dbg("Found drc-index:0x%x drc-name:%s drc-type:%s\n",
-					indexes[i + 1], name, type);
+		dbg("Found drc-index:0x%x drc-name:%s drc-type:%s\n",
+				indexes[i + 1], name, type);
 
-			retval = rpaphp_register_pci_slot(slot);
-		}
+		retval = rpaphp_enable_slot(slot);
+		if (!retval)
+			retval = rpaphp_register_slot(slot);
+
+		if (retval)
+			dealloc_slot_struct(slot);
+
+		name += strlen(name) + 1;
+		type += strlen(type) + 1;
 	}
-exit:
-	dbg("%s - Exit: num_slots=%d rc[%d]\n",
-	    __FUNCTION__, num_slots, retval);
+	dbg("%s - Exit: rc[%d]\n", __FUNCTION__, retval);
+
+	/* XXX FIXME: reports a failure only if last entry in loop failed */
 	return retval;
 }
 
@@ -354,7 +365,6 @@
 	struct device_node *dn = NULL;
 
 	info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
-	init_MUTEX(&rpaphp_sem);
 
 	while ((dn = of_find_node_by_name(dn, "pci")))
 		rpaphp_add_slot(dn);
@@ -367,8 +377,9 @@
 	cleanup_slots();
 }
 
-static int __enable_slot(struct slot *slot)
+static int enable_slot(struct hotplug_slot *hotplug_slot)
 {
+	struct slot *slot = (struct slot *)hotplug_slot->private;
 	int state;
 	int retval;
 
@@ -392,44 +403,15 @@
 	return 0;
 }
 
-static int enable_slot(struct hotplug_slot *hotplug_slot)
-{
-	int retval;
-	struct slot *slot = (struct slot *)hotplug_slot->private;
-
-	down(&rpaphp_sem);
-	retval = __enable_slot(slot);
-	up(&rpaphp_sem);
-
-	return retval;
-}
-
-static int __disable_slot(struct slot *slot)
-{
-	struct pci_dev *dev, *tmp;
-
-	if (slot->state == NOT_CONFIGURED)
-		return -EINVAL;
-
-	list_for_each_entry_safe(dev, tmp, &slot->bus->devices, bus_list) {
-		eeh_remove_bus_device(dev);
-		pci_remove_bus_device(dev);
-	}
-
-	slot->state = NOT_CONFIGURED;
-	return 0;
-}
-
 static int disable_slot(struct hotplug_slot *hotplug_slot)
 {
 	struct slot *slot = (struct slot *)hotplug_slot->private;
-	int retval;
+	if (slot->state == NOT_CONFIGURED)
+		return -EINVAL;
 
-	down(&rpaphp_sem);
-	retval = __disable_slot (slot);
-	up(&rpaphp_sem);
-
-	return retval;
+	pcibios_remove_pci_devices(slot->bus);
+	slot->state = NOT_CONFIGURED;
+	return 0;
 }
 
 struct hotplug_slot_ops rpaphp_hotplug_slot_ops = {
diff --git a/drivers/pci/hotplug/rpaphp_pci.c b/drivers/pci/hotplug/rpaphp_pci.c
index 6f6cbed..54ca865 100644
--- a/drivers/pci/hotplug/rpaphp_pci.c
+++ b/drivers/pci/hotplug/rpaphp_pci.c
@@ -64,75 +64,6 @@
 	return rc;
 }
 
-/**
- * get_pci_adapter_status - get the status of a slot
- * 
- * 0-- slot is empty
- * 1-- adapter is configured
- * 2-- adapter is not configured
- * 3-- not valid
- */
-int rpaphp_get_pci_adapter_status(struct slot *slot, int is_init, u8 * value)
-{
-	struct pci_bus *bus;
-	int state, rc;
-
-	*value = NOT_VALID;
-	rc = rpaphp_get_sensor_state(slot, &state);
-	if (rc)
-		goto exit;
-
- 	if (state == EMPTY)
- 		*value = EMPTY;
- 	else if (state == PRESENT) {
-		if (!is_init) {
-			/* at run-time slot->state can be changed by */
-			/* config/unconfig adapter */
-			*value = slot->state;
-		} else {
-			bus = pcibios_find_pci_bus(slot->dn);
-			if (bus && !list_empty(&bus->devices))
-				*value = CONFIGURED;
-			else
-				*value = NOT_CONFIGURED;
-		}
-	}
-exit:
-	return rc;
-}
-
-static void print_slot_pci_funcs(struct pci_bus *bus)
-{
-	struct device_node *dn;
-	struct pci_dev *dev;
-
-	dn = pci_bus_to_OF_node(bus);
-	if (!dn)
-		return;
-
-	dbg("%s: pci_devs of slot[%s]\n", __FUNCTION__, dn->full_name);
-	list_for_each_entry (dev, &bus->devices, bus_list)
-		dbg("\t%s\n", pci_name(dev));
-	return;
-}
-
-static int setup_pci_hotplug_slot_info(struct slot *slot)
-{
-	struct hotplug_slot_info *hotplug_slot_info = slot->hotplug_slot->info;
-
-	dbg("%s Initilize the PCI slot's hotplug->info structure ...\n",
-	    __FUNCTION__);
-	rpaphp_get_power_status(slot, &hotplug_slot_info->power_status);
-	rpaphp_get_pci_adapter_status(slot, 1,
-				      &hotplug_slot_info->adapter_status);
-	if (hotplug_slot_info->adapter_status == NOT_VALID) {
-		err("%s: NOT_VALID: skip dn->full_name=%s\n",
-		    __FUNCTION__, slot->dn->full_name);
-		return -EINVAL;
-	}
-	return 0;
-}
-
 static void set_slot_name(struct slot *slot)
 {
 	struct pci_bus *bus = slot->bus;
@@ -146,69 +77,73 @@
 			bus->number);
 }
 
-static int setup_pci_slot(struct slot *slot)
+/**
+ * rpaphp_enable_slot - record slot state, config pci device
+ *
+ * Initialize values in the slot, and the hotplug_slot info
+ * structures to indicate if there is a pci card plugged into
+ * the slot. If the slot is not empty, run the pcibios routine
+ * to get pcibios stuff correctly set up.
+ */
+int rpaphp_enable_slot(struct slot *slot)
 {
-	struct device_node *dn = slot->dn;
+	int rc, level, state;
 	struct pci_bus *bus;
+	struct hotplug_slot_info *info = slot->hotplug_slot->info;
 
-	BUG_ON(!dn);
-	bus = pcibios_find_pci_bus(dn);
+	info->adapter_status = NOT_VALID;
+	slot->state = EMPTY;
+
+	/* Find out if the power is turned on for the slot */
+	rc = rtas_get_power_level(slot->power_domain, &level);
+	if (rc)
+		return rc;
+	info->power_status = level;
+
+	/* Figure out if there is an adapter in the slot */
+	rc = rpaphp_get_sensor_state(slot, &state);
+	if (rc)
+		return rc;
+
+	bus = pcibios_find_pci_bus(slot->dn);
 	if (!bus) {
-		err("%s: no pci_bus for dn %s\n", __FUNCTION__, dn->full_name);
-		goto exit_rc;
+		err("%s: no pci_bus for dn %s\n", __FUNCTION__, slot->dn->full_name);
+		return -EINVAL;
 	}
 
+	info->adapter_status = EMPTY;
 	slot->bus = bus;
 	slot->pci_devs = &bus->devices;
 	set_slot_name(slot);
 
-	/* find slot's pci_dev if it's not empty */
-	if (slot->hotplug_slot->info->adapter_status == EMPTY) {
-		slot->state = EMPTY;	/* slot is empty */
-	} else {
-		/* slot is occupied */
-		if (!dn->child) {
-			/* non-empty slot has to have child */
-			err("%s: slot[%s]'s device_node doesn't have child for adapter\n", 
-				__FUNCTION__, slot->name);
-			goto exit_rc;
+	/* if there's an adapter in the slot, go add the pci devices */
+	if (state == PRESENT) {
+		info->adapter_status = NOT_CONFIGURED;
+		slot->state = NOT_CONFIGURED;
+
+		/* non-empty slot has to have child */
+		if (!slot->dn->child) {
+			err("%s: slot[%s]'s device_node doesn't have child for adapter\n",
+			    __FUNCTION__, slot->name);
+			return -EINVAL;
 		}
 
-		if (slot->hotplug_slot->info->adapter_status == NOT_CONFIGURED) {
-			dbg("%s CONFIGURING pci adapter in slot[%s]\n",  
-				__FUNCTION__, slot->name);
-			pcibios_add_pci_devices(slot->bus);
+		if (list_empty(&bus->devices))
+			pcibios_add_pci_devices(bus);
 
-		} else if (slot->hotplug_slot->info->adapter_status != CONFIGURED) {
-			err("%s: slot[%s]'s adapter_status is NOT_VALID.\n",
-				__FUNCTION__, slot->name);
-			goto exit_rc;
-		}
-		print_slot_pci_funcs(slot->bus);
-		if (!list_empty(slot->pci_devs)) {
+		if (!list_empty(&bus->devices)) {
+			info->adapter_status = CONFIGURED;
 			slot->state = CONFIGURED;
-		} else {
-			/* DLPAR add as opposed to 
-		 	 * boot time */
-			slot->state = NOT_CONFIGURED;
+		}
+
+		if (debug) {
+			struct pci_dev *dev;
+			dbg("%s: pci_devs of slot[%s]\n", __FUNCTION__, slot->dn->full_name);
+			list_for_each_entry (dev, &bus->devices, bus_list)
+				dbg("\t%s\n", pci_name(dev));
 		}
 	}
+
 	return 0;
-exit_rc:
-	dealloc_slot_struct(slot);
-	return -EINVAL;
-}
-
-int rpaphp_register_pci_slot(struct slot *slot)
-{
-	int rc = -EINVAL;
-
-	if (setup_pci_hotplug_slot_info(slot))
-		goto exit_rc;
-	if (setup_pci_slot(slot))
-		goto exit_rc;
-	rc = rpaphp_register_slot(slot);
-exit_rc:
-	return rc;
 }
 
diff --git a/drivers/pci/hotplug/rpaphp_slot.c b/drivers/pci/hotplug/rpaphp_slot.c
index 3009193..d4ee872 100644
--- a/drivers/pci/hotplug/rpaphp_slot.c
+++ b/drivers/pci/hotplug/rpaphp_slot.c
@@ -56,7 +56,6 @@
 static void rpaphp_release_slot(struct hotplug_slot *hotplug_slot)
 {
 	struct slot *slot = (struct slot *) hotplug_slot->private;
-
 	dealloc_slot_struct(slot);
 }
 
@@ -65,12 +64,12 @@
 	kfree(slot->hotplug_slot->info);
 	kfree(slot->hotplug_slot->name);
 	kfree(slot->hotplug_slot);
+	kfree(slot->location);
 	kfree(slot);
-	return;
 }
 
-struct slot *alloc_slot_struct(struct device_node *dn, int drc_index, char *drc_name,
-		  int power_domain)
+struct slot *alloc_slot_struct(struct device_node *dn,
+                       int drc_index, char *drc_name, int power_domain)
 {
 	struct slot *slot;
 	
@@ -115,7 +114,7 @@
 
 static int is_registered(struct slot *slot)
 {
-	struct slot             *tmp_slot;
+	struct slot *tmp_slot;
 
 	list_for_each_entry(tmp_slot, &rpaphp_slot_head, rpaphp_slot_list) {
 		if (!strcmp(tmp_slot->name, slot->name))
@@ -140,8 +139,6 @@
 	retval = pci_hp_deregister(php_slot);
 	if (retval)
 		err("Problem unregistering a slot %s\n", slot->name);
-	else
-		num_slots--;
 
 	dbg("%s - Exit: rc[%d]\n", __FUNCTION__, retval);
 	return retval;
@@ -160,14 +157,13 @@
 	/* should not try to register the same slot twice */
 	if (is_registered(slot)) {
 		err("rpaphp_register_slot: slot[%s] is already registered\n", slot->name);
-		retval = -EAGAIN;
-		goto register_fail;
+		return -EAGAIN;
 	}	
 
 	retval = pci_hp_register(php_slot);
 	if (retval) {
 		err("pci_hp_register failed with error %d\n", retval);
-		goto register_fail;
+		return retval;
 	}
 
 	/* create "phy_location" file */
@@ -181,43 +177,10 @@
 	list_add(&slot->rpaphp_slot_list, &rpaphp_slot_head);
 	info("Slot [%s](PCI location=%s) registered\n", slot->name,
 			slot->location);
-	num_slots++;
 	return 0;
 
 sysfs_fail:
 	pci_hp_deregister(php_slot);
-register_fail:
-	rpaphp_release_slot(php_slot);
 	return retval;
 }
 
-int rpaphp_get_power_status(struct slot *slot, u8 * value)
-{
-	int rc = 0, level;
-	
-	rc = rtas_get_power_level(slot->power_domain, &level);
-	if (rc < 0) {
-		err("failed to get power-level for slot(%s), rc=0x%x\n",
-			slot->location, rc);
-		return rc;
-	}
-
-	dbg("%s the power level of slot %s(pwd-domain:0x%x) is %d\n",
-		__FUNCTION__, slot->name, slot->power_domain, level);
-	*value = level;
-
-	return rc;
-}
-
-int rpaphp_set_attention_status(struct slot *slot, u8 status)
-{
-	int rc;
-
-	/* status: LED_OFF or LED_ON */
-	rc = rtas_set_indicator(DR_INDICATOR, slot->index, status);
-	if (rc < 0)
-		err("slot(name=%s location=%s index=0x%x) set attention-status(%d) failed! rc=0x%x\n",
-		    slot->name, slot->location, slot->index, status, rc);
-
-	return rc;
-}
diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h
index 01d31a1..37ed088 100644
--- a/drivers/pci/hotplug/shpchp.h
+++ b/drivers/pci/hotplug/shpchp.h
@@ -166,7 +166,7 @@
 extern int shpchp_configure_device(struct slot *p_slot);
 extern int shpchp_unconfigure_device(struct slot *p_slot);
 extern void cleanup_slots(struct controller *ctrl);
-extern void queue_pushbutton_work(struct work_struct *work);
+extern void shpchp_queue_pushbutton_work(struct work_struct *work);
 extern int shpc_init( struct controller *ctrl, struct pci_dev *pdev);
 
 #ifdef CONFIG_ACPI
diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c
index 5f4bc08..80dec97 100644
--- a/drivers/pci/hotplug/shpchp_core.c
+++ b/drivers/pci/hotplug/shpchp_core.c
@@ -136,7 +136,7 @@
 		slot->hpc_ops = ctrl->hpc_ops;
 		slot->number = ctrl->first_slot + (ctrl->slot_num_inc * i);
 		mutex_init(&slot->lock);
-		INIT_DELAYED_WORK(&slot->work, queue_pushbutton_work);
+		INIT_DELAYED_WORK(&slot->work, shpchp_queue_pushbutton_work);
 
 		/* register this slot with the hotplug pci core */
 		hotplug_slot->private = slot;
diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c
index b746bd2..2c94d442 100644
--- a/drivers/pci/hotplug/shpchp_ctrl.c
+++ b/drivers/pci/hotplug/shpchp_ctrl.c
@@ -433,7 +433,7 @@
 	kfree(info);
 }
 
-void queue_pushbutton_work(struct work_struct *work)
+void shpchp_queue_pushbutton_work(struct work_struct *work)
 {
 	struct slot *p_slot = container_of(work, struct slot, work.work);
 	struct pushbutton_work_info *info;
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index 435c195..9e1321d 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -24,20 +24,8 @@
 #include "pci.h"
 #include "msi.h"
 
-static struct kmem_cache* msi_cachep;
-
 static int pci_msi_enable = 1;
 
-static int msi_cache_init(void)
-{
-	msi_cachep = kmem_cache_create("msi_cache", sizeof(struct msi_desc),
-					0, SLAB_HWCACHE_ALIGN, NULL, NULL);
-	if (!msi_cachep)
-		return -ENOMEM;
-
-	return 0;
-}
-
 static void msi_set_enable(struct pci_dev *dev, int enable)
 {
 	int pos;
@@ -68,6 +56,29 @@
 	}
 }
 
+static void msix_flush_writes(unsigned int irq)
+{
+	struct msi_desc *entry;
+
+	entry = get_irq_msi(irq);
+	BUG_ON(!entry || !entry->dev);
+	switch (entry->msi_attrib.type) {
+	case PCI_CAP_ID_MSI:
+		/* nothing to do */
+		break;
+	case PCI_CAP_ID_MSIX:
+	{
+		int offset = entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE +
+			PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET;
+		readl(entry->mask_base + offset);
+		break;
+	}
+	default:
+		BUG();
+		break;
+	}
+}
+
 static void msi_set_mask_bit(unsigned int irq, int flag)
 {
 	struct msi_desc *entry;
@@ -187,41 +198,28 @@
 void mask_msi_irq(unsigned int irq)
 {
 	msi_set_mask_bit(irq, 1);
+	msix_flush_writes(irq);
 }
 
 void unmask_msi_irq(unsigned int irq)
 {
 	msi_set_mask_bit(irq, 0);
+	msix_flush_writes(irq);
 }
 
-static int msi_free_irq(struct pci_dev* dev, int irq);
+static int msi_free_irqs(struct pci_dev* dev);
 
-static int msi_init(void)
-{
-	static int status = -ENOMEM;
-
-	if (!status)
-		return status;
-
-	status = msi_cache_init();
-	if (status < 0) {
-		pci_msi_enable = 0;
-		printk(KERN_WARNING "PCI: MSI cache init failed\n");
-		return status;
-	}
-
-	return status;
-}
 
 static struct msi_desc* alloc_msi_entry(void)
 {
 	struct msi_desc *entry;
 
-	entry = kmem_cache_zalloc(msi_cachep, GFP_KERNEL);
+	entry = kzalloc(sizeof(struct msi_desc), GFP_KERNEL);
 	if (!entry)
 		return NULL;
 
-	entry->link.tail = entry->link.head = 0;	/* single message */
+	INIT_LIST_HEAD(&entry->list);
+	entry->irq = 0;
 	entry->dev = NULL;
 
 	return entry;
@@ -256,7 +254,6 @@
 static void __pci_restore_msix_state(struct pci_dev *dev)
 {
 	int pos;
-	int irq, head, tail = 0;
 	struct msi_desc *entry;
 	u16 control;
 
@@ -266,18 +263,15 @@
 	/* route the table */
 	pci_intx(dev, 0);		/* disable intx */
 	msix_set_enable(dev, 0);
-	irq = head = dev->first_msi_irq;
-	entry = get_irq_msi(irq);
-	pos = entry->msi_attrib.pos;
-	while (head != tail) {
-		entry = get_irq_msi(irq);
-		write_msi_msg(irq, &entry->msg);
-		msi_set_mask_bit(irq, entry->msi_attrib.masked);
 
-		tail = entry->link.tail;
-		irq = tail;
+	list_for_each_entry(entry, &dev->msi_list, list) {
+		write_msi_msg(entry->irq, &entry->msg);
+		msi_set_mask_bit(entry->irq, entry->msi_attrib.masked);
 	}
 
+	BUG_ON(list_empty(&dev->msi_list));
+	entry = list_entry(dev->msi_list.next, struct msi_desc, list);
+	pos = entry->msi_attrib.pos;
 	pci_read_config_word(dev, pos + PCI_MSIX_FLAGS, &control);
 	control &= ~PCI_MSIX_FLAGS_MASKALL;
 	control |= PCI_MSIX_FLAGS_ENABLE;
@@ -303,7 +297,7 @@
 static int msi_capability_init(struct pci_dev *dev)
 {
 	struct msi_desc *entry;
-	int pos, irq;
+	int pos, ret;
 	u16 control;
 
 	msi_set_enable(dev, 0);	/* Ensure msi is disabled as I set it up */
@@ -340,23 +334,21 @@
 			msi_mask_bits_reg(pos, is_64bit_address(control)),
 			maskbits);
 	}
+	list_add(&entry->list, &dev->msi_list);
+
 	/* Configure MSI capability structure */
-	irq = arch_setup_msi_irq(dev, entry);
-	if (irq < 0) {
-		kmem_cache_free(msi_cachep, entry);
-		return irq;
+	ret = arch_setup_msi_irqs(dev, 1, PCI_CAP_ID_MSI);
+	if (ret) {
+		msi_free_irqs(dev);
+		return ret;
 	}
-	entry->link.head = irq;
-	entry->link.tail = irq;
-	dev->first_msi_irq = irq;
-	set_irq_msi(irq, entry);
 
 	/* Set MSI enabled bits	 */
 	pci_intx(dev, 0);		/* disable intx */
 	msi_set_enable(dev, 1);
 	dev->msi_enabled = 1;
 
-	dev->irq = irq;
+	dev->irq = entry->irq;
 	return 0;
 }
 
@@ -373,8 +365,8 @@
 static int msix_capability_init(struct pci_dev *dev,
 				struct msix_entry *entries, int nvec)
 {
-	struct msi_desc *head = NULL, *tail = NULL, *entry = NULL;
-	int irq, pos, i, j, nr_entries, temp = 0;
+	struct msi_desc *entry;
+	int pos, i, j, nr_entries, ret;
 	unsigned long phys_addr;
 	u32 table_offset;
  	u16 control;
@@ -413,44 +405,34 @@
 		entry->dev = dev;
 		entry->mask_base = base;
 
-		/* Configure MSI-X capability structure */
-		irq = arch_setup_msi_irq(dev, entry);
-		if (irq < 0) {
-			kmem_cache_free(msi_cachep, entry);
-			break;
-		}
- 		entries[i].vector = irq;
-		if (!head) {
-			entry->link.head = irq;
-			entry->link.tail = irq;
-			head = entry;
-		} else {
-			entry->link.head = temp;
-			entry->link.tail = tail->link.tail;
-			tail->link.tail = irq;
-			head->link.head = irq;
-		}
-		temp = irq;
-		tail = entry;
-
-		set_irq_msi(irq, entry);
+		list_add(&entry->list, &dev->msi_list);
 	}
-	if (i != nvec) {
-		int avail = i - 1;
-		i--;
-		for (; i >= 0; i--) {
-			irq = (entries + i)->vector;
-			msi_free_irq(dev, irq);
-			(entries + i)->vector = 0;
+
+	ret = arch_setup_msi_irqs(dev, nvec, PCI_CAP_ID_MSIX);
+	if (ret) {
+		int avail = 0;
+		list_for_each_entry(entry, &dev->msi_list, list) {
+			if (entry->irq != 0) {
+				avail++;
+			}
 		}
+
+		msi_free_irqs(dev);
+
 		/* If we had some success report the number of irqs
 		 * we succeeded in setting up.
 		 */
-		if (avail <= 0)
-			avail = -EBUSY;
+		if (avail == 0)
+			avail = ret;
 		return avail;
 	}
-	dev->first_msi_irq = entries[0].vector;
+
+	i = 0;
+	list_for_each_entry(entry, &dev->msi_list, list) {
+		entries[i].vector = entry->irq;
+		set_irq_msi(entry->irq, entry);
+		i++;
+	}
 	/* Set MSI-X enabled bits */
 	pci_intx(dev, 0);		/* disable intx */
 	msix_set_enable(dev, 1);
@@ -460,21 +442,32 @@
 }
 
 /**
- * pci_msi_supported - check whether MSI may be enabled on device
+ * pci_msi_check_device - check whether MSI may be enabled on a device
  * @dev: pointer to the pci_dev data structure of MSI device function
+ * @nvec: how many MSIs have been requested ?
+ * @type: are we checking for MSI or MSI-X ?
  *
  * Look at global flags, the device itself, and its parent busses
- * to return 0 if MSI are supported for the device.
+ * to determine if MSI/-X are supported for the device. If MSI/-X is
+ * supported return 0, else return an error code.
  **/
-static
-int pci_msi_supported(struct pci_dev * dev)
+static int pci_msi_check_device(struct pci_dev* dev, int nvec, int type)
 {
 	struct pci_bus *bus;
+	int ret;
 
 	/* MSI must be globally enabled and supported by the device */
 	if (!pci_msi_enable || !dev || dev->no_msi)
 		return -EINVAL;
 
+	/*
+	 * You can't ask to have 0 or less MSIs configured.
+	 *  a) it's stupid ..
+	 *  b) the list manipulation code assumes nvec >= 1.
+	 */
+	if (nvec < 1)
+		return -ERANGE;
+
 	/* Any bridge which does NOT route MSI transactions from it's
 	 * secondary bus to it's primary bus must set NO_MSI flag on
 	 * the secondary pci_bus.
@@ -485,6 +478,13 @@
 		if (bus->bus_flags & PCI_BUS_FLAGS_NO_MSI)
 			return -EINVAL;
 
+	ret = arch_msi_check_device(dev, nvec, type);
+	if (ret)
+		return ret;
+
+	if (!pci_find_capability(dev, type))
+		return -EINVAL;
+
 	return 0;
 }
 
@@ -500,19 +500,12 @@
  **/
 int pci_enable_msi(struct pci_dev* dev)
 {
-	int pos, status;
+	int status;
 
-	if (pci_msi_supported(dev) < 0)
-		return -EINVAL;
-
-	status = msi_init();
-	if (status < 0)
+	status = pci_msi_check_device(dev, 1, PCI_CAP_ID_MSI);
+	if (status)
 		return status;
 
-	pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
-	if (!pos)
-		return -EINVAL;
-
 	WARN_ON(!!dev->msi_enabled);
 
 	/* Check whether driver already requested for MSI-X irqs */
@@ -525,69 +518,54 @@
 	status = msi_capability_init(dev);
 	return status;
 }
+EXPORT_SYMBOL(pci_enable_msi);
 
 void pci_disable_msi(struct pci_dev* dev)
 {
 	struct msi_desc *entry;
 	int default_irq;
 
-	if (!pci_msi_enable)
-		return;
-	if (!dev)
-		return;
-
-	if (!dev->msi_enabled)
+	if (!pci_msi_enable || !dev || !dev->msi_enabled)
 		return;
 
 	msi_set_enable(dev, 0);
 	pci_intx(dev, 1);		/* enable intx */
 	dev->msi_enabled = 0;
 
-	entry = get_irq_msi(dev->first_msi_irq);
-	if (!entry || !entry->dev || entry->msi_attrib.type != PCI_CAP_ID_MSI) {
+	BUG_ON(list_empty(&dev->msi_list));
+	entry = list_entry(dev->msi_list.next, struct msi_desc, list);
+	if (!entry->dev || entry->msi_attrib.type != PCI_CAP_ID_MSI) {
 		return;
 	}
-	if (irq_has_action(dev->first_msi_irq)) {
-		printk(KERN_WARNING "PCI: %s: pci_disable_msi() called without "
-		       "free_irq() on MSI irq %d\n",
-		       pci_name(dev), dev->first_msi_irq);
-		BUG_ON(irq_has_action(dev->first_msi_irq));
-	} else {
-		default_irq = entry->msi_attrib.default_irq;
-		msi_free_irq(dev, dev->first_msi_irq);
 
-		/* Restore dev->irq to its default pin-assertion irq */
-		dev->irq = default_irq;
-	}
-	dev->first_msi_irq = 0;
+	default_irq = entry->msi_attrib.default_irq;
+	msi_free_irqs(dev);
+
+	/* Restore dev->irq to its default pin-assertion irq */
+	dev->irq = default_irq;
 }
+EXPORT_SYMBOL(pci_disable_msi);
 
-static int msi_free_irq(struct pci_dev* dev, int irq)
+static int msi_free_irqs(struct pci_dev* dev)
 {
-	struct msi_desc *entry;
-	int head, entry_nr, type;
-	void __iomem *base;
+	struct msi_desc *entry, *tmp;
 
-	entry = get_irq_msi(irq);
-	if (!entry || entry->dev != dev) {
-		return -EINVAL;
-	}
-	type = entry->msi_attrib.type;
-	entry_nr = entry->msi_attrib.entry_nr;
-	head = entry->link.head;
-	base = entry->mask_base;
-	get_irq_msi(entry->link.head)->link.tail = entry->link.tail;
-	get_irq_msi(entry->link.tail)->link.head = entry->link.head;
+	list_for_each_entry(entry, &dev->msi_list, list)
+		BUG_ON(irq_has_action(entry->irq));
 
-	arch_teardown_msi_irq(irq);
-	kmem_cache_free(msi_cachep, entry);
+	arch_teardown_msi_irqs(dev);
 
-	if (type == PCI_CAP_ID_MSIX) {
-		writel(1, base + entry_nr * PCI_MSIX_ENTRY_SIZE +
-			PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET);
+	list_for_each_entry_safe(entry, tmp, &dev->msi_list, list) {
+		if (entry->msi_attrib.type == PCI_CAP_ID_MSIX) {
+			if (list_is_last(&entry->list, &dev->msi_list))
+				iounmap(entry->mask_base);
 
-		if (head == irq)
-			iounmap(base);
+			writel(1, entry->mask_base + entry->msi_attrib.entry_nr
+				  * PCI_MSIX_ENTRY_SIZE
+				  + PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET);
+		}
+		list_del(&entry->list);
+		kfree(entry);
 	}
 
 	return 0;
@@ -614,17 +592,14 @@
 	int i, j;
 	u16 control;
 
-	if (!entries || pci_msi_supported(dev) < 0)
+	if (!entries)
  		return -EINVAL;
 
-	status = msi_init();
-	if (status < 0)
+	status = pci_msi_check_device(dev, nvec, PCI_CAP_ID_MSIX);
+	if (status)
 		return status;
 
 	pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
-	if (!pos)
- 		return -EINVAL;
-
 	pci_read_config_word(dev, msi_control_reg(pos), &control);
 	nr_entries = multi_msix_capable(control);
 	if (nvec > nr_entries)
@@ -651,41 +626,25 @@
 	status = msix_capability_init(dev, entries, nvec);
 	return status;
 }
+EXPORT_SYMBOL(pci_enable_msix);
+
+static void msix_free_all_irqs(struct pci_dev *dev)
+{
+	msi_free_irqs(dev);
+}
 
 void pci_disable_msix(struct pci_dev* dev)
 {
-	int irq, head, tail = 0, warning = 0;
-
-	if (!pci_msi_enable)
-		return;
-	if (!dev)
-		return;
-
-	if (!dev->msix_enabled)
+	if (!pci_msi_enable || !dev || !dev->msix_enabled)
 		return;
 
 	msix_set_enable(dev, 0);
 	pci_intx(dev, 1);		/* enable intx */
 	dev->msix_enabled = 0;
 
-	irq = head = dev->first_msi_irq;
-	while (head != tail) {
-		tail = get_irq_msi(irq)->link.tail;
-		if (irq_has_action(irq))
-			warning = 1;
-		else if (irq != head)	/* Release MSI-X irq */
-			msi_free_irq(dev, irq);
-		irq = tail;
-	}
-	msi_free_irq(dev, irq);
-	if (warning) {
-		printk(KERN_WARNING "PCI: %s: pci_disable_msix() called without "
-			"free_irq() on all MSI-X irqs\n",
-			pci_name(dev));
-		BUG_ON(warning > 0);
-	}
-	dev->first_msi_irq = 0;
+	msix_free_all_irqs(dev);
 }
+EXPORT_SYMBOL(pci_disable_msix);
 
 /**
  * msi_remove_pci_irq_vectors - reclaim MSI(X) irqs to unused state
@@ -701,38 +660,11 @@
 	if (!pci_msi_enable || !dev)
  		return;
 
-	if (dev->msi_enabled) {
-		if (irq_has_action(dev->first_msi_irq)) {
-			printk(KERN_WARNING "PCI: %s: msi_remove_pci_irq_vectors() "
-			       "called without free_irq() on MSI irq %d\n",
-			       pci_name(dev), dev->first_msi_irq);
-			BUG_ON(irq_has_action(dev->first_msi_irq));
-		} else /* Release MSI irq assigned to this device */
-			msi_free_irq(dev, dev->first_msi_irq);
-	}
-	if (dev->msix_enabled) {
-		int irq, head, tail = 0, warning = 0;
-		void __iomem *base = NULL;
+	if (dev->msi_enabled)
+		msi_free_irqs(dev);
 
-		irq = head = dev->first_msi_irq;
-		while (head != tail) {
-			tail = get_irq_msi(irq)->link.tail;
-			base = get_irq_msi(irq)->mask_base;
-			if (irq_has_action(irq))
-				warning = 1;
-			else if (irq != head) /* Release MSI-X irq */
-				msi_free_irq(dev, irq);
-			irq = tail;
-		}
-		msi_free_irq(dev, irq);
-		if (warning) {
-			iounmap(base);
-			printk(KERN_WARNING "PCI: %s: msi_remove_pci_irq_vectors() "
-			       "called without free_irq() on all MSI-X irqs\n",
-			       pci_name(dev));
-			BUG_ON(warning > 0);
-		}
-	}
+	if (dev->msix_enabled)
+		msix_free_all_irqs(dev);
 }
 
 void pci_no_msi(void)
@@ -740,7 +672,53 @@
 	pci_msi_enable = 0;
 }
 
-EXPORT_SYMBOL(pci_enable_msi);
-EXPORT_SYMBOL(pci_disable_msi);
-EXPORT_SYMBOL(pci_enable_msix);
-EXPORT_SYMBOL(pci_disable_msix);
+void pci_msi_init_pci_dev(struct pci_dev *dev)
+{
+	INIT_LIST_HEAD(&dev->msi_list);
+}
+
+
+/* Arch hooks */
+
+int __attribute__ ((weak))
+arch_msi_check_device(struct pci_dev* dev, int nvec, int type)
+{
+	return 0;
+}
+
+int __attribute__ ((weak))
+arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *entry)
+{
+	return 0;
+}
+
+int __attribute__ ((weak))
+arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
+{
+	struct msi_desc *entry;
+	int ret;
+
+	list_for_each_entry(entry, &dev->msi_list, list) {
+		ret = arch_setup_msi_irq(dev, entry);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+void __attribute__ ((weak)) arch_teardown_msi_irq(unsigned int irq)
+{
+	return;
+}
+
+void __attribute__ ((weak))
+arch_teardown_msi_irqs(struct pci_dev *dev)
+{
+	struct msi_desc *entry;
+
+	list_for_each_entry(entry, &dev->msi_list, list) {
+		if (entry->irq != 0)
+			arch_teardown_msi_irq(entry->irq);
+	}
+}
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index 39e80fc..3bb7739 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -14,20 +14,6 @@
 #include "pci.h"
 
 /*
- *  Registration of PCI drivers and handling of hot-pluggable devices.
- */
-
-/* multithreaded probe logic */
-static int pci_multithread_probe =
-#ifdef CONFIG_PCI_MULTITHREAD_PROBE
-	1;
-#else
-	0;
-#endif
-__module_param_call("", pci_multithread_probe, param_set_bool, param_get_bool, &pci_multithread_probe, 0644);
-
-
-/*
  * Dynamic device IDs are disabled for !CONFIG_HOTPLUG
  */
 
@@ -52,7 +38,7 @@
 {
 	struct pci_dynid *dynid;
 	struct pci_driver *pdrv = to_pci_driver(driver);
-	__u32 vendor=PCI_ANY_ID, device=PCI_ANY_ID, subvendor=PCI_ANY_ID,
+	__u32 vendor, device, subvendor=PCI_ANY_ID,
 		subdevice=PCI_ANY_ID, class=0, class_mask=0;
 	unsigned long driver_data=0;
 	int fields=0;
@@ -61,7 +47,7 @@
 	fields = sscanf(buf, "%x %x %x %x %x %x %lux",
 			&vendor, &device, &subvendor, &subdevice,
 			&class, &class_mask, &driver_data);
-	if (fields < 0)
+	if (fields < 2)
 		return -EINVAL;
 
 	dynid = kzalloc(sizeof(*dynid), GFP_KERNEL);
@@ -569,7 +555,6 @@
 
 static int __init pci_driver_init(void)
 {
-	pci_bus_type.multithread_probe = pci_multithread_probe;
 	return bus_register(&pci_bus_type);
 }
 
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index cd913a2..284e83a 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -620,7 +620,8 @@
 		goto err_bin_file;
 
 	/* If the device has a ROM, try to expose it in sysfs. */
-	if (pci_resource_len(pdev, PCI_ROM_RESOURCE)) {
+	if (pci_resource_len(pdev, PCI_ROM_RESOURCE) ||
+	    (pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW)) {
 		rom_attr = kzalloc(sizeof(*rom_attr), GFP_ATOMIC);
 		if (rom_attr) {
 			pdev->rom_attr = rom_attr;
@@ -635,7 +636,7 @@
 				goto err_rom;
 		} else {
 			retval = -ENOMEM;
-			goto err_bin_file;
+			goto err_resource_files;
 		}
 	}
 	/* add platform-specific attributes */
@@ -645,6 +646,8 @@
 
 err_rom:
 	kfree(rom_attr);
+err_resource_files:
+	pci_remove_resource_files(pdev);
 err_bin_file:
 	if (pdev->cfg_size < 4096)
 		sysfs_remove_bin_file(&pdev->dev.kobj, &pci_config_attr);
@@ -695,4 +698,4 @@
 	return 0;
 }
 
-__initcall(pci_sysfs_init);
+late_initcall(pci_sysfs_init);
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 2a45827..fd47ac0 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -35,8 +35,7 @@
  * Given a PCI bus, returns the highest PCI bus number present in the set
  * including the given PCI bus and its list of child PCI buses.
  */
-unsigned char __devinit
-pci_bus_max_busnr(struct pci_bus* bus)
+unsigned char pci_bus_max_busnr(struct pci_bus* bus)
 {
 	struct list_head *tmp;
 	unsigned char max, n;
@@ -892,6 +891,34 @@
 }
 
 /**
+ * pcibios_set_pcie_reset_state - set reset state for device dev
+ * @dev: the PCI-E device reset
+ * @state: Reset state to enter into
+ *
+ *
+ * Sets the PCI-E reset state for the device. This is the default
+ * implementation. Architecture implementations can override this.
+ */
+int __attribute__ ((weak)) pcibios_set_pcie_reset_state(struct pci_dev *dev,
+							enum pcie_reset_state state)
+{
+	return -EINVAL;
+}
+
+/**
+ * pci_set_pcie_reset_state - set reset state for device dev
+ * @dev: the PCI-E device reset
+ * @state: Reset state to enter into
+ *
+ *
+ * Sets the PCI reset state for the device.
+ */
+int pci_set_pcie_reset_state(struct pci_dev *dev, enum pcie_reset_state state)
+{
+	return pcibios_set_pcie_reset_state(dev, state);
+}
+
+/**
  * pci_enable_wake - enable PCI device as wakeup event source
  * @dev: PCI device affected
  * @state: PCI state from which device will issue wakeup events
@@ -1295,7 +1322,7 @@
 
 /**
  * pci_msi_off - disables any msi or msix capabilities
- * @pdev: the PCI device to operate on
+ * @dev: the PCI device to operate on
  *
  * If you want to use msi see pci_enable_msi and friends.
  * This is a lower level primitive that allows us to disable
@@ -1427,4 +1454,5 @@
 EXPORT_SYMBOL(pci_save_state);
 EXPORT_SYMBOL(pci_restore_state);
 EXPORT_SYMBOL(pci_enable_wake);
+EXPORT_SYMBOL_GPL(pci_set_pcie_reset_state);
 
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 62ea04c..3fec13d 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -47,8 +47,10 @@
 
 #ifdef CONFIG_PCI_MSI
 void pci_no_msi(void);
+extern void pci_msi_init_pci_dev(struct pci_dev *dev);
 #else
 static inline void pci_no_msi(void) { }
+static inline void pci_msi_init_pci_dev(struct pci_dev *dev) { }
 #endif
 
 #if defined(CONFIG_PCI_MSI) && defined(CONFIG_PM)
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 2fe1d690..e48fcf0 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -364,7 +364,7 @@
 	}
 }
 
-static struct pci_bus * __devinit pci_alloc_bus(void)
+static struct pci_bus * pci_alloc_bus(void)
 {
 	struct pci_bus *b;
 
@@ -432,7 +432,7 @@
 	return NULL;
 }
 
-struct pci_bus * __devinit pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev, int busnr)
+struct pci_bus *pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev, int busnr)
 {
 	struct pci_bus *child;
 
@@ -461,7 +461,7 @@
 	pci_write_config_word(dev, rpcap + PCI_EXP_RTCTL, rpctl);
 }
 
-static void __devinit pci_fixup_parent_subordinate_busnr(struct pci_bus *child, int max)
+static void pci_fixup_parent_subordinate_busnr(struct pci_bus *child, int max)
 {
 	struct pci_bus *parent = child->parent;
 
@@ -477,7 +477,7 @@
 	}
 }
 
-unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus);
+unsigned int pci_scan_child_bus(struct pci_bus *bus);
 
 /*
  * If it's a bridge, configure it and scan the bus behind it.
@@ -489,7 +489,7 @@
  * them, we proceed to assigning numbers to the remaining buses in
  * order to avoid overlaps between old and new bus numbers.
  */
-int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max, int pass)
+int pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max, int pass)
 {
 	struct pci_bus *child;
 	int is_cardbus = (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS);
@@ -846,6 +846,23 @@
 	kfree(dev);
 }
 
+struct pci_dev *alloc_pci_dev(void)
+{
+	struct pci_dev *dev;
+
+	dev = kzalloc(sizeof(struct pci_dev), GFP_KERNEL);
+	if (!dev)
+		return NULL;
+
+	INIT_LIST_HEAD(&dev->global_list);
+	INIT_LIST_HEAD(&dev->bus_list);
+
+	pci_msi_init_pci_dev(dev);
+
+	return dev;
+}
+EXPORT_SYMBOL(alloc_pci_dev);
+
 /*
  * Read the config data for a PCI device, sanity-check it
  * and fill in the dev structure...
@@ -885,7 +902,7 @@
 	if (pci_bus_read_config_byte(bus, devfn, PCI_HEADER_TYPE, &hdr_type))
 		return NULL;
 
-	dev = kzalloc(sizeof(struct pci_dev), GFP_KERNEL);
+	dev = alloc_pci_dev();
 	if (!dev)
 		return NULL;
 
@@ -912,7 +929,7 @@
 	return dev;
 }
 
-void __devinit pci_device_add(struct pci_dev *dev, struct pci_bus *bus)
+void pci_device_add(struct pci_dev *dev, struct pci_bus *bus)
 {
 	device_initialize(&dev->dev);
 	dev->dev.release = pci_release_dev;
@@ -935,8 +952,7 @@
 	up_write(&pci_bus_sem);
 }
 
-struct pci_dev * __devinit
-pci_scan_single_device(struct pci_bus *bus, int devfn)
+struct pci_dev *pci_scan_single_device(struct pci_bus *bus, int devfn)
 {
 	struct pci_dev *dev;
 
@@ -958,7 +974,7 @@
  * discovered devices to the @bus->devices list.  New devices
  * will have an empty dev->global_list head.
  */
-int __devinit pci_scan_slot(struct pci_bus *bus, int devfn)
+int pci_scan_slot(struct pci_bus *bus, int devfn)
 {
 	int func, nr = 0;
 	int scan_all_fns;
@@ -991,7 +1007,7 @@
 	return nr;
 }
 
-unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus)
+unsigned int pci_scan_child_bus(struct pci_bus *bus)
 {
 	unsigned int devfn, pass, max = bus->secondary;
 	struct pci_dev *dev;
@@ -1041,7 +1057,7 @@
 	return max;
 }
 
-struct pci_bus * __devinit pci_create_bus(struct device *parent,
+struct pci_bus * pci_create_bus(struct device *parent,
 		int bus, struct pci_ops *ops, void *sysdata)
 {
 	int error;
@@ -1119,7 +1135,7 @@
 }
 EXPORT_SYMBOL_GPL(pci_create_bus);
 
-struct pci_bus * __devinit pci_scan_bus_parented(struct device *parent,
+struct pci_bus *pci_scan_bus_parented(struct device *parent,
 		int bus, struct pci_ops *ops, void *sysdata)
 {
 	struct pci_bus *b;
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 3411483..147d86f 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -1648,6 +1648,8 @@
 	}
 }
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk_disable_msi);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RS400_200, quirk_disable_msi);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RS480, quirk_disable_msi);
 
 /* Go through the list of Hypertransport capabilities and
  * return 1 if a HT MSI capability is found and enabled */
diff --git a/drivers/pci/search.c b/drivers/pci/search.c
index 2dd8681..b137a27 100644
--- a/drivers/pci/search.c
+++ b/drivers/pci/search.c
@@ -15,8 +15,7 @@
 
 DECLARE_RWSEM(pci_bus_sem);
 
-static struct pci_bus *
-pci_do_find_bus(struct pci_bus* bus, unsigned char busnr)
+static struct pci_bus *pci_do_find_bus(struct pci_bus *bus, unsigned char busnr)
 {
 	struct pci_bus* child;
 	struct list_head *tmp;
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 3554f39..5ec297d7 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -36,8 +36,7 @@
 
 #define ROUND_UP(x, a)		(((x) + (a) - 1) & ~((a) - 1))
 
-static void __devinit
-pbus_assign_resources_sorted(struct pci_bus *bus)
+static void pbus_assign_resources_sorted(struct pci_bus *bus)
 {
 	struct pci_dev *dev;
 	struct resource *res;
@@ -220,8 +219,7 @@
 /* Check whether the bridge supports optional I/O and
    prefetchable memory ranges. If not, the respective
    base/limit registers must be read-only and read as 0. */
-static void __devinit
-pci_bridge_check_ranges(struct pci_bus *bus)
+static void pci_bridge_check_ranges(struct pci_bus *bus)
 {
 	u16 io;
 	u32 pmem;
@@ -259,8 +257,7 @@
    bus resource of a given type. Note: we intentionally skip
    the bus resources which have already been assigned (that is,
    have non-NULL parent resource). */
-static struct resource * __devinit
-find_free_bus_resource(struct pci_bus *bus, unsigned long type)
+static struct resource *find_free_bus_resource(struct pci_bus *bus, unsigned long type)
 {
 	int i;
 	struct resource *r;
@@ -281,8 +278,7 @@
    since these windows have 4K granularity and the IO ranges
    of non-bridge PCI devices are limited to 256 bytes.
    We must be careful with the ISA aliasing though. */
-static void __devinit
-pbus_size_io(struct pci_bus *bus)
+static void pbus_size_io(struct pci_bus *bus)
 {
 	struct pci_dev *dev;
 	struct resource *b_res = find_free_bus_resource(bus, IORESOURCE_IO);
@@ -326,8 +322,7 @@
 
 /* Calculate the size of the bus and minimal alignment which
    guarantees that all child resources fit in this size. */
-static int __devinit
-pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long type)
+static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long type)
 {
 	struct pci_dev *dev;
 	unsigned long min_align, align, size;
@@ -447,8 +442,7 @@
 	}
 }
 
-void __devinit
-pci_bus_size_bridges(struct pci_bus *bus)
+void pci_bus_size_bridges(struct pci_bus *bus)
 {
 	struct pci_dev *dev;
 	unsigned long mask, prefmask;
@@ -498,8 +492,7 @@
 }
 EXPORT_SYMBOL(pci_bus_size_bridges);
 
-void __devinit
-pci_bus_assign_resources(struct pci_bus *bus)
+void pci_bus_assign_resources(struct pci_bus *bus)
 {
 	struct pci_bus *b;
 	struct pci_dev *dev;
diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c
index cb4ced3..6dfd861 100644
--- a/drivers/pci/setup-res.c
+++ b/drivers/pci/setup-res.c
@@ -101,8 +101,7 @@
 		new & ~PCI_REGION_FLAG_MASK);
 }
 
-int __devinit
-pci_claim_resource(struct pci_dev *dev, int resource)
+int pci_claim_resource(struct pci_dev *dev, int resource)
 {
 	struct resource *res = &dev->resource[resource];
 	struct resource *root = NULL;
@@ -212,8 +211,7 @@
 #endif
 
 /* Sort resources by alignment */
-void __devinit
-pdev_sort_resources(struct pci_dev *dev, struct resource_list *head)
+void pdev_sort_resources(struct pci_dev *dev, struct resource_list *head)
 {
 	int i;
 
diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c
index ac00424..50cad3a 100644
--- a/drivers/pcmcia/cs.c
+++ b/drivers/pcmcia/cs.c
@@ -26,7 +26,6 @@
 #include <linux/ioport.h>
 #include <linux/delay.h>
 #include <linux/pm.h>
-#include <linux/pci.h>
 #include <linux/device.h>
 #include <linux/kthread.h>
 #include <linux/freezer.h>
diff --git a/drivers/pcmcia/socket_sysfs.c b/drivers/pcmcia/socket_sysfs.c
index ea5765c..a2bb465 100644
--- a/drivers/pcmcia/socket_sysfs.c
+++ b/drivers/pcmcia/socket_sysfs.c
@@ -22,7 +22,6 @@
 #include <linux/ioport.h>
 #include <linux/delay.h>
 #include <linux/pm.h>
-#include <linux/pci.h>
 #include <linux/device.h>
 #include <linux/mutex.h>
 #include <asm/system.h>
diff --git a/drivers/ps3/ps3av.c b/drivers/ps3/ps3av.c
index d21e04c..1393e64 100644
--- a/drivers/ps3/ps3av.c
+++ b/drivers/ps3/ps3av.c
@@ -38,7 +38,24 @@
 static int timeout = 5000;	/* in msec ( 5 sec ) */
 module_param(timeout, int, 0644);
 
-static struct ps3av ps3av;
+static struct ps3av {
+	int available;
+	struct mutex mutex;
+	struct work_struct work;
+	struct completion done;
+	struct workqueue_struct *wq;
+	int open_count;
+	struct ps3_vuart_port_device *dev;
+
+	int region;
+	struct ps3av_pkt_av_get_hw_conf av_hw_conf;
+	u32 av_port[PS3AV_AV_PORT_MAX + PS3AV_OPT_PORT_MAX];
+	u32 opt_port[PS3AV_OPT_PORT_MAX];
+	u32 head[PS3AV_HEAD_MAX];
+	u32 audio_port;
+	int ps3av_mode;
+	int ps3av_mode_old;
+} ps3av;
 
 static struct ps3_vuart_port_device ps3av_dev = {
 	.match_id = PS3_MATCH_ID_AV_SETTINGS
@@ -159,7 +176,7 @@
 		else
 			printk(KERN_ERR
 			       "%s: failed event packet, cid:%08x size:%d\n",
-			       __FUNCTION__, hdr->cid, hdr->size);
+			       __func__, hdr->cid, hdr->size);
 		return 1;	/* receive event packet */
 	}
 	return 0;
@@ -181,7 +198,7 @@
 	if (res < 0) {
 		dev_dbg(&ps3av_dev.core,
 			"%s: ps3av_vuart_write() failed (result=%d)\n",
-			__FUNCTION__, res);
+			__func__, res);
 		return res;
 	}
 
@@ -194,7 +211,7 @@
 		if (res != PS3AV_HDR_SIZE) {
 			dev_dbg(&ps3av_dev.core,
 				"%s: ps3av_vuart_read() failed (result=%d)\n",
-				__FUNCTION__, res);
+				__func__, res);
 			return res;
 		}
 
@@ -204,7 +221,7 @@
 		if (res < 0) {
 			dev_dbg(&ps3av_dev.core,
 				"%s: ps3av_vuart_read() failed (result=%d)\n",
-				__FUNCTION__, res);
+				__func__, res);
 			return res;
 		}
 		res += PS3AV_HDR_SIZE;	/* total len */
@@ -214,7 +231,7 @@
 
 	if ((cmd | PS3AV_REPLY_BIT) != recv_buf->cid) {
 		dev_dbg(&ps3av_dev.core, "%s: reply err (result=%x)\n",
-			__FUNCTION__, recv_buf->cid);
+			__func__, recv_buf->cid);
 		return -EINVAL;
 	}
 
@@ -250,7 +267,7 @@
 		 struct ps3av_send_hdr *buf)
 {
 	int res = 0;
-	union {
+	static union {
 		struct ps3av_reply_hdr reply_hdr;
 		u8 raw[PS3AV_BUF_SIZE];
 	} recv_buf;
@@ -259,8 +276,7 @@
 
 	BUG_ON(!ps3av.available);
 
-	if (down_interruptible(&ps3av.sem))
-		return -ERESTARTSYS;
+	mutex_lock(&ps3av.mutex);
 
 	table = ps3av_search_cmd_table(cid, PS3AV_CID_MASK);
 	BUG_ON(!table);
@@ -277,7 +293,7 @@
 	if (res < 0) {
 		printk(KERN_ERR
 		       "%s: ps3av_send_cmd_pkt() failed (result=%d)\n",
-		       __FUNCTION__, res);
+		       __func__, res);
 		goto err;
 	}
 
@@ -286,16 +302,16 @@
 					 usr_buf_size);
 	if (res < 0) {
 		printk(KERN_ERR "%s: put_return_status() failed (result=%d)\n",
-		       __FUNCTION__, res);
+		       __func__, res);
 		goto err;
 	}
 
-	up(&ps3av.sem);
+	mutex_unlock(&ps3av.mutex);
 	return 0;
 
       err:
-	up(&ps3av.sem);
-	printk(KERN_ERR "%s: failed cid:%x res:%d\n", __FUNCTION__, cid, res);
+	mutex_unlock(&ps3av.mutex);
+	printk(KERN_ERR "%s: failed cid:%x res:%d\n", __func__, cid, res);
 	return res;
 }
 
@@ -440,7 +456,7 @@
 	ps3av_set_av_video_mute(PS3AV_CMD_MUTE_ON);
 
 	/* wake up ps3avd to do the actual video mode setting */
-	up(&ps3av.ping);
+	queue_work(ps3av.wq, &ps3av.work);
 
 	return 0;
 }
@@ -506,7 +522,7 @@
 	if (res == PS3AV_STATUS_NO_SYNC_HEAD)
 		printk(KERN_WARNING
 		       "%s: Command failed. Please try your request again. \n",
-		       __FUNCTION__);
+		       __func__);
 	else if (res)
 		dev_dbg(&ps3av_dev.core, "ps3av_cmd_avb_param failed\n");
 
@@ -515,18 +531,10 @@
 	ps3av_set_av_video_mute(PS3AV_CMD_MUTE_OFF);
 }
 
-static int ps3avd(void *p)
+static void ps3avd(struct work_struct *work)
 {
-	struct ps3av *info = p;
-
-	daemonize("ps3avd");
-	while (1) {
-		down(&info->ping);
-		ps3av_set_videomode_cont(info->ps3av_mode,
-					 info->ps3av_mode_old);
-		up(&info->pong);
-	}
-	return 0;
+	ps3av_set_videomode_cont(ps3av.ps3av_mode, ps3av.ps3av_mode_old);
+	complete(&ps3av.done);
 }
 
 static int ps3av_vid2table_id(int vid)
@@ -707,8 +715,7 @@
 
 	size = ARRAY_SIZE(video_mode_table);
 	if ((id & PS3AV_MODE_MASK) > size - 1 || id < 0) {
-		dev_dbg(&ps3av_dev.core, "%s: error id :%d\n", __FUNCTION__,
-			id);
+		dev_dbg(&ps3av_dev.core, "%s: error id :%d\n", __func__, id);
 		return -EINVAL;
 	}
 
@@ -717,15 +724,14 @@
 	if ((id & PS3AV_MODE_MASK) == 0) {
 		id = ps3av_auto_videomode(&ps3av.av_hw_conf, boot);
 		if (id < 1) {
-			printk(KERN_ERR "%s: invalid id :%d\n", __FUNCTION__,
-			       id);
+			printk(KERN_ERR "%s: invalid id :%d\n", __func__, id);
 			return -EINVAL;
 		}
 		id |= option;
 	}
 
 	/* set videomode */
-	down(&ps3av.pong);
+	wait_for_completion(&ps3av.done);
 	ps3av.ps3av_mode_old = ps3av.ps3av_mode;
 	ps3av.ps3av_mode = id;
 	if (ps3av_set_videomode())
@@ -736,6 +742,13 @@
 
 EXPORT_SYMBOL_GPL(ps3av_set_video_mode);
 
+int ps3av_get_auto_mode(int boot)
+{
+	return ps3av_auto_videomode(&ps3av.av_hw_conf, boot);
+}
+
+EXPORT_SYMBOL_GPL(ps3av_get_auto_mode);
+
 int ps3av_set_mode(u32 id, int boot)
 {
 	int res;
@@ -771,7 +784,7 @@
 	id = id & PS3AV_MODE_MASK;
 	size = ARRAY_SIZE(video_mode_table);
 	if (id > size - 1 || id < 0) {
-		printk(KERN_ERR "%s: invalid mode %d\n", __FUNCTION__, id);
+		printk(KERN_ERR "%s: invalid mode %d\n", __func__, id);
 		return -EINVAL;
 	}
 	return video_mode_table[id].interlace;
@@ -786,7 +799,7 @@
 	id = id & PS3AV_MODE_MASK;
 	size = ARRAY_SIZE(video_mode_table);
 	if (id > size - 1 || id < 0) {
-		printk(KERN_ERR "%s: invalid mode %d\n", __FUNCTION__, id);
+		printk(KERN_ERR "%s: invalid mode %d\n", __func__, id);
 		return -EINVAL;
 	}
 	return video_mode_table[id].freq;
@@ -802,7 +815,7 @@
 	id = id & PS3AV_MODE_MASK;
 	size = ARRAY_SIZE(video_mode_table);
 	if (id > size - 1 || id < 0) {
-		printk(KERN_ERR "%s: invalid mode %d\n", __FUNCTION__, id);
+		printk(KERN_ERR "%s: invalid mode %d\n", __func__, id);
 		return -EINVAL;
 	}
 	*xres = video_mode_table[id].x;
@@ -838,7 +851,7 @@
 		status = lv1_gpu_open(0);
 		if (status) {
 			printk(KERN_ERR "%s: lv1_gpu_open failed %d\n",
-			       __FUNCTION__, status);
+			       __func__, status);
 			ps3av.open_count--;
 		}
 	}
@@ -855,13 +868,13 @@
 
 	mutex_lock(&ps3av.mutex);
 	if (ps3av.open_count <= 0) {
-		printk(KERN_ERR "%s: GPU already closed\n", __FUNCTION__);
+		printk(KERN_ERR "%s: GPU already closed\n", __func__);
 		status = -1;
 	} else if (!--ps3av.open_count) {
 		status = lv1_gpu_close();
 		if (status)
 			printk(KERN_WARNING "%s: lv1_gpu_close failed %d\n",
-			       __FUNCTION__, status);
+			       __func__, status);
 	}
 	mutex_unlock(&ps3av.mutex);
 
@@ -880,13 +893,16 @@
 
 	memset(&ps3av, 0, sizeof(ps3av));
 
-	init_MUTEX(&ps3av.sem);
-	init_MUTEX_LOCKED(&ps3av.ping);
-	init_MUTEX(&ps3av.pong);
 	mutex_init(&ps3av.mutex);
 	ps3av.ps3av_mode = 0;
 	ps3av.dev = dev;
-	kernel_thread(ps3avd, &ps3av, CLONE_KERNEL);
+
+	INIT_WORK(&ps3av.work, ps3avd);
+	init_completion(&ps3av.done);
+	complete(&ps3av.done);
+	ps3av.wq = create_singlethread_workqueue("ps3avd");
+	if (!ps3av.wq)
+		return -ENOMEM;
 
 	ps3av.available = 1;
 	switch (ps3_os_area_get_av_multi_out()) {
@@ -908,7 +924,7 @@
 	/* init avsetting modules */
 	res = ps3av_cmd_init();
 	if (res < 0)
-		printk(KERN_ERR "%s: ps3av_cmd_init failed %d\n", __FUNCTION__,
+		printk(KERN_ERR "%s: ps3av_cmd_init failed %d\n", __func__,
 		       res);
 
 	ps3av_get_hw_conf(&ps3av);
@@ -926,6 +942,8 @@
 {
 	if (ps3av.available) {
 		ps3av_cmd_fin();
+		if (ps3av.wq)
+			destroy_workqueue(ps3av.wq);
 		ps3av.available = 0;
 	}
 
@@ -958,7 +976,7 @@
 	if (error) {
 		printk(KERN_ERR
 		       "%s: ps3_vuart_port_driver_register failed %d\n",
-		       __FUNCTION__, error);
+		       __func__, error);
 		return error;
 	}
 
@@ -966,7 +984,7 @@
 	if (error)
 		printk(KERN_ERR
 		       "%s: ps3_vuart_port_device_register failed %d\n",
-		       __FUNCTION__, error);
+		       __func__, error);
 
 	return error;
 }
diff --git a/drivers/ps3/ps3av_cmd.c b/drivers/ps3/ps3av_cmd.c
index bc70e81f..0145ea1 100644
--- a/drivers/ps3/ps3av_cmd.c
+++ b/drivers/ps3/ps3av_cmd.c
@@ -395,7 +395,7 @@
 	video_mode->video_order = ps3av_video_fmt_table[video_fmt].order;
 
 	pr_debug("%s: video_mode:vid:%x width:%d height:%d pitch:%d out_format:%d format:%x order:%x\n",
-		__FUNCTION__, video_vid, video_mode->width, video_mode->height,
+		__func__, video_vid, video_mode->width, video_mode->height,
 		video_mode->pitch, video_mode->video_out_format,
 		video_mode->video_format, video_mode->video_order);
 	return sizeof(*video_mode);
@@ -477,7 +477,7 @@
 		if (ps3av_cnv_mclk_table[i].fs == fs)
 			return ps3av_cnv_mclk_table[i].mclk;
 
-	printk(KERN_ERR "%s failed, fs:%x\n", __FUNCTION__, fs);
+	printk(KERN_ERR "%s failed, fs:%x\n", __func__, fs);
 	return 0;
 }
 
@@ -526,13 +526,12 @@
 		d = 4;
 		break;
 	default:
-		printk(KERN_ERR "%s failed, vid:%x\n", __FUNCTION__,
-		       video_vid);
+		printk(KERN_ERR "%s failed, vid:%x\n", __func__, video_vid);
 		break;
 	}
 
 	if (fs < PS3AV_CMD_AUDIO_FS_44K || fs > PS3AV_CMD_AUDIO_FS_192K)
-		printk(KERN_ERR "%s failed, fs:%x\n", __FUNCTION__, fs);
+		printk(KERN_ERR "%s failed, fs:%x\n", __func__, fs);
 	else
 		ns_val = ps3av_ns_table[PS3AV_CMD_AUDIO_FS_44K-BASE][d];
 
@@ -555,8 +554,7 @@
 		ret = ((p[0] << 4) + (p[1] << 5) + (p[2] << 6) + (p[3] << 7)) |
 		      0x01;
 	} else
-		printk(KERN_ERR "%s failed, source:%x\n", __FUNCTION__,
-		       source);
+		printk(KERN_ERR "%s failed, source:%x\n", __func__, source);
 	return ret;
 }
 
@@ -585,7 +583,7 @@
 		ret = PS3AV_CMD_AV_INPUTLEN_24;
 		break;
 	default:
-		printk(KERN_ERR "%s failed, word_bits:%x\n", __FUNCTION__,
+		printk(KERN_ERR "%s failed, word_bits:%x\n", __func__,
 		       word_bits);
 		break;
 	}
@@ -595,7 +593,7 @@
 static u8 ps3av_cnv_layout(u32 num_of_ch)
 {
 	if (num_of_ch > PS3AV_CMD_AUDIO_NUM_OF_CH_8) {
-		printk(KERN_ERR "%s failed, num_of_ch:%x\n", __FUNCTION__,
+		printk(KERN_ERR "%s failed, num_of_ch:%x\n", __func__,
 		       num_of_ch);
 		return 0;
 	}
@@ -864,7 +862,7 @@
 
 	res = get_status(avb);
 	if (res)
-		pr_debug("%s: PS3AV_CID_AVB_PARAM: failed %x\n", __FUNCTION__,
+		pr_debug("%s: PS3AV_CID_AVB_PARAM: failed %x\n", __func__,
 			 res);
 
       out:
@@ -1013,7 +1011,7 @@
 			return size;
 		if (error != -EAGAIN) {
 			printk(KERN_ERR "%s: ps3_vuart_read failed %d\n",
-			       __FUNCTION__, error);
+			       __func__, error);
 			return error;
 		}
 		msleep(POLLING_INTERVAL);
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index e71929d..9775210 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -2174,6 +2174,51 @@
 	return ret;
 }
 
+struct dasd_ccw_req * dasd_generic_build_rdc(struct dasd_device *device,
+					     void *rdc_buffer,
+					     int rdc_buffer_size, char *magic)
+{
+	struct dasd_ccw_req *cqr;
+	struct ccw1 *ccw;
+
+	cqr = dasd_smalloc_request(magic, 1 /* RDC */, rdc_buffer_size, device);
+
+	if (IS_ERR(cqr)) {
+		DEV_MESSAGE(KERN_WARNING, device, "%s",
+			    "Could not allocate RDC request");
+		return cqr;
+	}
+
+	ccw = cqr->cpaddr;
+	ccw->cmd_code = CCW_CMD_RDC;
+	ccw->cda = (__u32)(addr_t)rdc_buffer;
+	ccw->count = rdc_buffer_size;
+
+	cqr->device = device;
+	cqr->expires = 10*HZ;
+	clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags);
+	cqr->retries = 2;
+	cqr->buildclk = get_clock();
+	cqr->status = DASD_CQR_FILLED;
+	return cqr;
+}
+
+
+int dasd_generic_read_dev_chars(struct dasd_device *device, char *magic,
+				void **rdc_buffer, int rdc_buffer_size)
+{
+	int ret;
+	struct dasd_ccw_req *cqr;
+
+	cqr = dasd_generic_build_rdc(device, *rdc_buffer, rdc_buffer_size,
+				     magic);
+	if (IS_ERR(cqr))
+		return PTR_ERR(cqr);
+
+	ret = dasd_sleep_on(cqr);
+	dasd_sfree_request(cqr, cqr->device);
+	return ret;
+}
 
 static int __init
 dasd_init(void)
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
index cecab22..c9583fb 100644
--- a/drivers/s390/block/dasd_eckd.c
+++ b/drivers/s390/block/dasd_eckd.c
@@ -450,6 +450,81 @@
 	return 0;
 }
 
+struct dasd_ccw_req * dasd_eckd_build_rcd_lpm(struct dasd_device *device,
+					      void *rcd_buffer,
+					      struct ciw *ciw, __u8 lpm)
+{
+	struct dasd_ccw_req *cqr;
+	struct ccw1 *ccw;
+
+	cqr = dasd_smalloc_request("ECKD", 1 /* RCD */, ciw->count, device);
+
+	if (IS_ERR(cqr)) {
+		DEV_MESSAGE(KERN_WARNING, device, "%s",
+			    "Could not allocate RCD request");
+		return cqr;
+	}
+
+	ccw = cqr->cpaddr;
+	ccw->cmd_code = ciw->cmd;
+	ccw->cda = (__u32)(addr_t)rcd_buffer;
+	ccw->count = ciw->count;
+
+	cqr->device = device;
+	cqr->expires = 10*HZ;
+	cqr->lpm = lpm;
+	clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags);
+	cqr->retries = 2;
+	cqr->buildclk = get_clock();
+	cqr->status = DASD_CQR_FILLED;
+	return cqr;
+}
+
+static int dasd_eckd_read_conf_lpm(struct dasd_device *device,
+				   void **rcd_buffer,
+				   int *rcd_buffer_size, __u8 lpm)
+{
+	struct ciw *ciw;
+	char *rcd_buf = NULL;
+	int ret;
+	struct dasd_ccw_req *cqr;
+
+	/*
+	 * scan for RCD command in extended SenseID data
+	 */
+	ciw = ccw_device_get_ciw(device->cdev, CIW_TYPE_RCD);
+	if (!ciw || ciw->cmd == 0) {
+		ret = -EOPNOTSUPP;
+		goto out_error;
+	}
+	rcd_buf = kzalloc(ciw->count, GFP_KERNEL | GFP_DMA);
+	if (!rcd_buf) {
+		ret = -ENOMEM;
+		goto out_error;
+	}
+	cqr = dasd_eckd_build_rcd_lpm(device, rcd_buf, ciw, lpm);
+	if (IS_ERR(cqr)) {
+		ret =  PTR_ERR(cqr);
+		goto out_error;
+	}
+	ret = dasd_sleep_on(cqr);
+	/*
+	 * on success we update the user input parms
+	 */
+	dasd_sfree_request(cqr, cqr->device);
+	if (ret)
+		goto out_error;
+
+	*rcd_buffer_size = ciw->count;
+	*rcd_buffer = rcd_buf;
+	return 0;
+out_error:
+	kfree(rcd_buf);
+	*rcd_buffer = NULL;
+	*rcd_buffer_size = 0;
+	return ret;
+}
+
 static int
 dasd_eckd_read_conf(struct dasd_device *device)
 {
@@ -469,8 +544,8 @@
 	/* get configuration data per operational path */
 	for (lpm = 0x80; lpm; lpm>>= 1) {
 		if (lpm & path_data->opm){
-			rc = read_conf_data_lpm(device->cdev, &conf_data,
-						&conf_len, lpm);
+			rc = dasd_eckd_read_conf_lpm(device, &conf_data,
+						     &conf_len, lpm);
 			if (rc && rc != -EOPNOTSUPP) {	/* -EOPNOTSUPP is ok */
 				MESSAGE(KERN_WARNING,
 					"Read configuration data returned "
@@ -639,7 +714,7 @@
 	/* Read Device Characteristics */
 	rdc_data = (void *) &(private->rdc_data);
 	memset(rdc_data, 0, sizeof(rdc_data));
-	rc = read_dev_chars(device->cdev, &rdc_data, 64);
+	rc = dasd_generic_read_dev_chars(device, "ECKD", &rdc_data, 64);
 	if (rc)
 		DEV_MESSAGE(KERN_WARNING, device,
 			    "Read device characteristics returned "
diff --git a/drivers/s390/block/dasd_fba.c b/drivers/s390/block/dasd_fba.c
index be0909e..da16ead 100644
--- a/drivers/s390/block/dasd_fba.c
+++ b/drivers/s390/block/dasd_fba.c
@@ -135,7 +135,7 @@
 	}
 	/* Read Device Characteristics */
 	rdc_data = (void *) &(private->rdc_data);
-	rc = read_dev_chars(device->cdev, &rdc_data, 32);
+	rc = dasd_generic_read_dev_chars(device, "FBA ", &rdc_data, 32);
 	if (rc) {
 		DEV_MESSAGE(KERN_WARNING, device,
 			    "Read device characteristics returned error %d",
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h
index a2cc69e..241294c 100644
--- a/drivers/s390/block/dasd_int.h
+++ b/drivers/s390/block/dasd_int.h
@@ -509,6 +509,8 @@
 int dasd_generic_set_offline (struct ccw_device *cdev);
 int dasd_generic_notify(struct ccw_device *, int);
 
+int dasd_generic_read_dev_chars(struct dasd_device *, char *, void **, int);
+
 /* externals in dasd_devmap.c */
 extern int dasd_max_devindex;
 extern int dasd_probeonly;
diff --git a/drivers/s390/char/tape.h b/drivers/s390/char/tape.h
index bb4ff53..3b52f5c 100644
--- a/drivers/s390/char/tape.h
+++ b/drivers/s390/char/tape.h
@@ -103,6 +103,7 @@
 	TO_CRYPT_OFF,	/* Disable encrpytion */
 	TO_KEKL_SET,	/* Set KEK label */
 	TO_KEKL_QUERY,	/* Query KEK label */
+	TO_RDC,		/* Read device characteristics */
 	TO_SIZE,	/* #entries in tape_op_t */
 };
 
diff --git a/drivers/s390/char/tape_3590.c b/drivers/s390/char/tape_3590.c
index 50f5eda..7e2b2ab 100644
--- a/drivers/s390/char/tape_3590.c
+++ b/drivers/s390/char/tape_3590.c
@@ -788,6 +788,7 @@
 	case TO_SIZE:
 	case TO_KEKL_SET:
 	case TO_KEKL_QUERY:
+	case TO_RDC:
 		break;
 	}
 	return TAPE_IO_SUCCESS;
@@ -1549,6 +1550,26 @@
 	return TAPE_IO_STOP;
 }
 
+
+static int tape_3590_read_dev_chars(struct tape_device *device,
+				    struct tape_3590_rdc_data *rdc_data)
+{
+	int rc;
+	struct tape_request *request;
+
+	request = tape_alloc_request(1, sizeof(*rdc_data));
+	if (IS_ERR(request))
+		return PTR_ERR(request);
+	request->op = TO_RDC;
+	tape_ccw_end(request->cpaddr, CCW_CMD_RDC, sizeof(*rdc_data),
+		     request->cpdata);
+	rc = tape_do_io(device, request);
+	if (rc == 0)
+		memcpy(rdc_data, request->cpdata, sizeof(*rdc_data));
+	tape_free_request(request);
+	return rc;
+}
+
 /*
  * Setup device function
  */
@@ -1557,7 +1578,7 @@
 {
 	int rc;
 	struct tape_3590_disc_data *data;
-	char *rdc_data;
+	struct tape_3590_rdc_data *rdc_data;
 
 	DBF_EVENT(6, "3590 device setup\n");
 	data = kzalloc(sizeof(struct tape_3590_disc_data), GFP_KERNEL | GFP_DMA);
@@ -1566,12 +1587,12 @@
 	data->read_back_op = READ_PREVIOUS;
 	device->discdata = data;
 
-	rdc_data = kmalloc(64, GFP_KERNEL | GFP_DMA);
+	rdc_data = kmalloc(sizeof(*rdc_data), GFP_KERNEL | GFP_DMA);
 	if (!rdc_data) {
 		rc = -ENOMEM;
 		goto fail_kmalloc;
 	}
-	rc = read_dev_chars(device->cdev, (void**)&rdc_data, 64);
+	rc = tape_3590_read_dev_chars(device, rdc_data);
 	if (rc) {
 		DBF_LH(3, "Read device characteristics failed!\n");
 		goto fail_kmalloc;
@@ -1579,7 +1600,7 @@
 	rc = tape_std_assign(device);
 	if (rc)
 		goto fail_rdc_data;
-	if (rdc_data[31] == 0x13) {
+	if (rdc_data->data[31] == 0x13) {
 		PRINT_INFO("Device has crypto support\n");
 		data->crypt_info.capability |= TAPE390_CRYPT_SUPPORTED_MASK;
 		tape_3592_disable_crypt(device);
diff --git a/drivers/s390/char/tape_3590.h b/drivers/s390/char/tape_3590.h
index aa51388..4534055 100644
--- a/drivers/s390/char/tape_3590.h
+++ b/drivers/s390/char/tape_3590.h
@@ -129,6 +129,10 @@
 	char pad2[116];
 } __attribute__ ((packed));
 
+struct tape_3590_rdc_data {
+	char data[64];
+} __attribute__ ((packed));
+
 /* Datastructures for 3592 encryption support */
 
 struct tape3592_kekl {
diff --git a/drivers/s390/char/tape_core.c b/drivers/s390/char/tape_core.c
index e2a8a1a..2fae633 100644
--- a/drivers/s390/char/tape_core.c
+++ b/drivers/s390/char/tape_core.c
@@ -73,7 +73,7 @@
 	[TO_DIS] = "DIS",	[TO_ASSIGN] = "ASS",
 	[TO_UNASSIGN] = "UAS",  [TO_CRYPT_ON] = "CON",
 	[TO_CRYPT_OFF] = "COF",	[TO_KEKL_SET] = "KLS",
-	[TO_KEKL_QUERY] = "KLQ",
+	[TO_KEKL_QUERY] = "KLQ",[TO_RDC] = "RDC",
 };
 
 static int
@@ -911,6 +911,7 @@
 		case TO_ASSIGN:
 		case TO_UNASSIGN:
 		case TO_READ_ATTMSG:
+		case TO_RDC:
 			if (device->tape_state == TS_INIT)
 				break;
 			if (device->tape_state == TS_UNUSED)
diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c
index 05fac07..cba64e4 100644
--- a/drivers/s390/cio/qdio.c
+++ b/drivers/s390/cio/qdio.c
@@ -69,7 +69,6 @@
 
 static int qdio_performance_stats = 0;
 static int proc_perf_file_registration;
-static unsigned long i_p_c, i_p_nc, o_p_c, o_p_nc, ii_p_c, ii_p_nc;
 static struct qdio_perf_stats perf_stats;
 
 static int hydra_thinints;
@@ -111,6 +110,31 @@
 }
 
 /***************** SCRUBBER HELPER ROUTINES **********************/
+#ifdef CONFIG_64BIT
+static inline void qdio_perf_stat_inc(atomic64_t *count)
+{
+	if (qdio_performance_stats)
+		atomic64_inc(count);
+}
+
+static inline void qdio_perf_stat_dec(atomic64_t *count)
+{
+	if (qdio_performance_stats)
+		atomic64_dec(count);
+}
+#else /* CONFIG_64BIT */
+static inline void qdio_perf_stat_inc(atomic_t *count)
+{
+	if (qdio_performance_stats)
+		atomic_inc(count);
+}
+
+static inline void qdio_perf_stat_dec(atomic_t *count)
+{
+	if (qdio_performance_stats)
+		atomic_dec(count);
+}
+#endif /* CONFIG_64BIT */
 
 static inline __u64 
 qdio_get_micros(void)
@@ -277,8 +301,7 @@
 	QDIO_DBF_TEXT4(0,trace,"sigasync");
 	QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
 
-	if (qdio_performance_stats)
-		perf_stats.siga_syncs++;
+	qdio_perf_stat_inc(&perf_stats.siga_syncs);
 
 	cc = do_siga_sync(q->schid, gpr2, gpr3);
 	if (cc)
@@ -323,8 +346,7 @@
 	__u32 busy_bit;
 	__u64 start_time=0;
 
-	if (qdio_performance_stats)
-		perf_stats.siga_outs++;
+	qdio_perf_stat_inc(&perf_stats.siga_outs);
 
 	QDIO_DBF_TEXT4(0,trace,"sigaout");
 	QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
@@ -358,8 +380,7 @@
 	QDIO_DBF_TEXT4(0,trace,"sigain");
 	QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
 
-	if (qdio_performance_stats)
-		perf_stats.siga_ins++;
+	qdio_perf_stat_inc(&perf_stats.siga_ins);
 
 	cc = do_siga_input(q->schid, q->mask);
 	
@@ -953,8 +974,7 @@
 
 	if (unlikely(qdio_reserve_q(q))) {
 		qdio_release_q(q);
-		if (qdio_performance_stats)
-			o_p_c++;
+		qdio_perf_stat_inc(&perf_stats.outbound_tl_runs_resched);
 		/* as we're sissies, we'll check next time */
 		if (likely(!atomic_read(&q->is_in_shutdown))) {
 			qdio_mark_q(q);
@@ -962,10 +982,8 @@
 		}
 		return;
 	}
-	if (qdio_performance_stats) {
-		o_p_nc++;
-		perf_stats.tl_runs++;
-	}
+	qdio_perf_stat_inc(&perf_stats.outbound_tl_runs);
+	qdio_perf_stat_inc(&perf_stats.tl_runs);
 
 	/* see comment in qdio_kick_outbound_q */
 	siga_attempts=atomic_read(&q->busy_siga_counter);
@@ -1139,17 +1157,6 @@
 {
 	int i;
 
-	static int old_pcis=0;
-	static int old_thinints=0;
-
-	if (qdio_performance_stats) {
-		if ((old_pcis==perf_stats.pcis)&&
-		    (old_thinints==perf_stats.thinints))
-			perf_stats.start_time_inbound=NOW;
-		else
-			old_pcis=perf_stats.pcis;
-	}
-
 	i=qdio_get_inbound_buffer_frontier(q);
 	if ( (i!=GET_SAVED_FRONTIER(q)) ||
 	     (q->error_status_flags&QDIO_STATUS_LOOK_FOR_ERROR) ) {
@@ -1337,10 +1344,7 @@
 	q->siga_error=0;
 	q->error_status_flags=0;
 
-	if (qdio_performance_stats) {
-		perf_stats.inbound_time+=NOW-perf_stats.start_time_inbound;
-		perf_stats.inbound_cnt++;
-	}
+	qdio_perf_stat_inc(&perf_stats.inbound_cnt);
 }
 
 static void
@@ -1360,8 +1364,7 @@
 	 */
 	if (unlikely(qdio_reserve_q(q))) {
 		qdio_release_q(q);
-		if (qdio_performance_stats)
-			ii_p_c++;
+		qdio_perf_stat_inc(&perf_stats.inbound_thin_tl_runs_resched);
 		/* 
 		 * as we might just be about to stop polling, we make
 		 * sure that we check again at least once more 
@@ -1369,8 +1372,7 @@
 		tiqdio_sched_tl();
 		return;
 	}
-	if (qdio_performance_stats)
-		ii_p_nc++;
+	qdio_perf_stat_inc(&perf_stats.inbound_thin_tl_runs);
 	if (unlikely(atomic_read(&q->is_in_shutdown))) {
 		qdio_unmark_q(q);
 		goto out;
@@ -1412,8 +1414,7 @@
 		for (i=0;i<irq_ptr->no_output_qs;i++) {
 			oq = irq_ptr->output_qs[i];
 			if (!qdio_is_outbound_q_done(oq)) {
-				if (qdio_performance_stats)
-					perf_stats.tl_runs--;
+				qdio_perf_stat_dec(&perf_stats.tl_runs);
 				__qdio_outbound_processing(oq);
 			}
 		}
@@ -1452,8 +1453,7 @@
 
 	if (unlikely(qdio_reserve_q(q))) {
 		qdio_release_q(q);
-		if (qdio_performance_stats)
-			i_p_c++;
+		qdio_perf_stat_inc(&perf_stats.inbound_tl_runs_resched);
 		/* as we're sissies, we'll check next time */
 		if (likely(!atomic_read(&q->is_in_shutdown))) {
 			qdio_mark_q(q);
@@ -1461,10 +1461,8 @@
 		}
 		return;
 	}
-	if (qdio_performance_stats) {
-		i_p_nc++;
-		perf_stats.tl_runs++;
-	}
+	qdio_perf_stat_inc(&perf_stats.inbound_tl_runs);
+	qdio_perf_stat_inc(&perf_stats.tl_runs);
 
 again:
 	if (qdio_has_inbound_q_moved(q)) {
@@ -1510,8 +1508,7 @@
 
 	if (unlikely(qdio_reserve_q(q))) {
 		qdio_release_q(q);
-		if (qdio_performance_stats)
-			ii_p_c++;
+		qdio_perf_stat_inc(&perf_stats.inbound_thin_tl_runs_resched);
 		/* 
 		 * as we might just be about to stop polling, we make
 		 * sure that we check again at least once more 
@@ -1602,8 +1599,7 @@
 {
 	QDIO_DBF_TEXT4(0,trace,"iqdio_tl");
 
-	if (qdio_performance_stats)
-		perf_stats.tl_runs++;
+	qdio_perf_stat_inc(&perf_stats.tl_runs);
 
 	tiqdio_inbound_checks();
 }
@@ -1914,10 +1910,7 @@
 {
 	QDIO_DBF_TEXT4(0,trace,"thin_int");
 
-	if (qdio_performance_stats) {
-		perf_stats.thinints++;
-		perf_stats.start_time_inbound=NOW;
-	}
+	qdio_perf_stat_inc(&perf_stats.thinints);
 
 	/* SVS only when needed:
 	 * issue SVS to benefit from iqdio interrupt avoidance
@@ -1972,17 +1965,12 @@
 	int i;
 	struct qdio_q *q;
 
-	if (qdio_performance_stats) {
-		perf_stats.pcis++;
-		perf_stats.start_time_inbound=NOW;
-	}
+	qdio_perf_stat_inc(&perf_stats.pcis);
 	for (i=0;i<irq_ptr->no_input_qs;i++) {
 		q=irq_ptr->input_qs[i];
 		if (q->is_input_q&QDIO_FLAG_NO_INPUT_INTERRUPT_CONTEXT)
 			qdio_mark_q(q);
 		else {
-			if (qdio_performance_stats)
-				perf_stats.tl_runs--;
 			__qdio_inbound_processing(q);
 		}
 	}
@@ -1992,8 +1980,7 @@
 		q=irq_ptr->output_qs[i];
 		if (qdio_is_outbound_q_done(q))
 			continue;
-		if (qdio_performance_stats)
-			perf_stats.tl_runs--;
+		qdio_perf_stat_dec(&perf_stats.tl_runs);
 		if (!irq_ptr->sync_done_on_outb_pcis)
 			SYNC_MEMORY;
 		__qdio_outbound_processing(q);
@@ -3463,18 +3450,12 @@
 	struct qdio_irq *irq = (struct qdio_irq *) q->irq_ptr;
 
 	/* This is the outbound handling of queues */
-	if (qdio_performance_stats)
-		perf_stats.start_time_outbound=NOW;
-
 	qdio_do_qdio_fill_output(q,qidx,count,buffers);
 
 	used_elements=atomic_add_return(count, &q->number_of_buffers_used) - count;
 
 	if (callflags&QDIO_FLAG_DONT_SIGA) {
-		if (qdio_performance_stats) {
-			perf_stats.outbound_time+=NOW-perf_stats.start_time_outbound;
-			perf_stats.outbound_cnt++;
-		}
+		qdio_perf_stat_inc(&perf_stats.outbound_cnt);
 		return;
 	}
 	if (q->is_iqdio_q) {
@@ -3504,8 +3485,7 @@
 				qdio_kick_outbound_q(q);
 			} else {
 				QDIO_DBF_TEXT3(0,trace, "fast-req");
-				if (qdio_performance_stats)
-					perf_stats.fast_reqs++;
+				qdio_perf_stat_inc(&perf_stats.fast_reqs);
 			}
 		}
 		/* 
@@ -3516,10 +3496,7 @@
 		__qdio_outbound_processing(q);
 	}
 
-	if (qdio_performance_stats) {
-		perf_stats.outbound_time+=NOW-perf_stats.start_time_outbound;
-		perf_stats.outbound_cnt++;
-	}
+	qdio_perf_stat_inc(&perf_stats.outbound_cnt);
 }
 
 /* count must be 1 in iqdio */
@@ -3589,33 +3566,67 @@
 		return 0;
 
 #define _OUTP_IT(x...) c+=sprintf(buffer+c,x)
-	_OUTP_IT("i_p_nc/c=%lu/%lu\n",i_p_nc,i_p_c);
-	_OUTP_IT("ii_p_nc/c=%lu/%lu\n",ii_p_nc,ii_p_c);
-	_OUTP_IT("o_p_nc/c=%lu/%lu\n",o_p_nc,o_p_c);
-	_OUTP_IT("Number of tasklet runs (total)                  : %lu\n",
-		 perf_stats.tl_runs);
+#ifdef CONFIG_64BIT
+	_OUTP_IT("Number of tasklet runs (total)                  : %li\n",
+		 (long)atomic64_read(&perf_stats.tl_runs));
+	_OUTP_IT("Inbound tasklet runs      tried/retried         : %li/%li\n",
+		 (long)atomic64_read(&perf_stats.inbound_tl_runs),
+		 (long)atomic64_read(&perf_stats.inbound_tl_runs_resched));
+	_OUTP_IT("Inbound-thin tasklet runs tried/retried         : %li/%li\n",
+		 (long)atomic64_read(&perf_stats.inbound_thin_tl_runs),
+		 (long)atomic64_read(&perf_stats.inbound_thin_tl_runs_resched));
+	_OUTP_IT("Outbound tasklet runs     tried/retried         : %li/%li\n",
+		 (long)atomic64_read(&perf_stats.outbound_tl_runs),
+		 (long)atomic64_read(&perf_stats.outbound_tl_runs_resched));
 	_OUTP_IT("\n");
-	_OUTP_IT("Number of SIGA sync's issued                    : %lu\n",
-		 perf_stats.siga_syncs);
-	_OUTP_IT("Number of SIGA in's issued                      : %lu\n",
-		 perf_stats.siga_ins);
-	_OUTP_IT("Number of SIGA out's issued                     : %lu\n",
-		 perf_stats.siga_outs);
-	_OUTP_IT("Number of PCIs caught                           : %lu\n",
-		 perf_stats.pcis);
-	_OUTP_IT("Number of adapter interrupts caught             : %lu\n",
-		 perf_stats.thinints);
-	_OUTP_IT("Number of fast requeues (outg. SBALs w/o SIGA)  : %lu\n",
-		 perf_stats.fast_reqs);
+	_OUTP_IT("Number of SIGA sync's issued                    : %li\n",
+		 (long)atomic64_read(&perf_stats.siga_syncs));
+	_OUTP_IT("Number of SIGA in's issued                      : %li\n",
+		 (long)atomic64_read(&perf_stats.siga_ins));
+	_OUTP_IT("Number of SIGA out's issued                     : %li\n",
+		 (long)atomic64_read(&perf_stats.siga_outs));
+	_OUTP_IT("Number of PCIs caught                           : %li\n",
+		 (long)atomic64_read(&perf_stats.pcis));
+	_OUTP_IT("Number of adapter interrupts caught             : %li\n",
+		 (long)atomic64_read(&perf_stats.thinints));
+	_OUTP_IT("Number of fast requeues (outg. SBALs w/o SIGA)  : %li\n",
+		 (long)atomic64_read(&perf_stats.fast_reqs));
 	_OUTP_IT("\n");
-	_OUTP_IT("Total time of all inbound actions (us) incl. UL : %lu\n",
-		 perf_stats.inbound_time);
-	_OUTP_IT("Number of inbound transfers                     : %lu\n",
-		 perf_stats.inbound_cnt);
-	_OUTP_IT("Total time of all outbound do_QDIOs (us)        : %lu\n",
-		 perf_stats.outbound_time);
-	_OUTP_IT("Number of do_QDIOs outbound                     : %lu\n",
-		 perf_stats.outbound_cnt);
+	_OUTP_IT("Number of inbound transfers                     : %li\n",
+		 (long)atomic64_read(&perf_stats.inbound_cnt));
+	_OUTP_IT("Number of do_QDIOs outbound                     : %li\n",
+		 (long)atomic64_read(&perf_stats.outbound_cnt));
+#else /* CONFIG_64BIT */
+	_OUTP_IT("Number of tasklet runs (total)                  : %i\n",
+		 atomic_read(&perf_stats.tl_runs));
+	_OUTP_IT("Inbound tasklet runs      tried/retried         : %i/%i\n",
+		 atomic_read(&perf_stats.inbound_tl_runs),
+		 atomic_read(&perf_stats.inbound_tl_runs_resched));
+	_OUTP_IT("Inbound-thin tasklet runs tried/retried         : %i/%i\n",
+		 atomic_read(&perf_stats.inbound_thin_tl_runs),
+		 atomic_read(&perf_stats.inbound_thin_tl_runs_resched));
+	_OUTP_IT("Outbound tasklet runs     tried/retried         : %i/%i\n",
+		 atomic_read(&perf_stats.outbound_tl_runs),
+		 atomic_read(&perf_stats.outbound_tl_runs_resched));
+	_OUTP_IT("\n");
+	_OUTP_IT("Number of SIGA sync's issued                    : %i\n",
+		 atomic_read(&perf_stats.siga_syncs));
+	_OUTP_IT("Number of SIGA in's issued                      : %i\n",
+		 atomic_read(&perf_stats.siga_ins));
+	_OUTP_IT("Number of SIGA out's issued                     : %i\n",
+		 atomic_read(&perf_stats.siga_outs));
+	_OUTP_IT("Number of PCIs caught                           : %i\n",
+		 atomic_read(&perf_stats.pcis));
+	_OUTP_IT("Number of adapter interrupts caught             : %i\n",
+		 atomic_read(&perf_stats.thinints));
+	_OUTP_IT("Number of fast requeues (outg. SBALs w/o SIGA)  : %i\n",
+		 atomic_read(&perf_stats.fast_reqs));
+	_OUTP_IT("\n");
+	_OUTP_IT("Number of inbound transfers                     : %i\n",
+		 atomic_read(&perf_stats.inbound_cnt));
+	_OUTP_IT("Number of do_QDIOs outbound                     : %i\n",
+		 atomic_read(&perf_stats.outbound_cnt));
+#endif /* CONFIG_64BIT */
 	_OUTP_IT("\n");
 
         return c;
@@ -3642,8 +3653,6 @@
 static void
 qdio_remove_procfs_entry(void)
 {
-	perf_stats.tl_runs=0;
-
         if (!proc_perf_file_registration) /* means if it went ok earlier */
 		remove_proc_entry(QDIO_PERF,&proc_root);
 }
@@ -3671,13 +3680,38 @@
 		qdio_performance_stats = i;
 		if (i==0) {
 			/* reset perf. stat. info */
-			i_p_nc = 0;
-			i_p_c = 0;
-			ii_p_nc = 0;
-			ii_p_c = 0;
-			o_p_nc = 0;
-			o_p_c = 0;
-			memset(&perf_stats, 0, sizeof(struct qdio_perf_stats));
+#ifdef CONFIG_64BIT
+			atomic64_set(&perf_stats.tl_runs, 0);
+			atomic64_set(&perf_stats.outbound_tl_runs, 0);
+			atomic64_set(&perf_stats.inbound_tl_runs, 0);
+			atomic64_set(&perf_stats.inbound_tl_runs_resched, 0);
+			atomic64_set(&perf_stats.inbound_thin_tl_runs, 0);
+			atomic64_set(&perf_stats.inbound_thin_tl_runs_resched,
+				     0);
+			atomic64_set(&perf_stats.siga_outs, 0);
+			atomic64_set(&perf_stats.siga_ins, 0);
+			atomic64_set(&perf_stats.siga_syncs, 0);
+			atomic64_set(&perf_stats.pcis, 0);
+			atomic64_set(&perf_stats.thinints, 0);
+			atomic64_set(&perf_stats.fast_reqs, 0);
+			atomic64_set(&perf_stats.outbound_cnt, 0);
+			atomic64_set(&perf_stats.inbound_cnt, 0);
+#else /* CONFIG_64BIT */
+			atomic_set(&perf_stats.tl_runs, 0);
+			atomic_set(&perf_stats.outbound_tl_runs, 0);
+			atomic_set(&perf_stats.inbound_tl_runs, 0);
+			atomic_set(&perf_stats.inbound_tl_runs_resched, 0);
+			atomic_set(&perf_stats.inbound_thin_tl_runs, 0);
+			atomic_set(&perf_stats.inbound_thin_tl_runs_resched, 0);
+			atomic_set(&perf_stats.siga_outs, 0);
+			atomic_set(&perf_stats.siga_ins, 0);
+			atomic_set(&perf_stats.siga_syncs, 0);
+			atomic_set(&perf_stats.pcis, 0);
+			atomic_set(&perf_stats.thinints, 0);
+			atomic_set(&perf_stats.fast_reqs, 0);
+			atomic_set(&perf_stats.outbound_cnt, 0);
+			atomic_set(&perf_stats.inbound_cnt, 0);
+#endif /* CONFIG_64BIT */
 		}
 	} else {
 		QDIO_PRINT_WARN("QDIO performance_stats: write 0 or 1 to this file!\n");
diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h
index ec9af72..2895392 100644
--- a/drivers/s390/cio/qdio.h
+++ b/drivers/s390/cio/qdio.h
@@ -406,21 +406,43 @@
 #define CHSC_FLAG_SIGA_SYNC_DONE_ON_OUTB_PCIS 0x04
 
 struct qdio_perf_stats {
-	unsigned long tl_runs;
+#ifdef CONFIG_64BIT
+	atomic64_t tl_runs;
+	atomic64_t outbound_tl_runs;
+	atomic64_t outbound_tl_runs_resched;
+	atomic64_t inbound_tl_runs;
+	atomic64_t inbound_tl_runs_resched;
+	atomic64_t inbound_thin_tl_runs;
+	atomic64_t inbound_thin_tl_runs_resched;
 
-	unsigned long siga_outs;
-	unsigned long siga_ins;
-	unsigned long siga_syncs;
-	unsigned long pcis;
-	unsigned long thinints;
-	unsigned long fast_reqs;
+	atomic64_t siga_outs;
+	atomic64_t siga_ins;
+	atomic64_t siga_syncs;
+	atomic64_t pcis;
+	atomic64_t thinints;
+	atomic64_t fast_reqs;
 
-	__u64 start_time_outbound;
-	unsigned long outbound_cnt;
-	unsigned long outbound_time;
-	__u64 start_time_inbound;
-	unsigned long inbound_cnt;
-	unsigned long inbound_time;
+	atomic64_t outbound_cnt;
+	atomic64_t inbound_cnt;
+#else /* CONFIG_64BIT */
+	atomic_t tl_runs;
+	atomic_t outbound_tl_runs;
+	atomic_t outbound_tl_runs_resched;
+	atomic_t inbound_tl_runs;
+	atomic_t inbound_tl_runs_resched;
+	atomic_t inbound_thin_tl_runs;
+	atomic_t inbound_thin_tl_runs_resched;
+
+	atomic_t siga_outs;
+	atomic_t siga_ins;
+	atomic_t siga_syncs;
+	atomic_t pcis;
+	atomic_t thinints;
+	atomic_t fast_reqs;
+
+	atomic_t outbound_cnt;
+	atomic_t inbound_cnt;
+#endif /* CONFIG_64BIT */
 };
 
 /* unlikely as the later the better */
diff --git a/drivers/s390/net/qeth.h b/drivers/s390/net/qeth.h
index 84b108d..b34eb82 100644
--- a/drivers/s390/net/qeth.h
+++ b/drivers/s390/net/qeth.h
@@ -288,6 +288,7 @@
  */
 #define IF_NAME_LEN	 	16
 #define QETH_TX_TIMEOUT		100 * HZ
+#define QETH_RCD_TIMEOUT	60 * HZ
 #define QETH_HEADER_SIZE	32
 #define MAX_PORTNO 		15
 #define QETH_FAKE_LL_LEN_ETH	ETH_HLEN
@@ -582,6 +583,8 @@
 	CH_STATE_ACTIVATING,
 	CH_STATE_HALTED,
 	CH_STATE_STOPPED,
+	CH_STATE_RCD,
+	CH_STATE_RCD_DONE,
 };
 /**
  * card state machine
diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c
index ad7792d..6fd8870 100644
--- a/drivers/s390/net/qeth_main.c
+++ b/drivers/s390/net/qeth_main.c
@@ -315,7 +315,8 @@
 }
 
 static long
-__qeth_check_irb_error(struct ccw_device *cdev, struct irb *irb)
+__qeth_check_irb_error(struct ccw_device *cdev, unsigned long intparm,
+		       struct irb *irb)
 {
 	if (!IS_ERR(irb))
 		return 0;
@@ -330,6 +331,14 @@
 		PRINT_WARN("timeout on device %s\n", cdev->dev.bus_id);
 		QETH_DBF_TEXT(trace, 2, "ckirberr");
 		QETH_DBF_TEXT_(trace, 2, "  rc%d", -ETIMEDOUT);
+		if (intparm == QETH_RCD_PARM) {
+			struct qeth_card *card = CARD_FROM_CDEV(cdev);
+
+			if (card && (card->data.ccwdev == cdev)) {
+				card->data.state = CH_STATE_DOWN;
+				wake_up(&card->wait_q);
+			}
+		}
 		break;
 	default:
 		PRINT_WARN("unknown error %ld on device %s\n", PTR_ERR(irb),
@@ -401,7 +410,7 @@
 
 	QETH_DBF_TEXT(trace,5,"irq");
 
-	if (__qeth_check_irb_error(cdev, irb))
+	if (__qeth_check_irb_error(cdev, intparm, irb))
 		return;
 	cstat = irb->scsw.cstat;
 	dstat = irb->scsw.dstat;
@@ -429,7 +438,8 @@
 		channel->state = CH_STATE_HALTED;
 
 	/*let's wake up immediately on data channel*/
-	if ((channel == &card->data) && (intparm != 0))
+	if ((channel == &card->data) && (intparm != 0) &&
+	    (intparm != QETH_RCD_PARM))
 		goto out;
 
 	if (intparm == QETH_CLEAR_CHANNEL_PARM) {
@@ -453,6 +463,10 @@
 			HEXDUMP16(WARN,"irb: ",irb);
 			HEXDUMP16(WARN,"sense data: ",irb->ecw);
 		}
+		if (intparm == QETH_RCD_PARM) {
+			channel->state = CH_STATE_DOWN;
+			goto out;
+		}
 		rc = qeth_get_problem(cdev,irb);
 		if (rc) {
 			qeth_schedule_recovery(card);
@@ -460,6 +474,10 @@
 		}
 	}
 
+	if (intparm == QETH_RCD_PARM) {
+		channel->state = CH_STATE_RCD_DONE;
+		goto out;
+	}
 	if (intparm) {
 		buffer = (struct qeth_cmd_buffer *) __va((addr_t)intparm);
 		buffer->state = BUF_STATE_PROCESSED;
@@ -1204,6 +1222,54 @@
 }
 
 
+static int qeth_read_conf_data(struct qeth_card *card, void **buffer,
+			       int *length)
+{
+	struct ciw *ciw;
+	char *rcd_buf;
+	int ret;
+	struct qeth_channel *channel = &card->data;
+	unsigned long flags;
+
+	/*
+	 * scan for RCD command in extended SenseID data
+	 */
+	ciw = ccw_device_get_ciw(channel->ccwdev, CIW_TYPE_RCD);
+	if (!ciw || ciw->cmd == 0)
+		return -EOPNOTSUPP;
+	rcd_buf = kzalloc(ciw->count, GFP_KERNEL | GFP_DMA);
+	if (!rcd_buf)
+		return -ENOMEM;
+
+	channel->ccw.cmd_code = ciw->cmd;
+	channel->ccw.cda = (__u32) __pa (rcd_buf);
+	channel->ccw.count = ciw->count;
+	channel->ccw.flags = CCW_FLAG_SLI;
+	channel->state = CH_STATE_RCD;
+	spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
+	ret = ccw_device_start_timeout(channel->ccwdev, &channel->ccw,
+				       QETH_RCD_PARM, LPM_ANYPATH, 0,
+				       QETH_RCD_TIMEOUT);
+	spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags);
+	if (!ret)
+		wait_event(card->wait_q,
+			   (channel->state == CH_STATE_RCD_DONE ||
+			    channel->state == CH_STATE_DOWN));
+	if (channel->state == CH_STATE_DOWN)
+		ret = -EIO;
+	else
+		channel->state = CH_STATE_DOWN;
+	if (ret) {
+		kfree(rcd_buf);
+		*buffer = NULL;
+		*length = 0;
+	} else {
+		*length = ciw->count;
+		*buffer = rcd_buf;
+	}
+	return ret;
+}
+
 static int
 qeth_get_unitaddr(struct qeth_card *card)
 {
@@ -1212,9 +1278,9 @@
 	int rc;
 
 	QETH_DBF_TEXT(setup, 2, "getunit");
-	rc = read_conf_data(CARD_DDEV(card), (void **) &prcd, &length);
+	rc = qeth_read_conf_data(card, (void **) &prcd, &length);
 	if (rc) {
-		PRINT_ERR("read_conf_data for device %s returned %i\n",
+		PRINT_ERR("qeth_read_conf_data for device %s returned %i\n",
 			  CARD_DDEV_ID(card), rc);
 		return rc;
 	}
@@ -1223,6 +1289,7 @@
 	card->info.cula = prcd[63];
 	card->info.guestlan = ((prcd[0x10] == _ascebc['V']) &&
 			       (prcd[0x11] == _ascebc['M']));
+	kfree(prcd);
 	return 0;
 }
 
diff --git a/drivers/s390/net/qeth_mpc.h b/drivers/s390/net/qeth_mpc.h
index 0477c47..d74bc43d 100644
--- a/drivers/s390/net/qeth_mpc.h
+++ b/drivers/s390/net/qeth_mpc.h
@@ -37,6 +37,7 @@
 
 #define QETH_CLEAR_CHANNEL_PARM	-10
 #define QETH_HALT_CHANNEL_PARM	-11
+#define QETH_RCD_PARM -12
 
 /*****************************************************************************/
 /* IP Assist related definitions                                             */
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c
index 421da1e..c1f2d4b 100644
--- a/drivers/s390/scsi/zfcp_erp.c
+++ b/drivers/s390/scsi/zfcp_erp.c
@@ -186,7 +186,7 @@
 {
 	fsf_req->timer.function = zfcp_fsf_request_timeout_handler;
 	fsf_req->timer.data = (unsigned long) fsf_req->adapter;
-	fsf_req->timer.expires = timeout;
+	fsf_req->timer.expires = jiffies + timeout;
 	add_timer(&fsf_req->timer);
 }
 
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index ef16f7c..4c0a59a 100644
--- a/drivers/s390/scsi/zfcp_fsf.c
+++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -299,9 +299,10 @@
 	}
 
 	/* log additional information provided by FSF (if any) */
-	if (unlikely(qtcb->header.log_length)) {
+	if (likely(qtcb->header.log_length)) {
 		/* do not trust them ;-) */
-		if (qtcb->header.log_start > sizeof(struct fsf_qtcb)) {
+		if (unlikely(qtcb->header.log_start >
+			     sizeof(struct fsf_qtcb))) {
 			ZFCP_LOG_NORMAL
 			    ("bug: ULP (FSF logging) log data starts "
 			     "beyond end of packet header. Ignored. "
@@ -310,8 +311,9 @@
 			     sizeof(struct fsf_qtcb));
 			goto forget_log;
 		}
-		if ((size_t) (qtcb->header.log_start + qtcb->header.log_length)
-		    > sizeof(struct fsf_qtcb)) {
+		if (unlikely((size_t) (qtcb->header.log_start +
+				       qtcb->header.log_length) >
+			     sizeof(struct fsf_qtcb))) {
 			ZFCP_LOG_NORMAL("bug: ULP (FSF logging) log data ends "
 					"beyond end of packet header. Ignored. "
 					"(start=%i, length=%i, size=%li)\n",
diff --git a/drivers/sbus/sbus.c b/drivers/sbus/sbus.c
index eee590a..0026433 100644
--- a/drivers/sbus/sbus.c
+++ b/drivers/sbus/sbus.c
@@ -6,7 +6,6 @@
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/init.h>
-#include <linux/pci.h>
 #include <linux/device.h>
 
 #include <asm/system.h>
diff --git a/drivers/scsi/BusLogic.c b/drivers/scsi/BusLogic.c
index e874b89..96f4cab0 100644
--- a/drivers/scsi/BusLogic.c
+++ b/drivers/scsi/BusLogic.c
@@ -579,17 +579,17 @@
 	/*
 	   Append the list of standard BusLogic MultiMaster ISA I/O Addresses.
 	 */
-	if (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe330 : check_region(0x330, BusLogic_MultiMasterAddressCount) == 0)
+	if (!BusLogic_ProbeOptions.LimitedProbeISA || BusLogic_ProbeOptions.Probe330)
 		BusLogic_AppendProbeAddressISA(0x330);
-	if (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe334 : check_region(0x334, BusLogic_MultiMasterAddressCount) == 0)
+	if (!BusLogic_ProbeOptions.LimitedProbeISA || BusLogic_ProbeOptions.Probe334)
 		BusLogic_AppendProbeAddressISA(0x334);
-	if (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe230 : check_region(0x230, BusLogic_MultiMasterAddressCount) == 0)
+	if (!BusLogic_ProbeOptions.LimitedProbeISA || BusLogic_ProbeOptions.Probe230)
 		BusLogic_AppendProbeAddressISA(0x230);
-	if (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe234 : check_region(0x234, BusLogic_MultiMasterAddressCount) == 0)
+	if (!BusLogic_ProbeOptions.LimitedProbeISA || BusLogic_ProbeOptions.Probe234)
 		BusLogic_AppendProbeAddressISA(0x234);
-	if (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe130 : check_region(0x130, BusLogic_MultiMasterAddressCount) == 0)
+	if (!BusLogic_ProbeOptions.LimitedProbeISA || BusLogic_ProbeOptions.Probe130)
 		BusLogic_AppendProbeAddressISA(0x130);
-	if (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe134 : check_region(0x134, BusLogic_MultiMasterAddressCount) == 0)
+	if (!BusLogic_ProbeOptions.LimitedProbeISA || BusLogic_ProbeOptions.Probe134)
 		BusLogic_AppendProbeAddressISA(0x134);
 }
 
@@ -795,7 +795,9 @@
 	   host adapters are probed.
 	 */
 	if (!BusLogic_ProbeOptions.NoProbeISA)
-		if (PrimaryProbeInfo->IO_Address == 0 && (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe330 : check_region(0x330, BusLogic_MultiMasterAddressCount) == 0)) {
+		if (PrimaryProbeInfo->IO_Address == 0 &&
+				(!BusLogic_ProbeOptions.LimitedProbeISA ||
+				 BusLogic_ProbeOptions.Probe330)) {
 			PrimaryProbeInfo->HostAdapterType = BusLogic_MultiMaster;
 			PrimaryProbeInfo->HostAdapterBusType = BusLogic_ISA_Bus;
 			PrimaryProbeInfo->IO_Address = 0x330;
@@ -805,15 +807,25 @@
 	   omitting the Primary I/O Address which has already been handled.
 	 */
 	if (!BusLogic_ProbeOptions.NoProbeISA) {
-		if (!StandardAddressSeen[1] && (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe334 : check_region(0x334, BusLogic_MultiMasterAddressCount) == 0))
+		if (!StandardAddressSeen[1] &&
+				(!BusLogic_ProbeOptions.LimitedProbeISA ||
+				 BusLogic_ProbeOptions.Probe334))
 			BusLogic_AppendProbeAddressISA(0x334);
-		if (!StandardAddressSeen[2] && (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe230 : check_region(0x230, BusLogic_MultiMasterAddressCount) == 0))
+		if (!StandardAddressSeen[2] &&
+				(!BusLogic_ProbeOptions.LimitedProbeISA ||
+				 BusLogic_ProbeOptions.Probe230))
 			BusLogic_AppendProbeAddressISA(0x230);
-		if (!StandardAddressSeen[3] && (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe234 : check_region(0x234, BusLogic_MultiMasterAddressCount) == 0))
+		if (!StandardAddressSeen[3] &&
+				(!BusLogic_ProbeOptions.LimitedProbeISA ||
+				 BusLogic_ProbeOptions.Probe234))
 			BusLogic_AppendProbeAddressISA(0x234);
-		if (!StandardAddressSeen[4] && (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe130 : check_region(0x130, BusLogic_MultiMasterAddressCount) == 0))
+		if (!StandardAddressSeen[4] &&
+				(!BusLogic_ProbeOptions.LimitedProbeISA ||
+				 BusLogic_ProbeOptions.Probe130))
 			BusLogic_AppendProbeAddressISA(0x130);
-		if (!StandardAddressSeen[5] && (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe134 : check_region(0x134, BusLogic_MultiMasterAddressCount) == 0))
+		if (!StandardAddressSeen[5] &&
+				(!BusLogic_ProbeOptions.LimitedProbeISA ||
+				 BusLogic_ProbeOptions.Probe134))
 			BusLogic_AppendProbeAddressISA(0x134);
 	}
 	/*
@@ -2220,22 +2232,35 @@
 		HostAdapter->PCI_Device = ProbeInfo->PCI_Device;
 		HostAdapter->IRQ_Channel = ProbeInfo->IRQ_Channel;
 		HostAdapter->AddressCount = BusLogic_HostAdapterAddressCount[HostAdapter->HostAdapterType];
+
+		/*
+		   Make sure region is free prior to probing.
+		 */
+		if (!request_region(HostAdapter->IO_Address, HostAdapter->AddressCount,
+					"BusLogic"))
+			continue;
 		/*
 		   Probe the Host Adapter.  If unsuccessful, abort further initialization.
 		 */
-		if (!BusLogic_ProbeHostAdapter(HostAdapter))
+		if (!BusLogic_ProbeHostAdapter(HostAdapter)) {
+			release_region(HostAdapter->IO_Address, HostAdapter->AddressCount);
 			continue;
+		}
 		/*
 		   Hard Reset the Host Adapter.  If unsuccessful, abort further
 		   initialization.
 		 */
-		if (!BusLogic_HardwareResetHostAdapter(HostAdapter, true))
+		if (!BusLogic_HardwareResetHostAdapter(HostAdapter, true)) {
+			release_region(HostAdapter->IO_Address, HostAdapter->AddressCount);
 			continue;
+		}
 		/*
 		   Check the Host Adapter.  If unsuccessful, abort further initialization.
 		 */
-		if (!BusLogic_CheckHostAdapter(HostAdapter))
+		if (!BusLogic_CheckHostAdapter(HostAdapter)) {
+			release_region(HostAdapter->IO_Address, HostAdapter->AddressCount);
 			continue;
+		}
 		/*
 		   Initialize the Driver Options field if provided.
 		 */
@@ -2247,16 +2272,6 @@
 		 */
 		BusLogic_AnnounceDriver(HostAdapter);
 		/*
-		   Register usage of the I/O Address range.  From this point onward, any
-		   failure will be assumed to be due to a problem with the Host Adapter,
-		   rather than due to having mistakenly identified this port as belonging
-		   to a BusLogic Host Adapter.  The I/O Address range will not be
-		   released, thereby preventing it from being incorrectly identified as
-		   any other type of Host Adapter.
-		 */
-		if (!request_region(HostAdapter->IO_Address, HostAdapter->AddressCount, "BusLogic"))
-			continue;
-		/*
 		   Register the SCSI Host structure.
 		 */
 
@@ -2280,6 +2295,12 @@
 		   Acquire the System Resources necessary to use the Host Adapter, then
 		   Create the Initial CCBs, Initialize the Host Adapter, and finally
 		   perform Target Device Inquiry.
+
+		   From this point onward, any failure will be assumed to be due to a
+		   problem with the Host Adapter, rather than due to having mistakenly
+		   identified this port as belonging to a BusLogic Host Adapter.  The
+		   I/O Address range will not be released, thereby preventing it from
+		   being incorrectly identified as any other type of Host Adapter.
 		 */
 		if (BusLogic_ReadHostAdapterConfiguration(HostAdapter) &&
 		    BusLogic_ReportHostAdapterConfiguration(HostAdapter) &&
@@ -3598,6 +3619,7 @@
 
 __setup("BusLogic=", BusLogic_Setup);
 
+#ifdef MODULE
 static struct pci_device_id BusLogic_pci_tbl[] __devinitdata = {
 	{ PCI_VENDOR_ID_BUSLOGIC, PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER,
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
@@ -3607,6 +3629,7 @@
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
 	{ }
 };
+#endif
 MODULE_DEVICE_TABLE(pci, BusLogic_pci_tbl);
 
 module_init(BusLogic_init);
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index fcc4cb6..58c811d2 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -241,6 +241,12 @@
 	  You can override this choice by specifying "scsi_mod.scan=sync"
 	  or async on the kernel's command line.
 
+config SCSI_WAIT_SCAN
+	tristate
+	default m
+	depends on SCSI
+	depends on MODULES
+
 menu "SCSI Transports"
 	depends on SCSI
 
@@ -1194,17 +1200,6 @@
 	  There is no safe option other than using good cabling, right
 	  terminations and SCSI conformant devices.
 
-config SCSI_NCR53C8XX_PROFILE
-	bool "enable profiling"
-	depends on SCSI_ZALON || SCSI_NCR_Q720
-	help
-	  This option allows you to enable profiling information gathering.
-	  These statistics are not very accurate due to the low frequency
-	  of the kernel clock (100 Hz on i386) and have performance impact
-	  on systems that use very fast devices.
-
-	  The normal answer therefore is N.
-
 config SCSI_NCR53C8XX_NO_DISCONNECT
 	bool "not allow targets to disconnect"
 	depends on (SCSI_ZALON || SCSI_NCR_Q720) && SCSI_NCR53C8XX_DEFAULT_TAGS=0
@@ -1334,11 +1329,6 @@
 
 	  It currently supports Compaq EISA cards and NCR MCA cards
 
-config 53C700_IO_MAPPED
-	bool
-	depends on SCSI_SIM710
-	default y
-
 config SCSI_SYM53C416
 	tristate "Symbios 53c416 SCSI support"
 	depends on ISA && SCSI
@@ -1649,7 +1639,7 @@
 
 config ATARI_SCSI
 	tristate "Atari native SCSI support"
-	depends on ATARI && SCSI && BROKEN
+	depends on ATARI && SCSI
 	select SCSI_SPI_ATTRS
 	---help---
 	  If you have an Atari with built-in NCR5380 SCSI controller (TT,
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 70cff4c..51e884f 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -146,7 +146,7 @@
 # This goes last, so that "real" scsi devices probe earlier
 obj-$(CONFIG_SCSI_DEBUG)	+= scsi_debug.o
 
-obj-$(CONFIG_SCSI)		+= scsi_wait_scan.o
+obj-$(CONFIG_SCSI_WAIT_SCAN)	+= scsi_wait_scan.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/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c
index d789e61..1e82c69 100644
--- a/drivers/scsi/aacraid/aachba.c
+++ b/drivers/scsi/aacraid/aachba.c
@@ -5,7 +5,7 @@
  * based on the old aacraid driver that is..
  * Adaptec aacraid device driver for Linux.
  *
- * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
+ * Copyright (c) 2000-2007 Adaptec, Inc. (aacraid@adaptec.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
@@ -172,6 +172,30 @@
 int expose_physicals = -1;
 module_param(expose_physicals, int, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(expose_physicals, "Expose physical components of the arrays. -1=protect 0=off, 1=on");
+
+
+static inline int aac_valid_context(struct scsi_cmnd *scsicmd,
+		struct fib *fibptr) {
+	struct scsi_device *device;
+
+	if (unlikely(!scsicmd || !scsicmd->scsi_done )) {
+		dprintk((KERN_WARNING "aac_valid_context: scsi command corrupt\n"))
+;
+                aac_fib_complete(fibptr);
+                aac_fib_free(fibptr);
+                return 0;
+        }
+	scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL;
+	device = scsicmd->device;
+	if (unlikely(!device || !scsi_device_online(device))) {
+		dprintk((KERN_WARNING "aac_valid_context: scsi device corrupt\n"));
+		aac_fib_complete(fibptr);
+		aac_fib_free(fibptr);
+		return 0;
+	}
+	return 1;
+}
+
 /**
  *	aac_get_config_status	-	check the adapter configuration
  *	@common: adapter to query
@@ -258,13 +282,10 @@
 	u32 index; 
 	int status = 0;
 	struct fib * fibptr;
-	unsigned instance;
 	struct aac_get_container_count *dinfo;
 	struct aac_get_container_count_resp *dresp;
 	int maximum_num_containers = MAXIMUM_NUM_CONTAINERS;
 
-	instance = dev->scsi_host_ptr->unique_id;
-
 	if (!(fibptr = aac_fib_alloc(dev)))
 		return -ENOMEM;
 
@@ -284,88 +305,35 @@
 		maximum_num_containers = le32_to_cpu(dresp->ContainerSwitchEntries);
 		aac_fib_complete(fibptr);
 	}
+	aac_fib_free(fibptr);
 
 	if (maximum_num_containers < MAXIMUM_NUM_CONTAINERS)
 		maximum_num_containers = MAXIMUM_NUM_CONTAINERS;
-	fsa_dev_ptr = kmalloc(
-	  sizeof(*fsa_dev_ptr) * maximum_num_containers, GFP_KERNEL);
-	if (!fsa_dev_ptr) {
-		aac_fib_free(fibptr);
+	fsa_dev_ptr =  kmalloc(sizeof(*fsa_dev_ptr) * maximum_num_containers,
+			GFP_KERNEL);
+	if (!fsa_dev_ptr)
 		return -ENOMEM;
-	}
 	memset(fsa_dev_ptr, 0, sizeof(*fsa_dev_ptr) * maximum_num_containers);
 
 	dev->fsa_dev = fsa_dev_ptr;
 	dev->maximum_num_containers = maximum_num_containers;
 
-	for (index = 0; index < dev->maximum_num_containers; index++) {
-		struct aac_query_mount *dinfo;
-		struct aac_mount *dresp;
-
+	for (index = 0; index < dev->maximum_num_containers; ) {
 		fsa_dev_ptr[index].devname[0] = '\0';
 
-		aac_fib_init(fibptr);
-		dinfo = (struct aac_query_mount *) fib_data(fibptr);
+		status = aac_probe_container(dev, index);
 
-		dinfo->command = cpu_to_le32(VM_NameServe);
-		dinfo->count = cpu_to_le32(index);
-		dinfo->type = cpu_to_le32(FT_FILESYS);
-
-		status = aac_fib_send(ContainerCommand,
-				    fibptr,
-				    sizeof (struct aac_query_mount),
-				    FsaNormal,
-				    1, 1,
-				    NULL, NULL);
-		if (status < 0 ) {
+		if (status < 0) {
 			printk(KERN_WARNING "aac_get_containers: SendFIB failed.\n");
 			break;
 		}
-		dresp = (struct aac_mount *)fib_data(fibptr);
 
-		if ((le32_to_cpu(dresp->status) == ST_OK) &&
-		    (le32_to_cpu(dresp->mnt[0].vol) == CT_NONE)) {
-			dinfo->command = cpu_to_le32(VM_NameServe64);
-			dinfo->count = cpu_to_le32(index);
-			dinfo->type = cpu_to_le32(FT_FILESYS);
-
-			if (aac_fib_send(ContainerCommand,
-				    fibptr,
-				    sizeof(struct aac_query_mount),
-				    FsaNormal,
-				    1, 1,
-				    NULL, NULL) < 0)
-				continue;
-		} else
-			dresp->mnt[0].capacityhigh = 0;
-
-		dprintk ((KERN_DEBUG
-		  "VM_NameServe cid=%d status=%d vol=%d state=%d cap=%llu\n",
-		  (int)index, (int)le32_to_cpu(dresp->status),
-		  (int)le32_to_cpu(dresp->mnt[0].vol),
-		  (int)le32_to_cpu(dresp->mnt[0].state),
-		  ((u64)le32_to_cpu(dresp->mnt[0].capacity)) +
-		    (((u64)le32_to_cpu(dresp->mnt[0].capacityhigh)) << 32)));
-		if ((le32_to_cpu(dresp->status) == ST_OK) &&
-		    (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE) &&
-		    (le32_to_cpu(dresp->mnt[0].state) != FSCS_HIDDEN)) {
-			fsa_dev_ptr[index].valid = 1;
-			fsa_dev_ptr[index].type = le32_to_cpu(dresp->mnt[0].vol);
-			fsa_dev_ptr[index].size
-			  = ((u64)le32_to_cpu(dresp->mnt[0].capacity)) +
-			    (((u64)le32_to_cpu(dresp->mnt[0].capacityhigh)) << 32);
-			if (le32_to_cpu(dresp->mnt[0].state) & FSCS_READONLY)
-				    fsa_dev_ptr[index].ro = 1;
-		}
-		aac_fib_complete(fibptr);
 		/*
 		 *	If there are no more containers, then stop asking.
 		 */
-		if ((index + 1) >= le32_to_cpu(dresp->count)){
+		if (++index >= status)
 			break;
-		}
 	}
-	aac_fib_free(fibptr);
 	return status;
 }
 
@@ -382,8 +350,9 @@
 		buf = scsicmd->request_buffer;
 		transfer_len = min(scsicmd->request_bufflen, len + offset);
 	}
-
-	memcpy(buf + offset, data, transfer_len - offset);
+	transfer_len -= offset;
+	if (buf && transfer_len)
+		memcpy(buf + offset, data, transfer_len);
 
 	if (scsicmd->use_sg) 
 		kunmap_atomic(buf - sg->offset, KM_IRQ0);
@@ -396,7 +365,9 @@
 	struct scsi_cmnd * scsicmd;
 
 	scsicmd = (struct scsi_cmnd *) context;
-	scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL;
+
+	if (!aac_valid_context(scsicmd, fibptr))
+		return;
 
 	dprintk((KERN_DEBUG "get_container_name_callback[cpu %d]: t = %ld.\n", smp_processor_id(), jiffies));
 	BUG_ON(fibptr == NULL);
@@ -431,7 +402,7 @@
 /**
  *	aac_get_container_name	-	get container name, none blocking.
  */
-static int aac_get_container_name(struct scsi_cmnd * scsicmd, int cid)
+static int aac_get_container_name(struct scsi_cmnd * scsicmd)
 {
 	int status;
 	struct aac_get_name *dinfo;
@@ -448,7 +419,7 @@
 
 	dinfo->command = cpu_to_le32(VM_ContainerConfig);
 	dinfo->type = cpu_to_le32(CT_READ_NAME);
-	dinfo->cid = cpu_to_le32(cid);
+	dinfo->cid = cpu_to_le32(scmd_id(scsicmd));
 	dinfo->count = cpu_to_le32(sizeof(((struct aac_get_name_resp *)NULL)->data));
 
 	status = aac_fib_send(ContainerCommand,
@@ -473,6 +444,153 @@
 	return -1;
 }
 
+static int aac_probe_container_callback2(struct scsi_cmnd * scsicmd)
+{
+	struct fsa_dev_info *fsa_dev_ptr = ((struct aac_dev *)(scsicmd->device->host->hostdata))->fsa_dev;
+
+	if (fsa_dev_ptr[scmd_id(scsicmd)].valid)
+		return aac_scsi_cmd(scsicmd);
+
+	scsicmd->result = DID_NO_CONNECT << 16;
+	scsicmd->scsi_done(scsicmd);
+	return 0;
+}
+
+static int _aac_probe_container2(void * context, struct fib * fibptr)
+{
+	struct fsa_dev_info *fsa_dev_ptr;
+	int (*callback)(struct scsi_cmnd *);
+	struct scsi_cmnd * scsicmd = (struct scsi_cmnd *)context;
+
+	if (!aac_valid_context(scsicmd, fibptr))
+		return 0;
+
+	fsa_dev_ptr = ((struct aac_dev *)(scsicmd->device->host->hostdata))->fsa_dev;
+
+	scsicmd->SCp.Status = 0;
+	if (fsa_dev_ptr) {
+		struct aac_mount * dresp = (struct aac_mount *) fib_data(fibptr);
+		fsa_dev_ptr += scmd_id(scsicmd);
+
+		if ((le32_to_cpu(dresp->status) == ST_OK) &&
+		    (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE) &&
+		    (le32_to_cpu(dresp->mnt[0].state) != FSCS_HIDDEN)) {
+			fsa_dev_ptr->valid = 1;
+			fsa_dev_ptr->type = le32_to_cpu(dresp->mnt[0].vol);
+			fsa_dev_ptr->size
+			  = ((u64)le32_to_cpu(dresp->mnt[0].capacity)) +
+			    (((u64)le32_to_cpu(dresp->mnt[0].capacityhigh)) << 32);
+			fsa_dev_ptr->ro = ((le32_to_cpu(dresp->mnt[0].state) & FSCS_READONLY) != 0);
+		}
+		if ((fsa_dev_ptr->valid & 1) == 0)
+			fsa_dev_ptr->valid = 0;
+		scsicmd->SCp.Status = le32_to_cpu(dresp->count);
+	}
+	aac_fib_complete(fibptr);
+	aac_fib_free(fibptr);
+	callback = (int (*)(struct scsi_cmnd *))(scsicmd->SCp.ptr);
+	scsicmd->SCp.ptr = NULL;
+	return (*callback)(scsicmd);
+}
+
+static int _aac_probe_container1(void * context, struct fib * fibptr)
+{
+	struct scsi_cmnd * scsicmd;
+	struct aac_mount * dresp;
+	struct aac_query_mount *dinfo;
+	int status;
+
+	dresp = (struct aac_mount *) fib_data(fibptr);
+	dresp->mnt[0].capacityhigh = 0;
+	if ((le32_to_cpu(dresp->status) != ST_OK) ||
+	    (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE))
+		return _aac_probe_container2(context, fibptr);
+	scsicmd = (struct scsi_cmnd *) context;
+	scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL;
+
+	if (!aac_valid_context(scsicmd, fibptr))
+		return 0;
+
+	aac_fib_init(fibptr);
+
+	dinfo = (struct aac_query_mount *)fib_data(fibptr);
+
+	dinfo->command = cpu_to_le32(VM_NameServe64);
+	dinfo->count = cpu_to_le32(scmd_id(scsicmd));
+	dinfo->type = cpu_to_le32(FT_FILESYS);
+
+	status = aac_fib_send(ContainerCommand,
+			  fibptr,
+			  sizeof(struct aac_query_mount),
+			  FsaNormal,
+			  0, 1,
+			  (fib_callback) _aac_probe_container2,
+			  (void *) scsicmd);
+	/*
+	 *	Check that the command queued to the controller
+	 */
+	if (status == -EINPROGRESS) {
+		scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
+		return 0;
+	}
+	if (status < 0) {
+		/* Inherit results from VM_NameServe, if any */
+		dresp->status = cpu_to_le32(ST_OK);
+		return _aac_probe_container2(context, fibptr);
+	}
+	return 0;
+}
+
+static int _aac_probe_container(struct scsi_cmnd * scsicmd, int (*callback)(struct scsi_cmnd *))
+{
+	struct fib * fibptr;
+	int status = -ENOMEM;
+
+	if ((fibptr = aac_fib_alloc((struct aac_dev *)scsicmd->device->host->hostdata))) {
+		struct aac_query_mount *dinfo;
+
+		aac_fib_init(fibptr);
+
+		dinfo = (struct aac_query_mount *)fib_data(fibptr);
+
+		dinfo->command = cpu_to_le32(VM_NameServe);
+		dinfo->count = cpu_to_le32(scmd_id(scsicmd));
+		dinfo->type = cpu_to_le32(FT_FILESYS);
+		scsicmd->SCp.ptr = (char *)callback;
+
+		status = aac_fib_send(ContainerCommand,
+			  fibptr,
+			  sizeof(struct aac_query_mount),
+			  FsaNormal,
+			  0, 1,
+			  (fib_callback) _aac_probe_container1,
+			  (void *) scsicmd);
+		/*
+		 *	Check that the command queued to the controller
+		 */
+		if (status == -EINPROGRESS) {
+			scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
+			return 0;
+		}
+		if (status < 0) {
+			scsicmd->SCp.ptr = NULL;
+			aac_fib_complete(fibptr);
+			aac_fib_free(fibptr);
+		}
+	}
+	if (status < 0) {
+		struct fsa_dev_info *fsa_dev_ptr = ((struct aac_dev *)(scsicmd->device->host->hostdata))->fsa_dev;
+		if (fsa_dev_ptr) {
+			fsa_dev_ptr += scmd_id(scsicmd);
+			if ((fsa_dev_ptr->valid & 1) == 0) {
+				fsa_dev_ptr->valid = 0;
+				return (*callback)(scsicmd);
+			}
+		}
+	}
+	return status;
+}
+
 /**
  *	aac_probe_container		-	query a logical volume
  *	@dev: device to query
@@ -481,77 +599,37 @@
  *	Queries the controller about the given volume. The volume information
  *	is updated in the struct fsa_dev_info structure rather than returned.
  */
- 
+static int aac_probe_container_callback1(struct scsi_cmnd * scsicmd)
+{
+	scsicmd->device = NULL;
+	return 0;
+}
+
 int aac_probe_container(struct aac_dev *dev, int cid)
 {
-	struct fsa_dev_info *fsa_dev_ptr;
+	struct scsi_cmnd *scsicmd = kmalloc(sizeof(*scsicmd), GFP_KERNEL);
+	struct scsi_device *scsidev = kmalloc(sizeof(*scsidev), GFP_KERNEL);
 	int status;
-	struct aac_query_mount *dinfo;
-	struct aac_mount *dresp;
-	struct fib * fibptr;
-	unsigned instance;
 
-	fsa_dev_ptr = dev->fsa_dev;
-	if (!fsa_dev_ptr)
+	if (!scsicmd || !scsidev) {
+		kfree(scsicmd);
+		kfree(scsidev);
 		return -ENOMEM;
-	instance = dev->scsi_host_ptr->unique_id;
-
-	if (!(fibptr = aac_fib_alloc(dev)))
-		return -ENOMEM;
-
-	aac_fib_init(fibptr);
-
-	dinfo = (struct aac_query_mount *)fib_data(fibptr);
-
-	dinfo->command = cpu_to_le32(VM_NameServe);
-	dinfo->count = cpu_to_le32(cid);
-	dinfo->type = cpu_to_le32(FT_FILESYS);
-
-	status = aac_fib_send(ContainerCommand,
-			    fibptr,
-			    sizeof(struct aac_query_mount),
-			    FsaNormal,
-			    1, 1,
-			    NULL, NULL);
-	if (status < 0) {
-		printk(KERN_WARNING "aacraid: aac_probe_container query failed.\n");
-		goto error;
 	}
+	scsicmd->list.next = NULL;
+	scsicmd->scsi_done = (void (*)(struct scsi_cmnd*))_aac_probe_container1;
 
-	dresp = (struct aac_mount *) fib_data(fibptr);
+	scsicmd->device = scsidev;
+	scsidev->sdev_state = 0;
+	scsidev->id = cid;
+	scsidev->host = dev->scsi_host_ptr;
 
-	if ((le32_to_cpu(dresp->status) == ST_OK) &&
-	    (le32_to_cpu(dresp->mnt[0].vol) == CT_NONE)) {
-		dinfo->command = cpu_to_le32(VM_NameServe64);
-		dinfo->count = cpu_to_le32(cid);
-		dinfo->type = cpu_to_le32(FT_FILESYS);
-
-		if (aac_fib_send(ContainerCommand,
-			    fibptr,
-			    sizeof(struct aac_query_mount),
-			    FsaNormal,
-			    1, 1,
-			    NULL, NULL) < 0)
-			goto error;
-	} else
-		dresp->mnt[0].capacityhigh = 0;
-
-	if ((le32_to_cpu(dresp->status) == ST_OK) &&
-	    (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE) &&
-	    (le32_to_cpu(dresp->mnt[0].state) != FSCS_HIDDEN)) {
-		fsa_dev_ptr[cid].valid = 1;
-		fsa_dev_ptr[cid].type = le32_to_cpu(dresp->mnt[0].vol);
-		fsa_dev_ptr[cid].size
-		  = ((u64)le32_to_cpu(dresp->mnt[0].capacity)) +
-		    (((u64)le32_to_cpu(dresp->mnt[0].capacityhigh)) << 32);
-		if (le32_to_cpu(dresp->mnt[0].state) & FSCS_READONLY)
-			fsa_dev_ptr[cid].ro = 1;
-	}
-
-error:
-	aac_fib_complete(fibptr);
-	aac_fib_free(fibptr);
-
+	if (_aac_probe_container(scsicmd, aac_probe_container_callback1) == 0)
+		while (scsicmd->device == scsidev)
+			schedule();
+	kfree(scsidev);
+	status = scsicmd->SCp.Status;
+	kfree(scsicmd);
 	return status;
 }
 
@@ -1115,6 +1193,12 @@
 			printk(KERN_INFO "%s%d: serial %x\n",
 				dev->name, dev->id,
 				le32_to_cpu(dev->adapter_info.serial[0]));
+		if (dev->supplement_adapter_info.VpdInfo.Tsid[0]) {
+			printk(KERN_INFO "%s%d: TSID %.*s\n",
+			  dev->name, dev->id,
+			  (int)sizeof(dev->supplement_adapter_info.VpdInfo.Tsid),
+			  dev->supplement_adapter_info.VpdInfo.Tsid);
+		}
 	}
 
 	dev->nondasd_support = 0;
@@ -1241,7 +1325,9 @@
 	u32 cid;
 
 	scsicmd = (struct scsi_cmnd *) context;
-	scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL;
+
+	if (!aac_valid_context(scsicmd, fibptr))
+		return;
 
 	dev = (struct aac_dev *)scsicmd->device->host->hostdata;
 	cid = scmd_id(scsicmd);
@@ -1317,7 +1403,7 @@
 	scsicmd->scsi_done(scsicmd);
 }
 
-static int aac_read(struct scsi_cmnd * scsicmd, int cid)
+static int aac_read(struct scsi_cmnd * scsicmd)
 {
 	u64 lba;
 	u32 count;
@@ -1331,7 +1417,7 @@
 	 */
 	switch (scsicmd->cmnd[0]) {
 	case READ_6:
-		dprintk((KERN_DEBUG "aachba: received a read(6) command on id %d.\n", cid));
+		dprintk((KERN_DEBUG "aachba: received a read(6) command on id %d.\n", scmd_id(scsicmd)));
 
 		lba = ((scsicmd->cmnd[1] & 0x1F) << 16) | 
 			(scsicmd->cmnd[2] << 8) | scsicmd->cmnd[3];
@@ -1341,7 +1427,7 @@
 			count = 256;
 		break;
 	case READ_16:
-		dprintk((KERN_DEBUG "aachba: received a read(16) command on id %d.\n", cid));
+		dprintk((KERN_DEBUG "aachba: received a read(16) command on id %d.\n", scmd_id(scsicmd)));
 
 		lba = 	((u64)scsicmd->cmnd[2] << 56) |
 		 	((u64)scsicmd->cmnd[3] << 48) |
@@ -1355,7 +1441,7 @@
 			(scsicmd->cmnd[12] << 8) | scsicmd->cmnd[13];
 		break;
 	case READ_12:
-		dprintk((KERN_DEBUG "aachba: received a read(12) command on id %d.\n", cid));
+		dprintk((KERN_DEBUG "aachba: received a read(12) command on id %d.\n", scmd_id(scsicmd)));
 
 		lba = ((u64)scsicmd->cmnd[2] << 24) | 
 			(scsicmd->cmnd[3] << 16) |
@@ -1365,7 +1451,7 @@
 		      	(scsicmd->cmnd[8] << 8) | scsicmd->cmnd[9];
 		break;
 	default:
-		dprintk((KERN_DEBUG "aachba: received a read(10) command on id %d.\n", cid));
+		dprintk((KERN_DEBUG "aachba: received a read(10) command on id %d.\n", scmd_id(scsicmd)));
 
 		lba = ((u64)scsicmd->cmnd[2] << 24) | 
 			(scsicmd->cmnd[3] << 16) | 
@@ -1405,7 +1491,7 @@
 	return 0;
 }
 
-static int aac_write(struct scsi_cmnd * scsicmd, int cid)
+static int aac_write(struct scsi_cmnd * scsicmd)
 {
 	u64 lba;
 	u32 count;
@@ -1424,7 +1510,7 @@
 		if (count == 0)
 			count = 256;
 	} else if (scsicmd->cmnd[0] == WRITE_16) { /* 16 byte command */
-		dprintk((KERN_DEBUG "aachba: received a write(16) command on id %d.\n", cid));
+		dprintk((KERN_DEBUG "aachba: received a write(16) command on id %d.\n", scmd_id(scsicmd)));
 
 		lba = 	((u64)scsicmd->cmnd[2] << 56) |
 			((u64)scsicmd->cmnd[3] << 48) |
@@ -1436,14 +1522,14 @@
 		count = (scsicmd->cmnd[10] << 24) | (scsicmd->cmnd[11] << 16) |
 			(scsicmd->cmnd[12] << 8) | scsicmd->cmnd[13];
 	} else if (scsicmd->cmnd[0] == WRITE_12) { /* 12 byte command */
-		dprintk((KERN_DEBUG "aachba: received a write(12) command on id %d.\n", cid));
+		dprintk((KERN_DEBUG "aachba: received a write(12) command on id %d.\n", scmd_id(scsicmd)));
 
 		lba = ((u64)scsicmd->cmnd[2] << 24) | (scsicmd->cmnd[3] << 16)
 		    | (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5];
 		count = (scsicmd->cmnd[6] << 24) | (scsicmd->cmnd[7] << 16)
 		      | (scsicmd->cmnd[8] << 8) | scsicmd->cmnd[9];
 	} else {
-		dprintk((KERN_DEBUG "aachba: received a write(10) command on id %d.\n", cid));
+		dprintk((KERN_DEBUG "aachba: received a write(10) command on id %d.\n", scmd_id(scsicmd)));
 		lba = ((u64)scsicmd->cmnd[2] << 24) | (scsicmd->cmnd[3] << 16) | (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5];
 		count = (scsicmd->cmnd[7] << 8) | scsicmd->cmnd[8];
 	}
@@ -1488,7 +1574,9 @@
 	struct scsi_cmnd *cmd;
 
 	cmd = context;
-	cmd->SCp.phase = AAC_OWNER_MIDLEVEL;
+
+	if (!aac_valid_context(cmd, fibptr))
+		return;
 
 	dprintk((KERN_DEBUG "synchronize_callback[cpu %d]: t = %ld.\n", 
 				smp_processor_id(), jiffies));
@@ -1523,7 +1611,7 @@
 	cmd->scsi_done(cmd);
 }
 
-static int aac_synchronize(struct scsi_cmnd *scsicmd, int cid)
+static int aac_synchronize(struct scsi_cmnd *scsicmd)
 {
 	int status;
 	struct fib *cmd_fibcontext;
@@ -1568,7 +1656,7 @@
 	synchronizecmd = fib_data(cmd_fibcontext);
 	synchronizecmd->command = cpu_to_le32(VM_ContainerConfig);
 	synchronizecmd->type = cpu_to_le32(CT_FLUSH_CACHE);
-	synchronizecmd->cid = cpu_to_le32(cid);
+	synchronizecmd->cid = cpu_to_le32(scmd_id(scsicmd));
 	synchronizecmd->count = 
 	     cpu_to_le32(sizeof(((struct aac_synchronize_reply *)NULL)->data));
 
@@ -1646,29 +1734,12 @@
 				case TEST_UNIT_READY:
 					if (dev->in_reset)
 						return -1;
-					spin_unlock_irq(host->host_lock);
-					aac_probe_container(dev, cid);
-					if ((fsa_dev_ptr[cid].valid & 1) == 0)
-						fsa_dev_ptr[cid].valid = 0;
-					spin_lock_irq(host->host_lock);
-					if (fsa_dev_ptr[cid].valid == 0) {
-						scsicmd->result = DID_NO_CONNECT << 16;
-						scsicmd->scsi_done(scsicmd);
-						return 0;
-					}
+					return _aac_probe_container(scsicmd,
+							aac_probe_container_callback2);
 				default:
 					break;
 				}
 			}
-			/*
-			 *	If the target container still doesn't exist, 
-			 *	return failure
-			 */
-			if (fsa_dev_ptr[cid].valid == 0) {
-				scsicmd->result = DID_BAD_TARGET << 16;
-				scsicmd->scsi_done(scsicmd);
-				return 0;
-			}
 		} else {  /* check for physical non-dasd devices */
 			if ((dev->nondasd_support == 1) || expose_physicals) {
 				if (dev->in_reset)
@@ -1733,7 +1804,7 @@
 		setinqstr(dev, (void *) (inq_data.inqd_vid), fsa_dev_ptr[cid].type);
 		inq_data.inqd_pdt = INQD_PDT_DA;	/* Direct/random access device */
 		aac_internal_transfer(scsicmd, &inq_data, 0, sizeof(inq_data));
-		return aac_get_container_name(scsicmd, cid);
+		return aac_get_container_name(scsicmd);
 	}
 	case SERVICE_ACTION_IN:
 		if (!(dev->raw_io_interface) ||
@@ -1899,7 +1970,7 @@
 			  	min(sizeof(fsa_dev_ptr[cid].devname),
 				sizeof(scsicmd->request->rq_disk->disk_name) + 1));
 
-			return aac_read(scsicmd, cid);
+			return aac_read(scsicmd);
 
 		case WRITE_6:
 		case WRITE_10:
@@ -1907,11 +1978,11 @@
 		case WRITE_16:
 			if (dev->in_reset)
 				return -1;
-			return aac_write(scsicmd, cid);
+			return aac_write(scsicmd);
 
 		case SYNCHRONIZE_CACHE:
 			/* Issue FIB to tell Firmware to flush it's cache */
-			return aac_synchronize(scsicmd, cid);
+			return aac_synchronize(scsicmd);
 			
 		default:
 			/*
@@ -2058,7 +2129,10 @@
 	struct scsi_cmnd *scsicmd;
 
 	scsicmd = (struct scsi_cmnd *) context;
-	scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL;
+
+	if (!aac_valid_context(scsicmd, fibptr))
+		return;
+
 	dev = (struct aac_dev *)scsicmd->device->host->hostdata;
 
 	BUG_ON(fibptr == NULL);
diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h
index 39ecd0d..45ca3e8 100644
--- a/drivers/scsi/aacraid/aacraid.h
+++ b/drivers/scsi/aacraid/aacraid.h
@@ -12,8 +12,8 @@
  *----------------------------------------------------------------------------*/
 
 #ifndef AAC_DRIVER_BUILD
-# define AAC_DRIVER_BUILD 2423
-# define AAC_DRIVER_BRANCH "-mh3"
+# define AAC_DRIVER_BUILD 2437
+# define AAC_DRIVER_BRANCH "-mh4"
 #endif
 #define MAXIMUM_NUM_CONTAINERS	32
 
@@ -48,49 +48,13 @@
 
 
 /*
- *	DON'T CHANGE THE ORDER, this is set by the firmware
+ *	Firmware constants
  */
  
 #define		CT_NONE			0
-#define		CT_VOLUME		1
-#define		CT_MIRROR		2
-#define		CT_STRIPE		3
-#define		CT_RAID5		4
-#define		CT_SSRW			5
-#define		CT_SSRO			6
-#define		CT_MORPH		7
-#define		CT_PASSTHRU		8
-#define		CT_RAID4		9
-#define		CT_RAID10		10	/* stripe of mirror */
-#define		CT_RAID00		11	/* stripe of stripe */
-#define		CT_VOLUME_OF_MIRRORS	12	/* volume of mirror */
-#define		CT_PSEUDO_RAID		13	/* really raid4 */
-#define		CT_LAST_VOLUME_TYPE	14
 #define 	CT_OK        		218
-
-/*
- *	Types of objects addressable in some fashion by the client.
- *	This is a superset of those objects handled just by the filesystem
- *	and includes "raw" objects that an administrator would use to
- *	configure containers and filesystems.
- */
-
-#define		FT_REG		1	/* regular file */
-#define		FT_DIR		2	/* directory */
-#define		FT_BLK		3	/* "block" device - reserved */
-#define		FT_CHR		4	/* "character special" device - reserved */
-#define		FT_LNK		5	/* symbolic link */
-#define		FT_SOCK		6	/* socket */
-#define		FT_FIFO		7	/* fifo */
 #define		FT_FILESYS	8	/* ADAPTEC's "FSA"(tm) filesystem */
 #define		FT_DRIVE	9	/* physical disk - addressable in scsi by bus/id/lun */
-#define		FT_SLICE	10	/* virtual disk - raw volume - slice */
-#define		FT_PARTITION	11	/* FSA partition - carved out of a slice - building block for containers */
-#define		FT_VOLUME	12	/* Container - Volume Set */
-#define		FT_STRIPE	13	/* Container - Stripe Set */
-#define		FT_MIRROR	14	/* Container - Mirror Set */
-#define		FT_RAID5	15	/* Container - Raid 5 Set */
-#define		FT_DATABASE	16	/* Storage object with "foreign" content manager */
 
 /*
  *	Host side memory scatter gather list
@@ -497,6 +461,7 @@
 	void (*adapter_enable_int)(struct aac_dev *dev);
 	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);
+	int  (*adapter_restart)(struct aac_dev *dev, int bled);
 	/* Transport operations */
 	int  (*adapter_ioremap)(struct aac_dev * dev, u32 size);
 	irqreturn_t (*adapter_intr)(int irq, void *dev_id);
@@ -833,7 +798,7 @@
 	 */
 	struct list_head	fiblink;
 	void 			*data;
-	struct hw_fib		*hw_fib;		/* Actual shared object */
+	struct hw_fib		*hw_fib_va;		/* Actual shared object */
 	dma_addr_t		hw_fib_pa;		/* physical address of hw_fib*/
 };
 
@@ -878,10 +843,25 @@
 	__le32	Version;
 	__le32	FeatureBits;
 	u8	SlotNumber;
-	u8	ReservedPad0[0];
+	u8	ReservedPad0[3];
 	u8	BuildDate[12];
 	__le32	CurrentNumberPorts;
-	__le32	ReservedGrowth[24];
+	struct {
+		u8	AssemblyPn[8];
+		u8	FruPn[8];
+		u8	BatteryFruPn[8];
+		u8	EcVersionString[8];
+		u8	Tsid[12];
+	}	VpdInfo;
+	__le32	FlashFirmwareRevision;
+	__le32	FlashFirmwareBuild;
+	__le32	RaidTypeMorphOptions;
+	__le32	FlashFirmwareBootRevision;
+	__le32	FlashFirmwareBootBuild;
+	u8	MfgPcbaSerialNo[12];
+	u8	MfgWWNName[8];
+	__le32	MoreFeatureBits;
+	__le32	ReservedGrowth[1];
 };
 #define AAC_FEATURE_FALCON	0x00000010
 #define AAC_SIS_VERSION_V3	3
@@ -970,7 +950,6 @@
 	struct fib              *fibs;
 
 	struct fib		*free_fib;
-	struct fib		*timeout_fib;
 	spinlock_t		fib_lock;
 	
 	struct aac_queue_block *queues;
@@ -1060,6 +1039,9 @@
 #define aac_adapter_check_health(dev) \
 	(dev)->a_ops.adapter_check_health(dev)
 
+#define aac_adapter_restart(dev,bled) \
+	(dev)->a_ops.adapter_restart(dev,bled)
+
 #define aac_adapter_ioremap(dev, size) \
 	(dev)->a_ops.adapter_ioremap(dev, size)
 
@@ -1516,8 +1498,7 @@
 	struct creation_info	create_info;	/* if applicable */
 	__le32			capacity;
 	__le32			vol;    	/* substrate structure */
-	__le32			obj;	        /* FT_FILESYS, 
-						   FT_DATABASE, etc. */
+	__le32			obj;	        /* FT_FILESYS, etc. */
 	__le32			state;		/* unready for mounting, 
 						   readonly, etc. */
 	union aac_contentinfo	fileinfo;	/* Info specific to content 
@@ -1817,7 +1798,7 @@
 int aac_consumer_get(struct aac_dev * dev, struct aac_queue * q, struct aac_entry **entry);
 void aac_consumer_free(struct aac_dev * dev, struct aac_queue * q, u32 qnum);
 int aac_fib_complete(struct fib * context);
-#define fib_data(fibctx) ((void *)(fibctx)->hw_fib->data)
+#define fib_data(fibctx) ((void *)(fibctx)->hw_fib_va->data)
 struct aac_dev *aac_init_adapter(struct aac_dev *dev);
 int aac_get_config_status(struct aac_dev *dev, int commit_flag);
 int aac_get_containers(struct aac_dev *dev);
@@ -1840,8 +1821,11 @@
 int aac_get_adapter_info(struct aac_dev* dev);
 int aac_send_shutdown(struct aac_dev *dev);
 int aac_probe_container(struct aac_dev *dev, int cid);
+int _aac_rx_init(struct aac_dev *dev);
+int aac_rx_select_comm(struct aac_dev *dev, int comm);
 extern int numacb;
 extern int acbsize;
 extern char aac_driver_version[];
 extern int startup_timeout;
 extern int aif_timeout;
+extern int expose_physicals;
diff --git a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c
index e21070f..72b0393 100644
--- a/drivers/scsi/aacraid/commctrl.c
+++ b/drivers/scsi/aacraid/commctrl.c
@@ -5,7 +5,7 @@
  * based on the old aacraid driver that is..
  * Adaptec aacraid device driver for Linux.
  *
- * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
+ * Copyright (c) 2000-2007 Adaptec, Inc. (aacraid@adaptec.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
@@ -64,12 +64,15 @@
 	unsigned size;
 	int retval;
 
+	if (dev->in_reset) {
+		return -EBUSY;
+	}
 	fibptr = aac_fib_alloc(dev);
 	if(fibptr == NULL) {
 		return -ENOMEM;
 	}
 		
-	kfib = fibptr->hw_fib;
+	kfib = fibptr->hw_fib_va;
 	/*
 	 *	First copy in the header so that we can check the size field.
 	 */
@@ -91,9 +94,9 @@
 			goto cleanup;
 		}
 		/* Highjack the hw_fib */
-		hw_fib = fibptr->hw_fib;
+		hw_fib = fibptr->hw_fib_va;
 		hw_fib_pa = fibptr->hw_fib_pa;
-		fibptr->hw_fib = kfib = pci_alloc_consistent(dev->pdev, size, &fibptr->hw_fib_pa);
+		fibptr->hw_fib_va = 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);
 	}
@@ -137,7 +140,7 @@
 	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;
+		fibptr->hw_fib_va = hw_fib;
 	}
 	if (retval != -EINTR)
 		aac_fib_free(fibptr);
@@ -282,15 +285,15 @@
 		fib = list_entry(entry, struct fib, fiblink);
 		fibctx->count--;
 		spin_unlock_irqrestore(&dev->fib_lock, flags);
-		if (copy_to_user(f.fib, fib->hw_fib, sizeof(struct hw_fib))) {
-			kfree(fib->hw_fib);
+		if (copy_to_user(f.fib, fib->hw_fib_va, sizeof(struct hw_fib))) {
+			kfree(fib->hw_fib_va);
 			kfree(fib);
 			return -EFAULT;
 		}	
 		/*
 		 *	Free the space occupied by this copy of the fib.
 		 */
-		kfree(fib->hw_fib);
+		kfree(fib->hw_fib_va);
 		kfree(fib);
 		status = 0;
 	} else {
@@ -340,7 +343,7 @@
 		/*
 		 *	Free the space occupied by this copy of the fib.
 		 */
-		kfree(fib->hw_fib);
+		kfree(fib->hw_fib_va);
 		kfree(fib);
 	}
 	/*
@@ -388,10 +391,8 @@
 		/*
 		 *	Extract the fibctx from the input parameters
 		 */
-		if (fibctx->unique == (u32)(unsigned long)arg) {   
-			/* We found a winner */
+		if (fibctx->unique == (u32)(ptrdiff_t)arg) /* We found a winner */
 			break;
-		}
 		entry = entry->next;
 		fibctx = NULL;
 	}
@@ -465,16 +466,20 @@
 	void *sg_list[32];
 	u32   sg_indx = 0;
 	u32 byte_count = 0;
-	u32 actual_fibsize = 0;
+	u32 actual_fibsize64, actual_fibsize = 0;
 	int i;
 
 
+	if (dev->in_reset) {
+		dprintk((KERN_DEBUG"aacraid: send raw srb -EBUSY\n"));
+		return -EBUSY;
+	}
 	if (!capable(CAP_SYS_ADMIN)){
 		dprintk((KERN_DEBUG"aacraid: No permission to send raw srb\n")); 
 		return -EPERM;
 	}
 	/*
-	 *	Allocate and initialize a Fib then setup a BlockWrite command
+	 *	Allocate and initialize a Fib then setup a SRB command
 	 */
 	if (!(srbfib = aac_fib_alloc(dev))) {
 		return -ENOMEM;
@@ -541,129 +546,183 @@
 		rcode = -EINVAL;
 		goto cleanup;
 	}
-	if (dev->dac_support == 1) {
+	actual_fibsize = sizeof(struct aac_srb) - sizeof(struct sgentry) +
+		((user_srbcmd->sg.count & 0xff) * sizeof(struct sgentry));
+	actual_fibsize64 = actual_fibsize + (user_srbcmd->sg.count & 0xff) *
+	  (sizeof(struct sgentry64) - sizeof(struct sgentry));
+	/* User made a mistake - should not continue */
+	if ((actual_fibsize != fibsize) && (actual_fibsize64 != fibsize)) {
+		dprintk((KERN_DEBUG"aacraid: Bad Size specified in "
+		  "Raw SRB command calculated fibsize=%lu;%lu "
+		  "user_srbcmd->sg.count=%d aac_srb=%lu sgentry=%lu;%lu "
+		  "issued fibsize=%d\n",
+		  actual_fibsize, actual_fibsize64, user_srbcmd->sg.count,
+		  sizeof(struct aac_srb), sizeof(struct sgentry),
+		  sizeof(struct sgentry64), fibsize));
+		rcode = -EINVAL;
+		goto cleanup;
+	}
+	if ((data_dir == DMA_NONE) && user_srbcmd->sg.count) {
+		dprintk((KERN_DEBUG"aacraid: SG with no direction specified in Raw SRB command\n"));
+		rcode = -EINVAL;
+		goto cleanup;
+	}
+	byte_count = 0;
+	if (dev->adapter_info.options & AAC_OPT_SGMAP_HOST64) {
 		struct user_sgmap64* upsg = (struct user_sgmap64*)&user_srbcmd->sg;
 		struct sgmap64* psg = (struct sgmap64*)&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) +
-			((upsg->count & 0xff) * 
-		 	sizeof(struct sgentry));
-		if(actual_fibsize != fibsize){ // User made a mistake - should not continue
-			dprintk((KERN_DEBUG"aacraid: Bad Size specified in Raw SRB command\n"));
-			rcode = -EINVAL;
-			goto cleanup;
-		}
-		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;
-		}
+		if (actual_fibsize64 == fibsize) {
+			actual_fibsize = actual_fibsize64;
+			for (i = 0; i < upsg->count; i++) {
+				u64 addr;
+				void* p;
+				/* Does this really need to be GFP_DMA? */
+				p = kmalloc(upsg->sg[i].count,GFP_KERNEL|__GFP_DMA);
+				if(p == 0) {
+					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;
+				}
+				addr = (u64)upsg->sg[i].addr[0];
+				addr += ((u64)upsg->sg[i].addr[1]) << 32;
+				sg_user[i] = (void __user *)(ptrdiff_t)addr;
+				sg_list[i] = p; // save so we can clean up later
+				sg_indx = i;
 
-		for (i = 0; i < usg->count; i++) {
-			u64 addr;
-			void* p;
-			/* Does this really need to be GFP_DMA? */
-			p = kmalloc(usg->sg[i].count,GFP_KERNEL|__GFP_DMA);
-			if(p == 0) {
-				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));
+				if( flags & SRB_DataOut ){
+					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, upsg->sg[i].count, data_dir);
+
+				psg->sg[i].addr[0] = cpu_to_le32(addr & 0xffffffff);
+				psg->sg[i].addr[1] = cpu_to_le32(addr>>32);
+				byte_count += upsg->sg[i].count;
+				psg->sg[i].count = cpu_to_le32(upsg->sg[i].count);
+			}
+		} else {
+			struct user_sgmap* usg;
+			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;
 			}
-			sg_user[i] = (void __user *)(long)usg->sg[i].addr;
-			sg_list[i] = p; // save so we can clean up later
-			sg_indx = i;
+			memcpy (usg, upsg, actual_fibsize - sizeof(struct aac_srb)
+			  + sizeof(struct sgmap));
+			actual_fibsize = actual_fibsize64;
 
-			if( flags & SRB_DataOut ){
-				if(copy_from_user(p,sg_user[i],upsg->sg[i].count)){
+			for (i = 0; i < usg->count; i++) {
+				u64 addr;
+				void* p;
+				/* Does this really need to be GFP_DMA? */
+				p = kmalloc(usg->sg[i].count,GFP_KERNEL|__GFP_DMA);
+				if(p == 0) {
 					kfree (usg);
-					dprintk((KERN_DEBUG"aacraid: Could not copy sg data from user\n")); 
-					rcode = -EFAULT;
+					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 *)(ptrdiff_t)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],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, usg->sg[i].count, data_dir);
+
+				psg->sg[i].addr[0] = cpu_to_le32(addr & 0xffffffff);
+				psg->sg[i].addr[1] = cpu_to_le32(addr>>32);
+				byte_count += usg->sg[i].count;
+				psg->sg[i].count = cpu_to_le32(usg->sg[i].count);
 			}
-			addr = pci_map_single(dev->pdev, p, usg->sg[i].count, data_dir);
-
-			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);
 		}
-		kfree (usg);
-
 		srbcmd->count = cpu_to_le32(byte_count);
 		psg->count = cpu_to_le32(sg_indx+1);
 		status = aac_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) + (((user_srbcmd->sg.count & 0xff) - 1) * sizeof (struct sgentry));
-		if(actual_fibsize != fibsize){ // User made a mistake - should not continue
-			dprintk((KERN_DEBUG"aacraid: Bad Size specified in "
-			  "Raw SRB command calculated fibsize=%d "
-			  "user_srbcmd->sg.count=%d aac_srb=%d sgentry=%d "
-			  "issued fibsize=%d\n",
-			  actual_fibsize, user_srbcmd->sg.count,
-			  sizeof(struct aac_srb), sizeof(struct sgentry),
-			  fibsize));
-			rcode = -EINVAL;
-			goto cleanup;
-		}
-		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 < upsg->count; i++) {
-			dma_addr_t addr; 
-			void* p;
-			p = kmalloc(upsg->sg[i].count, GFP_KERNEL);
-			if(p == 0) {
-				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 *)(long)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],
-						upsg->sg[i].count)) {
-					dprintk((KERN_DEBUG"aacraid: Could not copy sg data from user\n")); 
-					rcode = -EFAULT;
+		if (actual_fibsize64 == fibsize) {
+			struct user_sgmap64* usg = (struct user_sgmap64 *)upsg;
+			for (i = 0; i < upsg->count; i++) {
+				u64 addr;
+				void* p;
+				/* Does this really need to be GFP_DMA? */
+				p = kmalloc(usg->sg[i].count,GFP_KERNEL|__GFP_DMA);
+				if(p == 0) {
+					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;
 				}
-			}
-			addr = pci_map_single(dev->pdev, p,
-				upsg->sg[i].count, data_dir);
+				addr = (u64)usg->sg[i].addr[0];
+				addr += ((u64)usg->sg[i].addr[1]) << 32;
+				sg_user[i] = (void __user *)(ptrdiff_t)addr;
+				sg_list[i] = p; // save so we can clean up later
+				sg_indx = i;
 
-			psg->sg[i].addr = cpu_to_le32(addr);
-			psg->sg[i].count = cpu_to_le32(upsg->sg[i].count);  
-			byte_count += upsg->sg[i].count;
+				if( flags & SRB_DataOut ){
+					if(copy_from_user(p,sg_user[i],usg->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, usg->sg[i].count, data_dir);
+
+				psg->sg[i].addr = cpu_to_le32(addr & 0xffffffff);
+				byte_count += usg->sg[i].count;
+				psg->sg[i].count = cpu_to_le32(usg->sg[i].count);
+			}
+		} else {
+			for (i = 0; i < upsg->count; i++) {
+				dma_addr_t addr;
+				void* p;
+				p = kmalloc(upsg->sg[i].count, GFP_KERNEL);
+				if(p == 0) {
+					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 *)(ptrdiff_t)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],
+							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,
+					upsg->sg[i].count, data_dir);
+
+				psg->sg[i].addr = cpu_to_le32(addr);
+				byte_count += upsg->sg[i].count;
+				psg->sg[i].count = cpu_to_le32(upsg->sg[i].count);
+			}
 		}
 		srbcmd->count = cpu_to_le32(byte_count);
 		psg->count = cpu_to_le32(sg_indx+1);
@@ -682,7 +741,8 @@
 
 	if( flags & SRB_DataIn ) {
 		for(i = 0 ; i <= sg_indx; i++){
-			byte_count = le32_to_cpu((dev->dac_support == 1)
+			byte_count = le32_to_cpu(
+			  (dev->adapter_info.options & AAC_OPT_SGMAP_HOST64)
 			      ? ((struct sgmap64*)&srbcmd->sg)->sg[i].count
 			      : srbcmd->sg.sg[i].count);
 			if(copy_to_user(sg_user[i], sg_list[i], byte_count)){
diff --git a/drivers/scsi/aacraid/comminit.c b/drivers/scsi/aacraid/comminit.c
index ae34768..33682ce 100644
--- a/drivers/scsi/aacraid/comminit.c
+++ b/drivers/scsi/aacraid/comminit.c
@@ -5,7 +5,7 @@
  * based on the old aacraid driver that is..
  * Adaptec aacraid device driver for Linux.
  *
- * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
+ * Copyright (c) 2000-2007 Adaptec, Inc. (aacraid@adaptec.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
@@ -110,7 +110,7 @@
 	/*
 	 *	Align the beginning of Headers to commalign
 	 */
-	align = (commalign - ((unsigned long)(base) & (commalign - 1)));
+	align = (commalign - ((ptrdiff_t)(base) & (commalign - 1)));
 	base = base + align;
 	phys = phys + align;
 	/*
diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c
index 1b97f60..5824a75 100644
--- a/drivers/scsi/aacraid/commsup.c
+++ b/drivers/scsi/aacraid/commsup.c
@@ -5,7 +5,7 @@
  * based on the old aacraid driver that is..
  * Adaptec aacraid device driver for Linux.
  *
- * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
+ * Copyright (c) 2000-2007 Adaptec, Inc. (aacraid@adaptec.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
@@ -94,7 +94,7 @@
 int aac_fib_setup(struct aac_dev * dev)
 {
 	struct fib *fibptr;
-	struct hw_fib *hw_fib_va;
+	struct hw_fib *hw_fib;
 	dma_addr_t hw_fib_pa;
 	int i;
 
@@ -106,24 +106,24 @@
 	if (i<0)
 		return -ENOMEM;
 		
-	hw_fib_va = dev->hw_fib_va;
+	hw_fib = dev->hw_fib_va;
 	hw_fib_pa = dev->hw_fib_pa;
-	memset(hw_fib_va, 0, dev->max_fib_size * (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB));
+	memset(hw_fib, 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 < (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB); i++, fibptr++) 
 	{
 		fibptr->dev = dev;
-		fibptr->hw_fib = hw_fib_va;
-		fibptr->data = (void *) fibptr->hw_fib->data;
+		fibptr->hw_fib_va = hw_fib;
+		fibptr->data = (void *) fibptr->hw_fib_va->data;
 		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 = cpu_to_le32(0xffffffff);
-		hw_fib_va->header.SenderSize = cpu_to_le16(dev->max_fib_size);
+		hw_fib->header.XferState = cpu_to_le32(0xffffffff);
+		hw_fib->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 + dev->max_fib_size);
+		hw_fib = (struct hw_fib *)((unsigned char *)hw_fib + dev->max_fib_size);
 		hw_fib_pa = hw_fib_pa + dev->max_fib_size;
 	}
 	/*
@@ -166,7 +166,7 @@
 	 *	Null out fields that depend on being zero at the start of
 	 *	each I/O
 	 */
-	fibptr->hw_fib->header.XferState = 0;
+	fibptr->hw_fib_va->header.XferState = 0;
 	fibptr->callback = NULL;
 	fibptr->callback_data = NULL;
 
@@ -178,7 +178,6 @@
  *	@fibptr: fib to free up
  *
  *	Frees up a fib and places it on the appropriate queue
- *	(either free or timed out)
  */
  
 void aac_fib_free(struct fib *fibptr)
@@ -186,19 +185,15 @@
 	unsigned long flags;
 
 	spin_lock_irqsave(&fibptr->dev->fib_lock, flags);
-	if (fibptr->flags & FIB_CONTEXT_FLAG_TIMED_OUT) {
+	if (unlikely(fibptr->flags & FIB_CONTEXT_FLAG_TIMED_OUT))
 		aac_config.fib_timeouts++;
-		fibptr->next = fibptr->dev->timeout_fib;
-		fibptr->dev->timeout_fib = fibptr;
-	} else {
-		if (fibptr->hw_fib->header.XferState != 0) {
-			printk(KERN_WARNING "aac_fib_free, XferState != 0, fibptr = 0x%p, XferState = 0x%x\n",
-				 (void*)fibptr, 
-				 le32_to_cpu(fibptr->hw_fib->header.XferState));
-		}
-		fibptr->next = fibptr->dev->free_fib;
-		fibptr->dev->free_fib = fibptr;
-	}	
+	if (fibptr->hw_fib_va->header.XferState != 0) {
+		printk(KERN_WARNING "aac_fib_free, XferState != 0, fibptr = 0x%p, XferState = 0x%x\n",
+			 (void*)fibptr,
+			 le32_to_cpu(fibptr->hw_fib_va->header.XferState));
+	}
+	fibptr->next = fibptr->dev->free_fib;
+	fibptr->dev->free_fib = fibptr;
 	spin_unlock_irqrestore(&fibptr->dev->fib_lock, flags);
 }
 
@@ -211,7 +206,7 @@
  
 void aac_fib_init(struct fib *fibptr)
 {
-	struct hw_fib *hw_fib = fibptr->hw_fib;
+	struct hw_fib *hw_fib = fibptr->hw_fib_va;
 
 	hw_fib->header.StructType = FIB_MAGIC;
 	hw_fib->header.Size = cpu_to_le16(fibptr->dev->max_fib_size);
@@ -231,7 +226,7 @@
  
 static void fib_dealloc(struct fib * fibptr)
 {
-	struct hw_fib *hw_fib = fibptr->hw_fib;
+	struct hw_fib *hw_fib = fibptr->hw_fib_va;
 	BUG_ON(hw_fib->header.StructType != FIB_MAGIC);
 	hw_fib->header.XferState = 0;        
 }
@@ -386,7 +381,7 @@
 		void *callback_data)
 {
 	struct aac_dev * dev = fibptr->dev;
-	struct hw_fib * hw_fib = fibptr->hw_fib;
+	struct hw_fib * hw_fib = fibptr->hw_fib_va;
 	unsigned long flags = 0;
 	unsigned long qflags;
 
@@ -430,7 +425,7 @@
 	 */
 	hw_fib->header.Command = cpu_to_le16(command);
 	hw_fib->header.XferState |= cpu_to_le32(SentFromHost);
-	fibptr->hw_fib->header.Flags = 0;	/* 0 the flags field - internal only*/
+	fibptr->hw_fib_va->header.Flags = 0;	/* 0 the flags field - internal only*/
 	/*
 	 *	Set the size of the Fib we want to send to the adapter
 	 */
@@ -462,7 +457,7 @@
 	dprintk((KERN_DEBUG "  Command =               %d.\n", le32_to_cpu(hw_fib->header.Command)));
 	dprintk((KERN_DEBUG "  SubCommand =            %d.\n", le32_to_cpu(((struct aac_query_mount *)fib_data(fibptr))->command)));
 	dprintk((KERN_DEBUG "  XferState  =            %x.\n", le32_to_cpu(hw_fib->header.XferState)));
-	dprintk((KERN_DEBUG "  hw_fib va being sent=%p\n",fibptr->hw_fib));
+	dprintk((KERN_DEBUG "  hw_fib va being sent=%p\n",fibptr->hw_fib_va));
 	dprintk((KERN_DEBUG "  hw_fib pa being sent=%lx\n",(ulong)fibptr->hw_fib_pa));
 	dprintk((KERN_DEBUG "  fib being sent=%p\n",fibptr));
 
@@ -513,22 +508,20 @@
 				}
 				udelay(5);
 			}
-		} else if (down_interruptible(&fibptr->event_wait)) {
-			spin_lock_irqsave(&fibptr->event_lock, flags);
-			if (fibptr->done == 0) {
-				fibptr->done = 2; /* Tell interrupt we aborted */
-				spin_unlock_irqrestore(&fibptr->event_lock, flags);
-				return -EINTR;
-			}
+		} else
+			(void)down_interruptible(&fibptr->event_wait);
+		spin_lock_irqsave(&fibptr->event_lock, flags);
+		if (fibptr->done == 0) {
+			fibptr->done = 2; /* Tell interrupt we aborted */
 			spin_unlock_irqrestore(&fibptr->event_lock, flags);
+			return -EINTR;
 		}
+		spin_unlock_irqrestore(&fibptr->event_lock, flags);
 		BUG_ON(fibptr->done == 0);
 			
-		if((fibptr->flags & FIB_CONTEXT_FLAG_TIMED_OUT)){
+		if(unlikely(fibptr->flags & FIB_CONTEXT_FLAG_TIMED_OUT))
 			return -ETIMEDOUT;
-		} else {
-			return 0;
-		}
+		return 0;
 	}
 	/*
 	 *	If the user does not want a response than return success otherwise
@@ -624,7 +617,7 @@
 
 int aac_fib_adapter_complete(struct fib *fibptr, unsigned short size)
 {
-	struct hw_fib * hw_fib = fibptr->hw_fib;
+	struct hw_fib * hw_fib = fibptr->hw_fib_va;
 	struct aac_dev * dev = fibptr->dev;
 	struct aac_queue * q;
 	unsigned long nointr = 0;
@@ -688,7 +681,7 @@
  
 int aac_fib_complete(struct fib *fibptr)
 {
-	struct hw_fib * hw_fib = fibptr->hw_fib;
+	struct hw_fib * hw_fib = fibptr->hw_fib_va;
 
 	/*
 	 *	Check for a fib which has already been completed
@@ -774,9 +767,8 @@
 #define AIF_SNIFF_TIMEOUT	(30*HZ)
 static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr)
 {
-	struct hw_fib * hw_fib = fibptr->hw_fib;
+	struct hw_fib * hw_fib = fibptr->hw_fib_va;
 	struct aac_aifcmd * aifcmd = (struct aac_aifcmd *)hw_fib->data;
-	int busy;
 	u32 container;
 	struct scsi_device *device;
 	enum {
@@ -988,9 +980,6 @@
 	 * behind you.
 	 */
 
-	busy = 0;
-
-
 	/*
 	 *	Find the scsi_device associated with the SCSI address,
 	 * and mark it as changed, invalidating the cache. This deals
@@ -1035,7 +1024,6 @@
 static int _aac_reset_adapter(struct aac_dev *aac)
 {
 	int index, quirks;
-	u32 ret;
 	int retval;
 	struct Scsi_Host *host;
 	struct scsi_device *dev;
@@ -1059,35 +1047,29 @@
 	 *	If a positive health, means in a known DEAD PANIC
 	 * state and the adapter could be reset to `try again'.
 	 */
-	retval = aac_adapter_check_health(aac);
-	if (retval == 0)
-		retval = aac_adapter_sync_cmd(aac, IOP_RESET_ALWAYS,
-		  0, 0, 0, 0, 0, 0, &ret, NULL, NULL, NULL, NULL);
-	if (retval)
-		retval = aac_adapter_sync_cmd(aac, IOP_RESET,
-		  0, 0, 0, 0, 0, 0, &ret, NULL, NULL, NULL, NULL);
+	retval = aac_adapter_restart(aac, aac_adapter_check_health(aac));
 
 	if (retval)
 		goto out;
-	if (ret != 0x00000001) {
-		retval = -ENODEV;
-		goto out;
-	}
 
 	/*
 	 *	Loop through the fibs, close the synchronous FIBS
 	 */
-	for (index = 0; index < (aac->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB); index++) {
+	for (retval = 1, index = 0; index < (aac->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB); index++) {
 		struct fib *fib = &aac->fibs[index];
-		if (!(fib->hw_fib->header.XferState & cpu_to_le32(NoResponseExpected | Async)) &&
-		  (fib->hw_fib->header.XferState & cpu_to_le32(ResponseExpected))) {
+		if (!(fib->hw_fib_va->header.XferState & cpu_to_le32(NoResponseExpected | Async)) &&
+		  (fib->hw_fib_va->header.XferState & cpu_to_le32(ResponseExpected))) {
 			unsigned long flagv;
 			spin_lock_irqsave(&fib->event_lock, flagv);
 			up(&fib->event_wait);
 			spin_unlock_irqrestore(&fib->event_lock, flagv);
 			schedule();
+			retval = 0;
 		}
 	}
+	/* Give some extra time for ioctls to complete. */
+	if (retval == 0)
+		ssleep(2);
 	index = aac->cardtype;
 
 	/*
@@ -1248,7 +1230,7 @@
 
 			memset(hw_fib, 0, sizeof(struct hw_fib));
 			memset(fib, 0, sizeof(struct fib));
-			fib->hw_fib = hw_fib;
+			fib->hw_fib_va = hw_fib;
 			fib->dev = aac;
 			aac_fib_init(fib);
 			fib->type = FSAFS_NTC_FIB_CONTEXT;
@@ -1354,11 +1336,11 @@
 			 *	do anything at this point since we don't have
 			 *	anything defined for this thread to do.
 			 */
-			hw_fib = fib->hw_fib;
+			hw_fib = fib->hw_fib_va;
 			memset(fib, 0, sizeof(struct fib));
 			fib->type = FSAFS_NTC_FIB_CONTEXT;
 			fib->size = sizeof( struct fib );
-			fib->hw_fib = hw_fib;
+			fib->hw_fib_va = hw_fib;
 			fib->data = hw_fib->data;
 			fib->dev = dev;
 			/*
@@ -1485,7 +1467,7 @@
 						 */
 						memcpy(hw_newfib, hw_fib, sizeof(struct hw_fib));
 						memcpy(newfib, fib, sizeof(struct fib));
-						newfib->hw_fib = hw_newfib;
+						newfib->hw_fib_va = hw_newfib;
 						/*
 						 * Put the FIB onto the
 						 * fibctx's fibs
diff --git a/drivers/scsi/aacraid/dpcsup.c b/drivers/scsi/aacraid/dpcsup.c
index d38b628..42c7dcd 100644
--- a/drivers/scsi/aacraid/dpcsup.c
+++ b/drivers/scsi/aacraid/dpcsup.c
@@ -5,7 +5,7 @@
  * based on the old aacraid driver that is..
  * Adaptec aacraid device driver for Linux.
  *
- * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
+ * Copyright (c) 2000-2007 Adaptec, Inc. (aacraid@adaptec.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
@@ -32,7 +32,6 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/types.h>
-#include <linux/pci.h>
 #include <linux/spinlock.h>
 #include <linux/slab.h>
 #include <linux/completion.h>
@@ -73,7 +72,7 @@
 		u32 index = le32_to_cpu(entry->addr);
 		fast = index & 0x01;
 		fib = &dev->fibs[index >> 2];
-		hwfib = fib->hw_fib;
+		hwfib = fib->hw_fib_va;
 		
 		aac_consumer_free(dev, q, HostNormRespQueue);
 		/*
@@ -84,11 +83,13 @@
 		 *	continue. The caller has already been notified that
 		 *	the fib timed out.
 		 */
-		if (!(fib->flags & FIB_CONTEXT_FLAG_TIMED_OUT))
-			dev->queues->queue[AdapNormCmdQueue].numpending--;
-		else {
-			printk(KERN_WARNING "aacraid: FIB timeout (%x).\n", fib->flags);
-			printk(KERN_DEBUG"aacraid: hwfib=%p fib index=%i fib=%p\n",hwfib, hwfib->header.SenderData,fib);
+		dev->queues->queue[AdapNormCmdQueue].numpending--;
+
+		if (unlikely(fib->flags & FIB_CONTEXT_FLAG_TIMED_OUT)) {
+			spin_unlock_irqrestore(q->lock, flags);
+			aac_fib_complete(fib);
+			aac_fib_free(fib);
+			spin_lock_irqsave(q->lock, flags);
 			continue;
 		}
 		spin_unlock_irqrestore(q->lock, flags);
@@ -193,7 +194,7 @@
 		INIT_LIST_HEAD(&fib->fiblink);
 		fib->type = FSAFS_NTC_FIB_CONTEXT;
 		fib->size = sizeof(struct fib);
-		fib->hw_fib = hw_fib;
+		fib->hw_fib_va = hw_fib;
 		fib->data = hw_fib->data;
 		fib->dev = dev;
 		
@@ -254,12 +255,13 @@
 			return 1;
 		}
 		memset(hw_fib, 0, sizeof(struct hw_fib));
-		memcpy(hw_fib, (struct hw_fib *)(((unsigned long)(dev->regs.sa)) + (index & ~0x00000002L)), sizeof(struct hw_fib));
+		memcpy(hw_fib, (struct hw_fib *)(((ptrdiff_t)(dev->regs.sa)) +
+		  (index & ~0x00000002L)), sizeof(struct hw_fib));
 		memset(fib, 0, sizeof(struct fib));
 		INIT_LIST_HEAD(&fib->fiblink);
 		fib->type = FSAFS_NTC_FIB_CONTEXT;
 		fib->size = sizeof(struct fib);
-		fib->hw_fib = hw_fib;
+		fib->hw_fib_va = hw_fib;
 		fib->data = hw_fib->data;
 		fib->dev = dev;
 	
@@ -271,7 +273,7 @@
 	} else {
 		int fast = index & 0x01;
 		struct fib * fib = &dev->fibs[index >> 2];
-		struct hw_fib * hwfib = fib->hw_fib;
+		struct hw_fib * hwfib = fib->hw_fib_va;
 
 		/*
 		 *	Remove this fib from the Outstanding I/O queue.
@@ -281,14 +283,14 @@
 		 *	continue. The caller has already been notified that
 		 *	the fib timed out.
 		 */
-		if ((fib->flags & FIB_CONTEXT_FLAG_TIMED_OUT)) {
-			printk(KERN_WARNING "aacraid: FIB timeout (%x).\n", fib->flags);
-			printk(KERN_DEBUG"aacraid: hwfib=%p index=%i fib=%p\n",hwfib, hwfib->header.SenderData,fib);
+		dev->queues->queue[AdapNormCmdQueue].numpending--;
+
+		if (unlikely(fib->flags & FIB_CONTEXT_FLAG_TIMED_OUT)) {
+			aac_fib_complete(fib);
+			aac_fib_free(fib);
 			return 0;
 		}
 
-		dev->queues->queue[AdapNormCmdQueue].numpending--;
-
 		if (fast) {
 			/*
 			 *	Doctor the fib
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
index 0f948c2..350ea7f 100644
--- a/drivers/scsi/aacraid/linit.c
+++ b/drivers/scsi/aacraid/linit.c
@@ -5,7 +5,7 @@
  * based on the old aacraid driver that is..
  * Adaptec aacraid device driver for Linux.
  *
- * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
+ * Copyright (c) 2000-2007 Adaptec, Inc. (aacraid@adaptec.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
@@ -82,8 +82,6 @@
 static int aac_cfg_major = -1;
 char aac_driver_version[] = AAC_DRIVER_FULL_VERSION;
 
-extern int expose_physicals;
-
 /*
  * Because of the way Linux names scsi devices, the order in this table has
  * become important.  Check for on-board Raid first, add-in cards second.
@@ -247,7 +245,19 @@
 
 static int aac_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
 {
+	struct Scsi_Host *host = cmd->device->host;
+	struct aac_dev *dev = (struct aac_dev *)host->hostdata;
+	u32 count = 0;
 	cmd->scsi_done = done;
+	for (; count < (host->can_queue + AAC_NUM_MGT_FIB); ++count) {
+		struct fib * fib = &dev->fibs[count];
+		struct scsi_cmnd * command;
+		if (fib->hw_fib_va->header.XferState &&
+		    ((command = fib->callback_data)) &&
+		    (command == cmd) &&
+		    (cmd->SCp.phase == AAC_OWNER_FIRMWARE))
+			return 0; /* Already owned by Adapter */
+	}
 	cmd->SCp.phase = AAC_OWNER_LOWLEVEL;
 	return (aac_scsi_cmd(cmd) ? FAILED : 0);
 } 
@@ -446,6 +456,40 @@
 	return aac_do_ioctl(dev, cmd, arg);
 }
 
+static int aac_eh_abort(struct scsi_cmnd* cmd)
+{
+	struct scsi_device * dev = cmd->device;
+	struct Scsi_Host * host = dev->host;
+	struct aac_dev * aac = (struct aac_dev *)host->hostdata;
+	int count;
+	int ret = FAILED;
+
+	printk(KERN_ERR "%s: Host adapter abort request (%d,%d,%d,%d)\n",
+		AAC_DRIVERNAME,
+		host->host_no, sdev_channel(dev), sdev_id(dev), dev->lun);
+	switch (cmd->cmnd[0]) {
+	case SERVICE_ACTION_IN:
+		if (!(aac->raw_io_interface) ||
+		    !(aac->raw_io_64) ||
+		    ((cmd->cmnd[1] & 0x1f) != SAI_READ_CAPACITY_16))
+			break;
+	case INQUIRY:
+	case READ_CAPACITY:
+	case TEST_UNIT_READY:
+		/* Mark associated FIB to not complete, eh handler does this */
+		for (count = 0; count < (host->can_queue + AAC_NUM_MGT_FIB); ++count) {
+			struct fib * fib = &aac->fibs[count];
+			if (fib->hw_fib_va->header.XferState &&
+			  (fib->callback_data == cmd)) {
+				fib->flags |= FIB_CONTEXT_FLAG_TIMED_OUT;
+				cmd->SCp.phase = AAC_OWNER_ERROR_HANDLER;
+				ret = SUCCESS;
+			}
+		}
+	}
+	return ret;
+}
+
 /*
  *	aac_eh_reset	- Reset command handling
  *	@scsi_cmd:	SCSI command block causing the reset
@@ -457,12 +501,20 @@
 	struct Scsi_Host * host = dev->host;
 	struct scsi_cmnd * command;
 	int count;
-	struct aac_dev * aac;
+	struct aac_dev * aac = (struct aac_dev *)host->hostdata;
 	unsigned long flags;
 
+	/* Mark the associated FIB to not complete, eh handler does this */
+	for (count = 0; count < (host->can_queue + AAC_NUM_MGT_FIB); ++count) {
+		struct fib * fib = &aac->fibs[count];
+		if (fib->hw_fib_va->header.XferState &&
+		  (fib->callback_data == cmd)) {
+			fib->flags |= FIB_CONTEXT_FLAG_TIMED_OUT;
+			cmd->SCp.phase = AAC_OWNER_ERROR_HANDLER;
+		}
+	}
 	printk(KERN_ERR "%s: Host adapter reset request. SCSI hang ?\n", 
 					AAC_DRIVERNAME);
-	aac = (struct aac_dev *)host->hostdata;
 
 	if ((count = aac_check_health(aac)))
 		return count;
@@ -496,7 +548,7 @@
 		ssleep(1);
 	}
 	printk(KERN_ERR "%s: SCSI bus appears hung\n", AAC_DRIVERNAME);
-	return -ETIMEDOUT;
+	return SUCCESS; /* Cause an immediate retry of the command with a ten second delay after successful tur */
 }
 
 /**
@@ -796,6 +848,7 @@
 	.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        		= MAXIMUM_NUM_CONTAINERS,
diff --git a/drivers/scsi/aacraid/nark.c b/drivers/scsi/aacraid/nark.c
index c76b611..a8ace56 100644
--- a/drivers/scsi/aacraid/nark.c
+++ b/drivers/scsi/aacraid/nark.c
@@ -74,9 +74,6 @@
 
 int aac_nark_init(struct aac_dev * dev)
 {
-	extern int _aac_rx_init(struct aac_dev *dev);
-	extern int aac_rx_select_comm(struct aac_dev *dev, int comm);
-
 	/*
 	 *	Fill in the function dispatch table.
 	 */
diff --git a/drivers/scsi/aacraid/rkt.c b/drivers/scsi/aacraid/rkt.c
index d953c3f..9c5fcfb 100644
--- a/drivers/scsi/aacraid/rkt.c
+++ b/drivers/scsi/aacraid/rkt.c
@@ -45,7 +45,6 @@
 static int aac_rkt_select_comm(struct aac_dev *dev, int comm)
 {
 	int retval;
-	extern int aac_rx_select_comm(struct aac_dev *dev, int comm);
 	retval = aac_rx_select_comm(dev, comm);
 	if (comm == AAC_COMM_MESSAGE) {
 		/*
@@ -97,8 +96,6 @@
 
 int aac_rkt_init(struct aac_dev *dev)
 {
-	extern int _aac_rx_init(struct aac_dev *dev);
-
 	/*
 	 *	Fill in the function dispatch table.
 	 */
diff --git a/drivers/scsi/aacraid/rx.c b/drivers/scsi/aacraid/rx.c
index d242e26..0c71315 100644
--- a/drivers/scsi/aacraid/rx.c
+++ b/drivers/scsi/aacraid/rx.c
@@ -5,7 +5,7 @@
  * based on the old aacraid driver that is..
  * Adaptec aacraid device driver for Linux.
  *
- * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
+ * Copyright (c) 2000-2007 Adaptec, Inc. (aacraid@adaptec.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
@@ -57,25 +57,25 @@
 	 *	been enabled.
 	 *	Check to see if this is our interrupt.  If it isn't just return
 	 */
-	if (intstat & ~(dev->OIMR)) {
+	if (likely(intstat & ~(dev->OIMR))) {
 		bellbits = rx_readl(dev, OutboundDoorbellReg);
-		if (bellbits & DoorBellPrintfReady) {
+		if (unlikely(bellbits & DoorBellPrintfReady)) {
 			aac_printf(dev, readl (&dev->IndexRegs->Mailbox[5]));
 			rx_writel(dev, MUnit.ODR,DoorBellPrintfReady);
 			rx_writel(dev, InboundDoorbellReg,DoorBellPrintfDone);
 		}
-		else if (bellbits & DoorBellAdapterNormCmdReady) {
+		else if (unlikely(bellbits & DoorBellAdapterNormCmdReady)) {
 			rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdReady);
 			aac_command_normal(&dev->queues->queue[HostNormCmdQueue]);
 		}
-		else if (bellbits & DoorBellAdapterNormRespReady) {
+		else if (likely(bellbits & DoorBellAdapterNormRespReady)) {
 			rx_writel(dev, MUnit.ODR,DoorBellAdapterNormRespReady);
 			aac_response_normal(&dev->queues->queue[HostNormRespQueue]);
 		}
-		else if (bellbits & DoorBellAdapterNormCmdNotFull) {
+		else if (unlikely(bellbits & DoorBellAdapterNormCmdNotFull)) {
 			rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull);
 		}
-		else if (bellbits & DoorBellAdapterNormRespNotFull) {
+		else if (unlikely(bellbits & DoorBellAdapterNormRespNotFull)) {
 			rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull);
 			rx_writel(dev, MUnit.ODR, DoorBellAdapterNormRespNotFull);
 		}
@@ -88,11 +88,11 @@
 {
 	struct aac_dev *dev = dev_id;
 	u32 Index = rx_readl(dev, MUnit.OutboundQueue);
-	if (Index == 0xFFFFFFFFL)
+	if (unlikely(Index == 0xFFFFFFFFL))
 		Index = rx_readl(dev, MUnit.OutboundQueue);
-	if (Index != 0xFFFFFFFFL) {
+	if (likely(Index != 0xFFFFFFFFL)) {
 		do {
-			if (aac_intr_normal(dev, Index)) {
+			if (unlikely(aac_intr_normal(dev, Index))) {
 				rx_writel(dev, MUnit.OutboundQueue, Index);
 				rx_writel(dev, MUnit.ODR, DoorBellAdapterNormRespReady);
 			}
@@ -204,7 +204,7 @@
 		 */
 		msleep(1);
 	}
-	if (ok != 1) {
+	if (unlikely(ok != 1)) {
 		/*
 		 *	Restore interrupt mask even though we timed out
 		 */
@@ -294,7 +294,7 @@
  *	Start up processing on an i960 based AAC adapter
  */
 
-void aac_rx_start_adapter(struct aac_dev *dev)
+static void aac_rx_start_adapter(struct aac_dev *dev)
 {
 	struct aac_init *init;
 
@@ -319,12 +319,12 @@
 	/*
 	 *	Check to see if the board failed any self tests.
 	 */
-	if (status & SELF_TEST_FAILED)
+	if (unlikely(status & SELF_TEST_FAILED))
 		return -1;
 	/*
 	 *	Check to see if the board panic'd.
 	 */
-	if (status & KERNEL_PANIC) {
+	if (unlikely(status & KERNEL_PANIC)) {
 		char * buffer;
 		struct POSTSTATUS {
 			__le32 Post_Command;
@@ -333,15 +333,15 @@
 		dma_addr_t paddr, baddr;
 		int ret;
 
-		if ((status & 0xFF000000L) == 0xBC000000L)
+		if (likely((status & 0xFF000000L) == 0xBC000000L))
 			return (status >> 16) & 0xFF;
 		buffer = pci_alloc_consistent(dev->pdev, 512, &baddr);
 		ret = -2;
-		if (buffer == NULL)
+		if (unlikely(buffer == NULL))
 			return ret;
 		post = pci_alloc_consistent(dev->pdev,
 		  sizeof(struct POSTSTATUS), &paddr);
-		if (post == NULL) {
+		if (unlikely(post == NULL)) {
 			pci_free_consistent(dev->pdev, 512, buffer, baddr);
 			return ret;
 		}
@@ -353,7 +353,7 @@
 		  NULL, NULL, NULL, NULL, NULL);
 		pci_free_consistent(dev->pdev, sizeof(struct POSTSTATUS),
 		  post, paddr);
-		if ((buffer[0] == '0') && ((buffer[1] == 'x') || (buffer[1] == 'X'))) {
+		if (likely((buffer[0] == '0') && ((buffer[1] == 'x') || (buffer[1] == 'X')))) {
 			ret = (buffer[2] <= '9') ? (buffer[2] - '0') : (buffer[2] - 'A' + 10);
 			ret <<= 4;
 			ret += (buffer[3] <= '9') ? (buffer[3] - '0') : (buffer[3] - 'A' + 10);
@@ -364,7 +364,7 @@
 	/*
 	 *	Wait for the adapter to be up and running.
 	 */
-	if (!(status & KERNEL_UP_AND_RUNNING))
+	if (unlikely(!(status & KERNEL_UP_AND_RUNNING)))
 		return -3;
 	/*
 	 *	Everything is OK
@@ -387,7 +387,7 @@
 	unsigned long nointr = 0;
 
 	spin_lock_irqsave(q->lock, qflags);
-	aac_queue_get( dev, &Index, AdapNormCmdQueue, fib->hw_fib, 1, fib, &nointr);
+	aac_queue_get( dev, &Index, AdapNormCmdQueue, fib->hw_fib_va, 1, fib, &nointr);
 
 	q->numpending++;
 	*(q->headers.producer) = cpu_to_le32(Index + 1);
@@ -419,9 +419,9 @@
 	spin_unlock_irqrestore(q->lock, qflags);
 	for(;;) {
 		Index = rx_readl(dev, MUnit.InboundQueue);
-		if (Index == 0xFFFFFFFFL)
+		if (unlikely(Index == 0xFFFFFFFFL))
 			Index = rx_readl(dev, MUnit.InboundQueue);
-		if (Index != 0xFFFFFFFFL)
+		if (likely(Index != 0xFFFFFFFFL))
 			break;
 		if (--count == 0) {
 			spin_lock_irqsave(q->lock, qflags);
@@ -437,7 +437,7 @@
 	device += sizeof(u32);
 	writel((u32)(addr >> 32), device);
 	device += sizeof(u32);
-	writel(le16_to_cpu(fib->hw_fib->header.Size), device);
+	writel(le16_to_cpu(fib->hw_fib_va->header.Size), device);
 	rx_writel(dev, MUnit.InboundQueue, Index);
 	return 0;
 }
@@ -460,22 +460,34 @@
 	return 0;
 }
 
-static int aac_rx_restart_adapter(struct aac_dev *dev)
+static int aac_rx_restart_adapter(struct aac_dev *dev, int bled)
 {
 	u32 var;
 
-	printk(KERN_ERR "%s%d: adapter kernel panic'd.\n",
-			dev->name, dev->id);
+	if (bled)
+		printk(KERN_ERR "%s%d: adapter kernel panic'd %x.\n",
+			dev->name, dev->id, bled);
+	else {
+		bled = aac_adapter_sync_cmd(dev, IOP_RESET_ALWAYS,
+		  0, 0, 0, 0, 0, 0, &var, NULL, NULL, NULL, NULL);
+		if (!bled && (var != 0x00000001))
+			bled = -EINVAL;
+	}
+	if (bled && (bled != -ETIMEDOUT))
+		bled = aac_adapter_sync_cmd(dev, IOP_RESET,
+		  0, 0, 0, 0, 0, 0, &var, NULL, NULL, NULL, NULL);
 
-	if (aac_rx_check_health(dev) <= 0)
-		return 1;
-	if (rx_sync_cmd(dev, IOP_RESET, 0, 0, 0, 0, 0, 0,
-			&var, NULL, NULL, NULL, NULL))
-		return 1;
+	if (bled && (bled != -ETIMEDOUT))
+		return -EINVAL;
+	if (bled || (var == 0x3803000F)) { /* USE_OTHER_METHOD */
+		rx_writel(dev, MUnit.reserved2, 3);
+		msleep(5000); /* Delay 5 seconds */
+		var = 0x00000001;
+	}
 	if (var != 0x00000001)
-		 return 1;
+		return -EINVAL;
 	if (rx_readl(dev, MUnit.OMRx[0]) & KERNEL_PANIC)
-		return 1;
+		return -ENODEV;
 	return 0;
 }
 
@@ -517,24 +529,29 @@
 {
 	unsigned long start;
 	unsigned long status;
-	int instance;
-	const char * name;
-
-	instance = dev->id;
-	name     = dev->name;
+	int restart = 0;
+	int instance = dev->id;
+	const char * name = dev->name;
 
 	if (aac_adapter_ioremap(dev, dev->base_size)) {
 		printk(KERN_WARNING "%s: unable to map adapter.\n", name);
 		goto error_iounmap;
 	}
 
+	/* Failure to reset here is an option ... */
+	dev->OIMR = status = rx_readb (dev, MUnit.OIMR);
+	if ((((status & 0xff) != 0xff) || reset_devices) &&
+	  !aac_rx_restart_adapter(dev, 0))
+		++restart;
 	/*
 	 *	Check to see if the board panic'd while booting.
 	 */
 	status = rx_readl(dev, MUnit.OMRx[0]);
-	if (status & KERNEL_PANIC)
-		if (aac_rx_restart_adapter(dev))
+	if (status & KERNEL_PANIC) {
+		if (aac_rx_restart_adapter(dev, aac_rx_check_health(dev)))
 			goto error_iounmap;
+		++restart;
+	}
 	/*
 	 *	Check to see if the board failed any self tests.
 	 */
@@ -556,12 +573,23 @@
 	 */
 	while (!((status = rx_readl(dev, MUnit.OMRx[0])) & KERNEL_UP_AND_RUNNING))
 	{
-		if(time_after(jiffies, start+startup_timeout*HZ))
-		{
+		if ((restart &&
+		  (status & (KERNEL_PANIC|SELF_TEST_FAILED|MONITOR_PANIC))) ||
+		  time_after(jiffies, start+HZ*startup_timeout)) {
 			printk(KERN_ERR "%s%d: adapter kernel failed to start, init status = %lx.\n", 
 					dev->name, instance, status);
 			goto error_iounmap;
 		}
+		if (!restart &&
+		  ((status & (KERNEL_PANIC|SELF_TEST_FAILED|MONITOR_PANIC)) ||
+		  time_after(jiffies, start + HZ *
+		  ((startup_timeout > 60)
+		    ? (startup_timeout - 60)
+		    : (startup_timeout / 2))))) {
+			if (likely(!aac_rx_restart_adapter(dev, aac_rx_check_health(dev))))
+				start = jiffies;
+			++restart;
+		}
 		msleep(1);
 	}
 	/*
@@ -572,6 +600,7 @@
 	dev->a_ops.adapter_notify = aac_rx_notify_adapter;
 	dev->a_ops.adapter_sync_cmd = rx_sync_cmd;
 	dev->a_ops.adapter_check_health = aac_rx_check_health;
+	dev->a_ops.adapter_restart = aac_rx_restart_adapter;
 
 	/*
 	 *	First clear out all interrupts.  Then enable the one's that we
diff --git a/drivers/scsi/aacraid/sa.c b/drivers/scsi/aacraid/sa.c
index 6f1a178..f4b5e97 100644
--- a/drivers/scsi/aacraid/sa.c
+++ b/drivers/scsi/aacraid/sa.c
@@ -31,7 +31,6 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/types.h>
-#include <linux/pci.h>
 #include <linux/spinlock.h>
 #include <linux/slab.h>
 #include <linux/blkdev.h>
diff --git a/drivers/scsi/aha1542.c b/drivers/scsi/aha1542.c
index 1d239f6..cbbfbc9 100644
--- a/drivers/scsi/aha1542.c
+++ b/drivers/scsi/aha1542.c
@@ -35,7 +35,6 @@
 #include <linux/proc_fs.h>
 #include <linux/init.h>
 #include <linux/spinlock.h>
-#include <linux/pci.h>
 #include <linux/isapnp.h>
 #include <linux/blkdev.h>
 #include <linux/mca.h>
diff --git a/drivers/scsi/aic7xxx/Kconfig.aic79xx b/drivers/scsi/aic7xxx/Kconfig.aic79xx
index 911ea17..5e6620f 100644
--- a/drivers/scsi/aic7xxx/Kconfig.aic79xx
+++ b/drivers/scsi/aic7xxx/Kconfig.aic79xx
@@ -57,18 +57,6 @@
 	or modify the assembler Makefile or the files it includes if your
 	build environment is different than that of the author.
 
-config AIC79XX_ENABLE_RD_STRM
-	bool "Enable Read Streaming for All Targets"
-	depends on SCSI_AIC79XX
-	default n
-	help
-	Read Streaming is a U320 protocol option that should enhance
-	performance.  Early U320 drive firmware actually performs slower
-	with read streaming enabled so it is disabled by default.  Read
-	Streaming can be configured in much the same way as tagged queueing
-	using the "rd_strm" command line option.  See
-	drivers/scsi/aic7xxx/README.aic79xx for details.
-
 config AIC79XX_DEBUG_ENABLE
 	bool "Compile in Debugging Code"
 	depends on SCSI_AIC79XX
diff --git a/drivers/scsi/aic7xxx/Kconfig.aic7xxx b/drivers/scsi/aic7xxx/Kconfig.aic7xxx
index cd93f9a..88da670 100644
--- a/drivers/scsi/aic7xxx/Kconfig.aic7xxx
+++ b/drivers/scsi/aic7xxx/Kconfig.aic7xxx
@@ -50,16 +50,6 @@
 
 	Default: 5000 (5 seconds)
 
-config AIC7XXX_PROBE_EISA_VL
-	bool "Probe for EISA and VL AIC7XXX Adapters"
-	depends on SCSI_AIC7XXX && EISA
-	help
-	Probe for EISA and VLB Aic7xxx controllers.  In many newer systems,
-	the invasive probes necessary to detect these controllers can cause
-	other devices to fail.  For this reason, the non-PCI probe code is
-	disabled by default.  The current value of this option can be "toggled"
-	via the no_probe kernel command line option.
-
 config AIC7XXX_BUILD_FIRMWARE
 	bool "Build Adapter Firmware with Kernel Build"
 	depends on SCSI_AIC7XXX && !PREVENT_FIRMWARE_BUILD
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c
index 2be03e9..6054881 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm.c
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.c
@@ -363,6 +363,8 @@
 				 struct scsi_cmnd *);
 static void ahd_linux_setup_tag_info_global(char *p);
 static int  aic79xx_setup(char *c);
+static void ahd_freeze_simq(struct ahd_softc *ahd);
+static void ahd_release_simq(struct ahd_softc *ahd);
 
 static int ahd_linux_unit;
 
@@ -2016,13 +2018,13 @@
 	cmd->scsi_done(cmd);
 }
 
-void
+static void
 ahd_freeze_simq(struct ahd_softc *ahd)
 {
 	scsi_block_requests(ahd->platform_data->host);
 }
 
-void
+static void
 ahd_release_simq(struct ahd_softc *ahd)
 {
 	scsi_unblock_requests(ahd->platform_data->host);
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.h b/drivers/scsi/aic7xxx/aic79xx_osm.h
index 147c83c..9218f29 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm.h
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.h
@@ -837,8 +837,6 @@
 void	ahd_platform_free(struct ahd_softc *ahd);
 void	ahd_platform_init(struct ahd_softc *ahd);
 void	ahd_platform_freeze_devq(struct ahd_softc *ahd, struct scb *scb);
-void	ahd_freeze_simq(struct ahd_softc *ahd);
-void	ahd_release_simq(struct ahd_softc *ahd);
 
 static __inline void
 ahd_freeze_scb(struct scb *scb)
diff --git a/drivers/scsi/aic7xxx/aic7xxx.h b/drivers/scsi/aic7xxx/aic7xxx.h
index 954c7c2..e1bd57b 100644
--- a/drivers/scsi/aic7xxx/aic7xxx.h
+++ b/drivers/scsi/aic7xxx/aic7xxx.h
@@ -1278,11 +1278,6 @@
 	AHC_QUEUE_TAGGED
 } ahc_queue_alg;
 
-void			ahc_set_tags(struct ahc_softc *ahc,
-				     struct scsi_cmnd *cmd,
-				     struct ahc_devinfo *devinfo,
-				     ahc_queue_alg alg);
-
 /**************************** Target Mode *************************************/
 #ifdef AHC_TARGET_MODE
 void		ahc_send_lstate_events(struct ahc_softc *,
diff --git a/drivers/scsi/aic7xxx/aic7xxx_core.c b/drivers/scsi/aic7xxx/aic7xxx_core.c
index 50ef785..75733b0 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_core.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_core.c
@@ -2073,7 +2073,7 @@
 /*
  * Update the current state of tagged queuing for a given target.
  */
-void
+static void
 ahc_set_tags(struct ahc_softc *ahc, struct scsi_cmnd *cmd,
 	     struct ahc_devinfo *devinfo, ahc_queue_alg alg)
 {
diff --git a/drivers/scsi/aic94xx/aic94xx_scb.c b/drivers/scsi/aic94xx/aic94xx_scb.c
index 8f43ff7..db6ab1a 100644
--- a/drivers/scsi/aic94xx/aic94xx_scb.c
+++ b/drivers/scsi/aic94xx/aic94xx_scb.c
@@ -24,7 +24,6 @@
  *
  */
 
-#include <linux/pci.h>
 #include <scsi/scsi_host.h>
 
 #include "aic94xx.h"
diff --git a/drivers/scsi/arcmsr/arcmsr_attr.c b/drivers/scsi/arcmsr/arcmsr_attr.c
index 12497da..03bfed6 100644
--- a/drivers/scsi/arcmsr/arcmsr_attr.c
+++ b/drivers/scsi/arcmsr/arcmsr_attr.c
@@ -49,7 +49,6 @@
 #include <linux/init.h>
 #include <linux/errno.h>
 #include <linux/delay.h>
-#include <linux/pci.h>
 
 #include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_device.h>
diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c
index 0f920c8..eff846a 100644
--- a/drivers/scsi/atari_NCR5380.c
+++ b/drivers/scsi/atari_NCR5380.c
@@ -1,19 +1,19 @@
-/* 
+/*
  * NCR 5380 generic driver routines.  These should make it *trivial*
- * 	to implement 5380 SCSI drivers under Linux with a non-trantor
+ *	to implement 5380 SCSI drivers under Linux with a non-trantor
  *	architecture.
  *
  *	Note that these routines also work with NR53c400 family chips.
  *
  * Copyright 1993, Drew Eckhardt
- *	Visionary Computing 
+ *	Visionary Computing
  *	(Unix and Linux consulting and custom programming)
- * 	drew@colorado.edu
+ *	drew@colorado.edu
  *	+1 (303) 666-5836
  *
- * DISTRIBUTION RELEASE 6. 
+ * DISTRIBUTION RELEASE 6.
  *
- * For more information, please consult 
+ * For more information, please consult
  *
  * NCR 5380 Family
  * SCSI Protocol Controller
@@ -57,7 +57,7 @@
  * - I've deleted all the stuff for AUTOPROBE_IRQ, REAL_DMA_POLL, PSEUDO_DMA
  *    and USLEEP, because these were messing up readability and will never be
  *    needed for Atari SCSI.
- * 
+ *
  * - I've revised the NCR5380_main() calling scheme (relax the 'main_running'
  *   stuff), and 'main' is executed in a bottom half if awoken by an
  *   interrupt.
@@ -69,21 +69,29 @@
  */
 
 /*
- * Further development / testing that should be done : 
- * 1.  Test linked command handling code after Eric is ready with 
+ * Further development / testing that should be done :
+ * 1.  Test linked command handling code after Eric is ready with
  *     the high level code.
  */
 #include <scsi/scsi_dbg.h>
 #include <scsi/scsi_transport_spi.h>
 
 #if (NDEBUG & NDEBUG_LISTS)
-#define LIST(x,y) \
-  { printk("LINE:%d   Adding %p to %p\n", __LINE__, (void*)(x), (void*)(y)); \
-    if ((x)==(y)) udelay(5); }
-#define REMOVE(w,x,y,z) \
-  { printk("LINE:%d   Removing: %p->%p  %p->%p \n", __LINE__, \
-	   (void*)(w), (void*)(x), (void*)(y), (void*)(z)); \
-    if ((x)==(y)) udelay(5); }
+#define LIST(x, y)						\
+	do {							\
+		printk("LINE:%d   Adding %p to %p\n",		\
+		       __LINE__, (void*)(x), (void*)(y));	\
+		if ((x) == (y))					\
+			udelay(5);				\
+	} while (0)
+#define REMOVE(w, x, y, z)					\
+	do {							\
+		printk("LINE:%d   Removing: %p->%p  %p->%p \n",	\
+		       __LINE__, (void*)(w), (void*)(x),	\
+		       (void*)(y), (void*)(z));			\
+		if ((x) == (y))					\
+			udelay(5);				\
+	} while (0)
 #else
 #define LIST(x,y)
 #define REMOVE(w,x,y,z)
@@ -103,62 +111,62 @@
  * more difficult than it has to be.
  *
  * Also, many of the SCSI drivers were written before the command queuing
- * routines were implemented, meaning their implementations of queued 
+ * routines were implemented, meaning their implementations of queued
  * commands were hacked on rather than designed in from the start.
  *
- * When I designed the Linux SCSI drivers I figured that 
+ * When I designed the Linux SCSI drivers I figured that
  * while having two different SCSI boards in a system might be useful
  * for debugging things, two of the same type wouldn't be used.
  * Well, I was wrong and a number of users have mailed me about running
  * multiple high-performance SCSI boards in a server.
  *
- * Finally, when I get questions from users, I have no idea what 
+ * Finally, when I get questions from users, I have no idea what
  * revision of my driver they are running.
  *
  * This driver attempts to address these problems :
- * This is a generic 5380 driver.  To use it on a different platform, 
+ * This is a generic 5380 driver.  To use it on a different platform,
  * one simply writes appropriate system specific macros (ie, data
- * transfer - some PC's will use the I/O bus, 68K's must use 
+ * transfer - some PC's will use the I/O bus, 68K's must use
  * memory mapped) and drops this file in their 'C' wrapper.
  *
- * As far as command queueing, two queues are maintained for 
+ * As far as command queueing, two queues are maintained for
  * each 5380 in the system - commands that haven't been issued yet,
- * and commands that are currently executing.  This means that an 
- * unlimited number of commands may be queued, letting 
- * more commands propagate from the higher driver levels giving higher 
- * throughput.  Note that both I_T_L and I_T_L_Q nexuses are supported, 
- * allowing multiple commands to propagate all the way to a SCSI-II device 
+ * and commands that are currently executing.  This means that an
+ * unlimited number of commands may be queued, letting
+ * more commands propagate from the higher driver levels giving higher
+ * throughput.  Note that both I_T_L and I_T_L_Q nexuses are supported,
+ * allowing multiple commands to propagate all the way to a SCSI-II device
  * while a command is already executing.
  *
- * To solve the multiple-boards-in-the-same-system problem, 
+ * To solve the multiple-boards-in-the-same-system problem,
  * there is a separate instance structure for each instance
  * of a 5380 in the system.  So, multiple NCR5380 drivers will
  * be able to coexist with appropriate changes to the high level
- * SCSI code.  
+ * SCSI code.
  *
  * A NCR5380_PUBLIC_REVISION macro is provided, with the release
- * number (updated for each public release) printed by the 
- * NCR5380_print_options command, which should be called from the 
+ * number (updated for each public release) printed by the
+ * NCR5380_print_options command, which should be called from the
  * wrapper detect function, so that I know what release of the driver
  * users are using.
  *
- * Issues specific to the NCR5380 : 
+ * Issues specific to the NCR5380 :
  *
- * When used in a PIO or pseudo-dma mode, the NCR5380 is a braindead 
- * piece of hardware that requires you to sit in a loop polling for 
- * the REQ signal as long as you are connected.  Some devices are 
- * brain dead (ie, many TEXEL CD ROM drives) and won't disconnect 
+ * When used in a PIO or pseudo-dma mode, the NCR5380 is a braindead
+ * piece of hardware that requires you to sit in a loop polling for
+ * the REQ signal as long as you are connected.  Some devices are
+ * brain dead (ie, many TEXEL CD ROM drives) and won't disconnect
  * while doing long seek operations.
- * 
+ *
  * The workaround for this is to keep track of devices that have
  * disconnected.  If the device hasn't disconnected, for commands that
- * should disconnect, we do something like 
+ * should disconnect, we do something like
  *
  * while (!REQ is asserted) { sleep for N usecs; poll for M usecs }
- * 
- * Some tweaking of N and M needs to be done.  An algorithm based 
+ *
+ * Some tweaking of N and M needs to be done.  An algorithm based
  * on "time to data" would give the best results as long as short time
- * to datas (ie, on the same track) were considered, however these 
+ * to datas (ie, on the same track) were considered, however these
  * broken devices are the exception rather than the rule and I'd rather
  * spend my time optimizing for the normal case.
  *
@@ -167,9 +175,9 @@
  * At the heart of the design is a coroutine, NCR5380_main,
  * which is started when not running by the interrupt handler,
  * timer, and queue command function.  It attempts to establish
- * I_T_L or I_T_L_Q nexuses by removing the commands from the 
- * issue queue and calling NCR5380_select() if a nexus 
- * is not established. 
+ * I_T_L or I_T_L_Q nexuses by removing the commands from the
+ * issue queue and calling NCR5380_select() if a nexus
+ * is not established.
  *
  * Once a nexus is established, the NCR5380_information_transfer()
  * phase goes through the various phases as instructed by the target.
@@ -183,10 +191,10 @@
  * calling NCR5380_intr()  which will in turn call NCR5380_reselect
  * to reestablish a nexus.  This will run main if necessary.
  *
- * On command termination, the done function will be called as 
+ * On command termination, the done function will be called as
  * appropriate.
  *
- * SCSI pointers are maintained in the SCp field of SCSI command 
+ * SCSI pointers are maintained in the SCp field of SCSI command
  * structures, being initialized after the command is connected
  * in NCR5380_select, and set as appropriate in NCR5380_information_transfer.
  * Note that in violation of the standard, an implicit SAVE POINTERS operation
@@ -196,12 +204,12 @@
 /*
  * Using this file :
  * This file a skeleton Linux SCSI driver for the NCR 5380 series
- * of chips.  To use it, you write an architecture specific functions 
+ * of chips.  To use it, you write an architecture specific functions
  * and macros and include this file in your driver.
  *
- * These macros control options : 
+ * These macros control options :
  * AUTOSENSE - if defined, REQUEST SENSE will be performed automatically
- *	for commands that return with a CHECK CONDITION status. 
+ *	for commands that return with a CHECK CONDITION status.
  *
  * LINKED - if defined, linked commands are supported.
  *
@@ -210,18 +218,18 @@
  * SUPPORT_TAGS - if defined, SCSI-2 tagged queuing is used where possible
  *
  * These macros MUST be defined :
- * 
+ *
  * NCR5380_read(register)  - read from the specified register
  *
- * NCR5380_write(register, value) - write to the specific register 
+ * NCR5380_write(register, value) - write to the specific register
  *
  * Either real DMA *or* pseudo DMA may be implemented
- * REAL functions : 
+ * REAL functions :
  * NCR5380_REAL_DMA should be defined if real DMA is to be used.
- * Note that the DMA setup functions should return the number of bytes 
+ * Note that the DMA setup functions should return the number of bytes
  *	that they were able to program the controller for.
  *
- * Also note that generic i386/PC versions of these macros are 
+ * Also note that generic i386/PC versions of these macros are
  *	available as NCR5380_i386_dma_write_setup,
  *	NCR5380_i386_dma_read_setup, and NCR5380_i386_dma_residual.
  *
@@ -234,14 +242,14 @@
  * NCR5380_pread(instance, dst, count);
  *
  * If nothing specific to this implementation needs doing (ie, with external
- * hardware), you must also define 
- *  
+ * hardware), you must also define
+ *
  * NCR5380_queue_command
  * NCR5380_reset
  * NCR5380_abort
  * NCR5380_proc_info
  *
- * to be the global entry points into the specific driver, ie 
+ * to be the global entry points into the specific driver, ie
  * #define NCR5380_queue_command t128_queue_command.
  *
  * If this is not done, the routines will be defined as static functions
@@ -249,7 +257,7 @@
  * accessible wrapper function.
  *
  * The generic driver is initialized by calling NCR5380_init(instance),
- * after setting the appropriate host specific fields and ID.  If the 
+ * after setting the appropriate host specific fields and ID.  If the
  * driver wishes to autoprobe for an IRQ line, the NCR5380_probe_irq(instance,
  * possible) function may be used.  Before the specific driver initialization
  * code finishes, NCR5380_print_options should be called.
@@ -264,8 +272,9 @@
 	(struct NCR5380_hostdata *)(in)->hostdata
 #define	HOSTDATA(in) ((struct NCR5380_hostdata *)(in)->hostdata)
 
-#define	NEXT(cmd)	((Scsi_Cmnd *)((cmd)->host_scribble))
-#define	NEXTADDR(cmd)	((Scsi_Cmnd **)&((cmd)->host_scribble))
+#define	NEXT(cmd)		((Scsi_Cmnd *)(cmd)->host_scribble)
+#define	SET_NEXT(cmd,next)	((cmd)->host_scribble = (void *)(next))
+#define	NEXTADDR(cmd)		((Scsi_Cmnd **)&(cmd)->host_scribble)
 
 #define	HOSTNO		instance->host_no
 #define	H_NO(cmd)	(cmd)->device->host->host_no
@@ -312,34 +321,34 @@
 #define TAG_NONE 0xff
 
 typedef struct {
-    DECLARE_BITMAP(allocated, MAX_TAGS);
-    int		nr_allocated;
-    int		queue_size;
+	DECLARE_BITMAP(allocated, MAX_TAGS);
+	int nr_allocated;
+	int queue_size;
 } TAG_ALLOC;
 
-static TAG_ALLOC TagAlloc[8][8]; /* 8 targets and 8 LUNs */
+static TAG_ALLOC TagAlloc[8][8];	/* 8 targets and 8 LUNs */
 
 
-static void __init init_tags( void )
+static void __init init_tags(void)
 {
-    int target, lun;
-    TAG_ALLOC *ta;
-    
-    if (!setup_use_tagged_queuing)
-	return;
-    
-    for( target = 0; target < 8; ++target ) {
-	for( lun = 0; lun < 8; ++lun ) {
-	    ta = &TagAlloc[target][lun];
-	    bitmap_zero(ta->allocated, MAX_TAGS);
-	    ta->nr_allocated = 0;
-	    /* At the beginning, assume the maximum queue size we could
-	     * support (MAX_TAGS). This value will be decreased if the target
-	     * returns QUEUE_FULL status.
-	     */
-	    ta->queue_size = MAX_TAGS;
+	int target, lun;
+	TAG_ALLOC *ta;
+
+	if (!setup_use_tagged_queuing)
+		return;
+
+	for (target = 0; target < 8; ++target) {
+		for (lun = 0; lun < 8; ++lun) {
+			ta = &TagAlloc[target][lun];
+			bitmap_zero(ta->allocated, MAX_TAGS);
+			ta->nr_allocated = 0;
+			/* At the beginning, assume the maximum queue size we could
+			 * support (MAX_TAGS). This value will be decreased if the target
+			 * returns QUEUE_FULL status.
+			 */
+			ta->queue_size = MAX_TAGS;
+		}
 	}
-    }
 }
 
 
@@ -348,24 +357,24 @@
  * check that there is a free tag and the target's queue won't overflow. This
  * function should be called with interrupts disabled to avoid race
  * conditions.
- */ 
+ */
 
-static int is_lun_busy( Scsi_Cmnd *cmd, int should_be_tagged )
+static int is_lun_busy(Scsi_Cmnd *cmd, int should_be_tagged)
 {
-    SETUP_HOSTDATA(cmd->device->host);
+	SETUP_HOSTDATA(cmd->device->host);
 
-    if (hostdata->busy[cmd->device->id] & (1 << cmd->device->lun))
-	return( 1 );
-    if (!should_be_tagged ||
-	!setup_use_tagged_queuing || !cmd->device->tagged_supported)
-	return( 0 );
-    if (TagAlloc[cmd->device->id][cmd->device->lun].nr_allocated >=
-	TagAlloc[cmd->device->id][cmd->device->lun].queue_size ) {
-	TAG_PRINTK( "scsi%d: target %d lun %d: no free tags\n",
-		    H_NO(cmd), cmd->device->id, cmd->device->lun );
-	return( 1 );
-    }
-    return( 0 );
+	if (hostdata->busy[cmd->device->id] & (1 << cmd->device->lun))
+		return 1;
+	if (!should_be_tagged ||
+	    !setup_use_tagged_queuing || !cmd->device->tagged_supported)
+		return 0;
+	if (TagAlloc[cmd->device->id][cmd->device->lun].nr_allocated >=
+	    TagAlloc[cmd->device->id][cmd->device->lun].queue_size) {
+		TAG_PRINTK("scsi%d: target %d lun %d: no free tags\n",
+			   H_NO(cmd), cmd->device->id, cmd->device->lun);
+		return 1;
+	}
+	return 0;
 }
 
 
@@ -374,31 +383,30 @@
  * untagged.
  */
 
-static void cmd_get_tag( Scsi_Cmnd *cmd, int should_be_tagged )
+static void cmd_get_tag(Scsi_Cmnd *cmd, int should_be_tagged)
 {
-    SETUP_HOSTDATA(cmd->device->host);
+	SETUP_HOSTDATA(cmd->device->host);
 
-    /* If we or the target don't support tagged queuing, allocate the LUN for
-     * an untagged command.
-     */
-    if (!should_be_tagged ||
-	!setup_use_tagged_queuing || !cmd->device->tagged_supported) {
-	cmd->tag = TAG_NONE;
-	hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun);
-	TAG_PRINTK( "scsi%d: target %d lun %d now allocated by untagged "
-		    "command\n", H_NO(cmd), cmd->device->id, cmd->device->lun );
-    }
-    else {
-	TAG_ALLOC *ta = &TagAlloc[cmd->device->id][cmd->device->lun];
+	/* If we or the target don't support tagged queuing, allocate the LUN for
+	 * an untagged command.
+	 */
+	if (!should_be_tagged ||
+	    !setup_use_tagged_queuing || !cmd->device->tagged_supported) {
+		cmd->tag = TAG_NONE;
+		hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun);
+		TAG_PRINTK("scsi%d: target %d lun %d now allocated by untagged "
+			   "command\n", H_NO(cmd), cmd->device->id, cmd->device->lun);
+	} else {
+		TAG_ALLOC *ta = &TagAlloc[cmd->device->id][cmd->device->lun];
 
-	cmd->tag = find_first_zero_bit( ta->allocated, MAX_TAGS );
-	set_bit( cmd->tag, ta->allocated );
-	ta->nr_allocated++;
-	TAG_PRINTK( "scsi%d: using tag %d for target %d lun %d "
-		    "(now %d tags in use)\n",
-		    H_NO(cmd), cmd->tag, cmd->device->id, cmd->device->lun,
-		    ta->nr_allocated );
-    }
+		cmd->tag = find_first_zero_bit(ta->allocated, MAX_TAGS);
+		set_bit(cmd->tag, ta->allocated);
+		ta->nr_allocated++;
+		TAG_PRINTK("scsi%d: using tag %d for target %d lun %d "
+			   "(now %d tags in use)\n",
+			   H_NO(cmd), cmd->tag, cmd->device->id,
+			   cmd->device->lun, ta->nr_allocated);
+	}
 }
 
 
@@ -406,44 +414,42 @@
  * unlock the LUN.
  */
 
-static void cmd_free_tag( Scsi_Cmnd *cmd )
+static void cmd_free_tag(Scsi_Cmnd *cmd)
 {
-    SETUP_HOSTDATA(cmd->device->host);
+	SETUP_HOSTDATA(cmd->device->host);
 
-    if (cmd->tag == TAG_NONE) {
-	hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun);
-	TAG_PRINTK( "scsi%d: target %d lun %d untagged cmd finished\n",
-		    H_NO(cmd), cmd->device->id, cmd->device->lun );
-    }
-    else if (cmd->tag >= MAX_TAGS) {
-	printk(KERN_NOTICE "scsi%d: trying to free bad tag %d!\n",
-		H_NO(cmd), cmd->tag );
-    }
-    else {
-	TAG_ALLOC *ta = &TagAlloc[cmd->device->id][cmd->device->lun];
-	clear_bit( cmd->tag, ta->allocated );
-	ta->nr_allocated--;
-	TAG_PRINTK( "scsi%d: freed tag %d for target %d lun %d\n",
-		    H_NO(cmd), cmd->tag, cmd->device->id, cmd->device->lun );
-    }
+	if (cmd->tag == TAG_NONE) {
+		hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun);
+		TAG_PRINTK("scsi%d: target %d lun %d untagged cmd finished\n",
+			   H_NO(cmd), cmd->device->id, cmd->device->lun);
+	} else if (cmd->tag >= MAX_TAGS) {
+		printk(KERN_NOTICE "scsi%d: trying to free bad tag %d!\n",
+		       H_NO(cmd), cmd->tag);
+	} else {
+		TAG_ALLOC *ta = &TagAlloc[cmd->device->id][cmd->device->lun];
+		clear_bit(cmd->tag, ta->allocated);
+		ta->nr_allocated--;
+		TAG_PRINTK("scsi%d: freed tag %d for target %d lun %d\n",
+			   H_NO(cmd), cmd->tag, cmd->device->id, cmd->device->lun);
+	}
 }
 
 
-static void free_all_tags( void )
+static void free_all_tags(void)
 {
-    int target, lun;
-    TAG_ALLOC *ta;
+	int target, lun;
+	TAG_ALLOC *ta;
 
-    if (!setup_use_tagged_queuing)
-	return;
-    
-    for( target = 0; target < 8; ++target ) {
-	for( lun = 0; lun < 8; ++lun ) {
-	    ta = &TagAlloc[target][lun];
-	    bitmap_zero(ta->allocated, MAX_TAGS);
-	    ta->nr_allocated = 0;
+	if (!setup_use_tagged_queuing)
+		return;
+
+	for (target = 0; target < 8; ++target) {
+		for (lun = 0; lun < 8; ++lun) {
+			ta = &TagAlloc[target][lun];
+			bitmap_zero(ta->allocated, MAX_TAGS);
+			ta->nr_allocated = 0;
+		}
 	}
-    }
 }
 
 #endif /* SUPPORT_TAGS */
@@ -461,89 +467,94 @@
  *    assumed to be already transfered into ptr/this_residual.
  */
 
-static void merge_contiguous_buffers( Scsi_Cmnd *cmd )
+static void merge_contiguous_buffers(Scsi_Cmnd *cmd)
 {
-    unsigned long endaddr;
+	unsigned long endaddr;
 #if (NDEBUG & NDEBUG_MERGING)
-    unsigned long oldlen = cmd->SCp.this_residual;
-    int		  cnt = 1;
+	unsigned long oldlen = cmd->SCp.this_residual;
+	int cnt = 1;
 #endif
 
-    for (endaddr = virt_to_phys(cmd->SCp.ptr + cmd->SCp.this_residual - 1) + 1;
-	 cmd->SCp.buffers_residual &&
-	 virt_to_phys(page_address(cmd->SCp.buffer[1].page)+
-		      cmd->SCp.buffer[1].offset) == endaddr; ) {
-	MER_PRINTK("VTOP(%p) == %08lx -> merging\n",
-		   cmd->SCp.buffer[1].address, endaddr);
+	for (endaddr = virt_to_phys(cmd->SCp.ptr + cmd->SCp.this_residual - 1) + 1;
+	     cmd->SCp.buffers_residual &&
+	     virt_to_phys(page_address(cmd->SCp.buffer[1].page) +
+			  cmd->SCp.buffer[1].offset) == endaddr;) {
+		MER_PRINTK("VTOP(%p) == %08lx -> merging\n",
+			   page_address(cmd->SCp.buffer[1].page), endaddr);
 #if (NDEBUG & NDEBUG_MERGING)
-	++cnt;
+		++cnt;
 #endif
-	++cmd->SCp.buffer;
-	--cmd->SCp.buffers_residual;
-	cmd->SCp.this_residual += cmd->SCp.buffer->length;
-	endaddr += cmd->SCp.buffer->length;
-    }
+		++cmd->SCp.buffer;
+		--cmd->SCp.buffers_residual;
+		cmd->SCp.this_residual += cmd->SCp.buffer->length;
+		endaddr += cmd->SCp.buffer->length;
+	}
 #if (NDEBUG & NDEBUG_MERGING)
-    if (oldlen != cmd->SCp.this_residual)
-	MER_PRINTK("merged %d buffers from %p, new length %08x\n",
-		   cnt, cmd->SCp.ptr, cmd->SCp.this_residual);
+	if (oldlen != cmd->SCp.this_residual)
+		MER_PRINTK("merged %d buffers from %p, new length %08x\n",
+			   cnt, cmd->SCp.ptr, cmd->SCp.this_residual);
 #endif
 }
 
 /*
  * Function : void initialize_SCp(Scsi_Cmnd *cmd)
  *
- * Purpose : initialize the saved data pointers for cmd to point to the 
+ * Purpose : initialize the saved data pointers for cmd to point to the
  *	start of the buffer.
  *
  * Inputs : cmd - Scsi_Cmnd structure to have pointers reset.
  */
 
-static __inline__ void initialize_SCp(Scsi_Cmnd *cmd)
+static inline void initialize_SCp(Scsi_Cmnd *cmd)
 {
-    /* 
-     * Initialize the Scsi Pointer field so that all of the commands in the 
-     * various queues are valid.
-     */
-
-    if (cmd->use_sg) {
-	cmd->SCp.buffer = (struct scatterlist *) cmd->request_buffer;
-	cmd->SCp.buffers_residual = cmd->use_sg - 1;
-	cmd->SCp.ptr = (char *)page_address(cmd->SCp.buffer->page)+
-		       cmd->SCp.buffer->offset;
-	cmd->SCp.this_residual = cmd->SCp.buffer->length;
-	/* ++roman: Try to merge some scatter-buffers if they are at
-	 * contiguous physical addresses.
+	/*
+	 * Initialize the Scsi Pointer field so that all of the commands in the
+	 * various queues are valid.
 	 */
-	merge_contiguous_buffers( cmd );
-    } else {
-	cmd->SCp.buffer = NULL;
-	cmd->SCp.buffers_residual = 0;
-	cmd->SCp.ptr = (char *) cmd->request_buffer;
-	cmd->SCp.this_residual = cmd->request_bufflen;
-    }
+
+	if (cmd->use_sg) {
+		cmd->SCp.buffer = (struct scatterlist *)cmd->request_buffer;
+		cmd->SCp.buffers_residual = cmd->use_sg - 1;
+		cmd->SCp.ptr = (char *)page_address(cmd->SCp.buffer->page) +
+			       cmd->SCp.buffer->offset;
+		cmd->SCp.this_residual = cmd->SCp.buffer->length;
+		/* ++roman: Try to merge some scatter-buffers if they are at
+		 * contiguous physical addresses.
+		 */
+		merge_contiguous_buffers(cmd);
+	} else {
+		cmd->SCp.buffer = NULL;
+		cmd->SCp.buffers_residual = 0;
+		cmd->SCp.ptr = (char *)cmd->request_buffer;
+		cmd->SCp.this_residual = cmd->request_bufflen;
+	}
 }
 
 #include <linux/delay.h>
 
 #if NDEBUG
 static struct {
-    unsigned char mask;
-    const char * name;} 
-signals[] = {{ SR_DBP, "PARITY"}, { SR_RST, "RST" }, { SR_BSY, "BSY" }, 
-    { SR_REQ, "REQ" }, { SR_MSG, "MSG" }, { SR_CD,  "CD" }, { SR_IO, "IO" }, 
-    { SR_SEL, "SEL" }, {0, NULL}}, 
-basrs[] = {{BASR_ATN, "ATN"}, {BASR_ACK, "ACK"}, {0, NULL}},
-icrs[] = {{ICR_ASSERT_RST, "ASSERT RST"},{ICR_ASSERT_ACK, "ASSERT ACK"},
-    {ICR_ASSERT_BSY, "ASSERT BSY"}, {ICR_ASSERT_SEL, "ASSERT SEL"}, 
-    {ICR_ASSERT_ATN, "ASSERT ATN"}, {ICR_ASSERT_DATA, "ASSERT DATA"}, 
-    {0, NULL}},
-mrs[] = {{MR_BLOCK_DMA_MODE, "MODE BLOCK DMA"}, {MR_TARGET, "MODE TARGET"}, 
-    {MR_ENABLE_PAR_CHECK, "MODE PARITY CHECK"}, {MR_ENABLE_PAR_INTR, 
-    "MODE PARITY INTR"}, {MR_ENABLE_EOP_INTR,"MODE EOP INTR"},
-    {MR_MONITOR_BSY, "MODE MONITOR BSY"},
-    {MR_DMA_MODE, "MODE DMA"}, {MR_ARBITRATE, "MODE ARBITRATION"}, 
-    {0, NULL}};
+	unsigned char mask;
+	const char *name;
+} signals[] = {
+	{ SR_DBP, "PARITY"}, { SR_RST, "RST" }, { SR_BSY, "BSY" },
+	{ SR_REQ, "REQ" }, { SR_MSG, "MSG" }, { SR_CD,  "CD" }, { SR_IO, "IO" },
+	{ SR_SEL, "SEL" }, {0, NULL}
+}, basrs[] = {
+	{BASR_ATN, "ATN"}, {BASR_ACK, "ACK"}, {0, NULL}
+}, icrs[] = {
+	{ICR_ASSERT_RST, "ASSERT RST"},{ICR_ASSERT_ACK, "ASSERT ACK"},
+	{ICR_ASSERT_BSY, "ASSERT BSY"}, {ICR_ASSERT_SEL, "ASSERT SEL"},
+	{ICR_ASSERT_ATN, "ASSERT ATN"}, {ICR_ASSERT_DATA, "ASSERT DATA"},
+	{0, NULL}
+}, mrs[] = {
+	{MR_BLOCK_DMA_MODE, "MODE BLOCK DMA"}, {MR_TARGET, "MODE TARGET"},
+	{MR_ENABLE_PAR_CHECK, "MODE PARITY CHECK"}, {MR_ENABLE_PAR_INTR,
+	"MODE PARITY INTR"}, {MR_ENABLE_EOP_INTR,"MODE EOP INTR"},
+	{MR_MONITOR_BSY, "MODE MONITOR BSY"},
+	{MR_DMA_MODE, "MODE DMA"}, {MR_ARBITRATE, "MODE ARBITRATION"},
+	{0, NULL}
+};
 
 /*
  * Function : void NCR5380_print(struct Scsi_Host *instance)
@@ -553,45 +564,47 @@
  * Input : instance - which NCR5380
  */
 
-static void NCR5380_print(struct Scsi_Host *instance) {
-    unsigned char status, data, basr, mr, icr, i;
-    unsigned long flags;
+static void NCR5380_print(struct Scsi_Host *instance)
+{
+	unsigned char status, data, basr, mr, icr, i;
+	unsigned long flags;
 
-    local_irq_save(flags);
-    data = NCR5380_read(CURRENT_SCSI_DATA_REG);
-    status = NCR5380_read(STATUS_REG);
-    mr = NCR5380_read(MODE_REG);
-    icr = NCR5380_read(INITIATOR_COMMAND_REG);
-    basr = NCR5380_read(BUS_AND_STATUS_REG);
-    local_irq_restore(flags);
-    printk("STATUS_REG: %02x ", status);
-    for (i = 0; signals[i].mask ; ++i) 
-	if (status & signals[i].mask)
-	    printk(",%s", signals[i].name);
-    printk("\nBASR: %02x ", basr);
-    for (i = 0; basrs[i].mask ; ++i) 
-	if (basr & basrs[i].mask)
-	    printk(",%s", basrs[i].name);
-    printk("\nICR: %02x ", icr);
-    for (i = 0; icrs[i].mask; ++i) 
-	if (icr & icrs[i].mask)
-	    printk(",%s", icrs[i].name);
-    printk("\nMODE: %02x ", mr);
-    for (i = 0; mrs[i].mask; ++i) 
-	if (mr & mrs[i].mask)
-	    printk(",%s", mrs[i].name);
-    printk("\n");
+	local_irq_save(flags);
+	data = NCR5380_read(CURRENT_SCSI_DATA_REG);
+	status = NCR5380_read(STATUS_REG);
+	mr = NCR5380_read(MODE_REG);
+	icr = NCR5380_read(INITIATOR_COMMAND_REG);
+	basr = NCR5380_read(BUS_AND_STATUS_REG);
+	local_irq_restore(flags);
+	printk("STATUS_REG: %02x ", status);
+	for (i = 0; signals[i].mask; ++i)
+		if (status & signals[i].mask)
+			printk(",%s", signals[i].name);
+	printk("\nBASR: %02x ", basr);
+	for (i = 0; basrs[i].mask; ++i)
+		if (basr & basrs[i].mask)
+			printk(",%s", basrs[i].name);
+	printk("\nICR: %02x ", icr);
+	for (i = 0; icrs[i].mask; ++i)
+		if (icr & icrs[i].mask)
+			printk(",%s", icrs[i].name);
+	printk("\nMODE: %02x ", mr);
+	for (i = 0; mrs[i].mask; ++i)
+		if (mr & mrs[i].mask)
+			printk(",%s", mrs[i].name);
+	printk("\n");
 }
 
 static struct {
-    unsigned char value;
-    const char *name;
+	unsigned char value;
+	const char *name;
 } phases[] = {
-    {PHASE_DATAOUT, "DATAOUT"}, {PHASE_DATAIN, "DATAIN"}, {PHASE_CMDOUT, "CMDOUT"},
-    {PHASE_STATIN, "STATIN"}, {PHASE_MSGOUT, "MSGOUT"}, {PHASE_MSGIN, "MSGIN"},
-    {PHASE_UNKNOWN, "UNKNOWN"}};
+	{PHASE_DATAOUT, "DATAOUT"}, {PHASE_DATAIN, "DATAIN"}, {PHASE_CMDOUT, "CMDOUT"},
+	{PHASE_STATIN, "STATIN"}, {PHASE_MSGOUT, "MSGOUT"}, {PHASE_MSGIN, "MSGIN"},
+	{PHASE_UNKNOWN, "UNKNOWN"}
+};
 
-/* 
+/*
  * Function : void NCR5380_print_phase(struct Scsi_Host *instance)
  *
  * Purpose : print the current SCSI phase for debugging purposes
@@ -601,30 +614,35 @@
 
 static void NCR5380_print_phase(struct Scsi_Host *instance)
 {
-    unsigned char status;
-    int i;
+	unsigned char status;
+	int i;
 
-    status = NCR5380_read(STATUS_REG);
-    if (!(status & SR_REQ)) 
-	printk(KERN_DEBUG "scsi%d: REQ not asserted, phase unknown.\n", HOSTNO);
-    else {
-	for (i = 0; (phases[i].value != PHASE_UNKNOWN) && 
-	    (phases[i].value != (status & PHASE_MASK)); ++i); 
-	printk(KERN_DEBUG "scsi%d: phase %s\n", HOSTNO, phases[i].name);
-    }
+	status = NCR5380_read(STATUS_REG);
+	if (!(status & SR_REQ))
+		printk(KERN_DEBUG "scsi%d: REQ not asserted, phase unknown.\n", HOSTNO);
+	else {
+		for (i = 0; (phases[i].value != PHASE_UNKNOWN) &&
+		     (phases[i].value != (status & PHASE_MASK)); ++i)
+			;
+		printk(KERN_DEBUG "scsi%d: phase %s\n", HOSTNO, phases[i].name);
+	}
 }
 
 #else /* !NDEBUG */
 
 /* dummies... */
-__inline__ void NCR5380_print(struct Scsi_Host *instance) { };
-__inline__ void NCR5380_print_phase(struct Scsi_Host *instance) { };
+static inline void NCR5380_print(struct Scsi_Host *instance)
+{
+};
+static inline void NCR5380_print_phase(struct Scsi_Host *instance)
+{
+};
 
 #endif
 
 /*
  * ++roman: New scheme of calling NCR5380_main()
- * 
+ *
  * If we're not in an interrupt, we can call our main directly, it cannot be
  * already running. Else, we queue it on a task queue, if not 'main_running'
  * tells us that a lower level is already executing it. This way,
@@ -638,33 +656,33 @@
 #include <linux/workqueue.h>
 #include <linux/interrupt.h>
 
-static volatile int main_running = 0;
-static DECLARE_WORK(NCR5380_tqueue, (void (*)(void*))NCR5380_main, NULL);
+static volatile int main_running;
+static DECLARE_WORK(NCR5380_tqueue, NCR5380_main);
 
-static __inline__ void queue_main(void)
+static inline void queue_main(void)
 {
-    if (!main_running) {
-	/* If in interrupt and NCR5380_main() not already running,
-	   queue it on the 'immediate' task queue, to be processed
-	   immediately after the current interrupt processing has
-	   finished. */
-	schedule_work(&NCR5380_tqueue);
-    }
-    /* else: nothing to do: the running NCR5380_main() will pick up
-       any newly queued command. */
+	if (!main_running) {
+		/* If in interrupt and NCR5380_main() not already running,
+		   queue it on the 'immediate' task queue, to be processed
+		   immediately after the current interrupt processing has
+		   finished. */
+		schedule_work(&NCR5380_tqueue);
+	}
+	/* else: nothing to do: the running NCR5380_main() will pick up
+	   any newly queued command. */
 }
 
 
-static inline void NCR5380_all_init (void)
+static inline void NCR5380_all_init(void)
 {
-    static int done = 0;
-    if (!done) {
-	INI_PRINTK("scsi : NCR5380_all_init()\n");
-	done = 1;
-    }
+	static int done = 0;
+	if (!done) {
+		INI_PRINTK("scsi : NCR5380_all_init()\n");
+		done = 1;
+	}
 }
 
- 
+
 /*
  * Function : void NCR58380_print_options (struct Scsi_Host *instance)
  *
@@ -674,23 +692,23 @@
  * Inputs : instance, pointer to this instance.  Unused.
  */
 
-static void __init NCR5380_print_options (struct Scsi_Host *instance)
+static void __init NCR5380_print_options(struct Scsi_Host *instance)
 {
-    printk(" generic options"
-#ifdef AUTOSENSE 
-    " AUTOSENSE"
+	printk(" generic options"
+#ifdef AUTOSENSE
+	       " AUTOSENSE"
 #endif
 #ifdef REAL_DMA
-    " REAL DMA"
+	       " REAL DMA"
 #endif
 #ifdef PARITY
-    " PARITY"
+	       " PARITY"
 #endif
 #ifdef SUPPORT_TAGS
-    " SCSI-2 TAGGED QUEUING"
+	       " SCSI-2 TAGGED QUEUING"
 #endif
-    );
-    printk(" generic release=%d", NCR5380_PUBLIC_RELEASE);
+	       );
+	printk(" generic release=%d", NCR5380_PUBLIC_RELEASE);
 }
 
 /*
@@ -699,27 +717,27 @@
  * Purpose : print commands in the various queues, called from
  *	NCR5380_abort and NCR5380_debug to aid debugging.
  *
- * Inputs : instance, pointer to this instance.  
+ * Inputs : instance, pointer to this instance.
  */
 
-static void NCR5380_print_status (struct Scsi_Host *instance)
+static void NCR5380_print_status(struct Scsi_Host *instance)
 {
-    char *pr_bfr;
-    char *start;
-    int len;
+	char *pr_bfr;
+	char *start;
+	int len;
 
-    NCR_PRINT(NDEBUG_ANY);
-    NCR_PRINT_PHASE(NDEBUG_ANY);
+	NCR_PRINT(NDEBUG_ANY);
+	NCR_PRINT_PHASE(NDEBUG_ANY);
 
-    pr_bfr = (char *) __get_free_page(GFP_ATOMIC);
-    if (!pr_bfr) {
-	printk("NCR5380_print_status: no memory for print buffer\n");
-	return;
-    }
-    len = NCR5380_proc_info(pr_bfr, &start, 0, PAGE_SIZE, HOSTNO, 0);
-    pr_bfr[len] = 0;
-    printk("\n%s\n", pr_bfr);
-    free_page((unsigned long) pr_bfr);
+	pr_bfr = (char *)__get_free_page(GFP_ATOMIC);
+	if (!pr_bfr) {
+		printk("NCR5380_print_status: no memory for print buffer\n");
+		return;
+	}
+	len = NCR5380_proc_info(instance, pr_bfr, &start, 0, PAGE_SIZE, 0);
+	pr_bfr[len] = 0;
+	printk("\n%s\n", pr_bfr);
+	free_page((unsigned long)pr_bfr);
 }
 
 
@@ -738,443 +756,478 @@
 */
 
 #undef SPRINTF
-#define SPRINTF(fmt,args...) \
-  do { if (pos + strlen(fmt) + 20 /* slop */ < buffer + length) \
-	 pos += sprintf(pos, fmt , ## args); } while(0)
-static
-char *lprint_Scsi_Cmnd (Scsi_Cmnd *cmd, char *pos, char *buffer, int length);
+#define SPRINTF(fmt,args...)							\
+	do {									\
+		if (pos + strlen(fmt) + 20 /* slop */ < buffer + length)	\
+			pos += sprintf(pos, fmt , ## args);			\
+	} while(0)
+static char *lprint_Scsi_Cmnd(Scsi_Cmnd *cmd, char *pos, char *buffer, int length);
 
-static
-int NCR5380_proc_info (struct Scsi_Host *instance, char *buffer, char **start, off_t offset,
-		       int length, int inout)
+static int NCR5380_proc_info(struct Scsi_Host *instance, char *buffer,
+			     char **start, off_t offset, int length, int inout)
 {
-    char *pos = buffer;
-    struct NCR5380_hostdata *hostdata;
-    Scsi_Cmnd *ptr;
-    unsigned long flags;
-    off_t begin = 0;
-#define check_offset()				\
-    do {					\
-	if (pos - buffer < offset - begin) {	\
-	    begin += pos - buffer;		\
-	    pos = buffer;			\
-	}					\
-    } while (0)
+	char *pos = buffer;
+	struct NCR5380_hostdata *hostdata;
+	Scsi_Cmnd *ptr;
+	unsigned long flags;
+	off_t begin = 0;
+#define check_offset()					\
+	do {						\
+		if (pos - buffer < offset - begin) {	\
+			begin += pos - buffer;		\
+			pos = buffer;			\
+		}					\
+	} while (0)
 
-    hostdata = (struct NCR5380_hostdata *)instance->hostdata;
+	hostdata = (struct NCR5380_hostdata *)instance->hostdata;
 
-    if (inout) { /* Has data been written to the file ? */
-	return(-ENOSYS);  /* Currently this is a no-op */
-    }
-    SPRINTF("NCR5380 core release=%d.\n", NCR5380_PUBLIC_RELEASE);
-    check_offset();
-    local_irq_save(flags);
-    SPRINTF("NCR5380: coroutine is%s running.\n", main_running ? "" : "n't");
-    check_offset();
-    if (!hostdata->connected)
-	SPRINTF("scsi%d: no currently connected command\n", HOSTNO);
-    else
-	pos = lprint_Scsi_Cmnd ((Scsi_Cmnd *) hostdata->connected,
-				pos, buffer, length);
-    SPRINTF("scsi%d: issue_queue\n", HOSTNO);
-    check_offset();
-    for (ptr = (Scsi_Cmnd *) hostdata->issue_queue; ptr; ptr = NEXT(ptr)) {
-	pos = lprint_Scsi_Cmnd (ptr, pos, buffer, length);
+	if (inout)			/* Has data been written to the file ? */
+		return -ENOSYS;		/* Currently this is a no-op */
+	SPRINTF("NCR5380 core release=%d.\n", NCR5380_PUBLIC_RELEASE);
 	check_offset();
-    }
-
-    SPRINTF("scsi%d: disconnected_queue\n", HOSTNO);
-    check_offset();
-    for (ptr = (Scsi_Cmnd *) hostdata->disconnected_queue; ptr;
-	 ptr = NEXT(ptr)) {
-	pos = lprint_Scsi_Cmnd (ptr, pos, buffer, length);
+	local_irq_save(flags);
+	SPRINTF("NCR5380: coroutine is%s running.\n",
+		main_running ? "" : "n't");
 	check_offset();
-    }
+	if (!hostdata->connected)
+		SPRINTF("scsi%d: no currently connected command\n", HOSTNO);
+	else
+		pos = lprint_Scsi_Cmnd((Scsi_Cmnd *) hostdata->connected,
+				       pos, buffer, length);
+	SPRINTF("scsi%d: issue_queue\n", HOSTNO);
+	check_offset();
+	for (ptr = (Scsi_Cmnd *)hostdata->issue_queue; ptr; ptr = NEXT(ptr)) {
+		pos = lprint_Scsi_Cmnd(ptr, pos, buffer, length);
+		check_offset();
+	}
 
-    local_irq_restore(flags);
-    *start = buffer + (offset - begin);
-    if (pos - buffer < offset - begin)
-	return 0;
-    else if (pos - buffer - (offset - begin) < length)
-	return pos - buffer - (offset - begin);
-    return length;
+	SPRINTF("scsi%d: disconnected_queue\n", HOSTNO);
+	check_offset();
+	for (ptr = (Scsi_Cmnd *) hostdata->disconnected_queue; ptr;
+	     ptr = NEXT(ptr)) {
+		pos = lprint_Scsi_Cmnd(ptr, pos, buffer, length);
+		check_offset();
+	}
+
+	local_irq_restore(flags);
+	*start = buffer + (offset - begin);
+	if (pos - buffer < offset - begin)
+		return 0;
+	else if (pos - buffer - (offset - begin) < length)
+		return pos - buffer - (offset - begin);
+	return length;
 }
 
-static char *
-lprint_Scsi_Cmnd (Scsi_Cmnd *cmd, char *pos, char *buffer, int length)
+static char *lprint_Scsi_Cmnd(Scsi_Cmnd *cmd, char *pos, char *buffer, int length)
 {
-    int i, s;
-    unsigned char *command;
-    SPRINTF("scsi%d: destination target %d, lun %d\n",
-	    H_NO(cmd), cmd->device->id, cmd->device->lun);
-    SPRINTF("        command = ");
-    command = cmd->cmnd;
-    SPRINTF("%2d (0x%02x)", command[0], command[0]);
-    for (i = 1, s = COMMAND_SIZE(command[0]); i < s; ++i)
-	SPRINTF(" %02x", command[i]);
-    SPRINTF("\n");
-    return pos;
+	int i, s;
+	unsigned char *command;
+	SPRINTF("scsi%d: destination target %d, lun %d\n",
+		H_NO(cmd), cmd->device->id, cmd->device->lun);
+	SPRINTF("        command = ");
+	command = cmd->cmnd;
+	SPRINTF("%2d (0x%02x)", command[0], command[0]);
+	for (i = 1, s = COMMAND_SIZE(command[0]); i < s; ++i)
+		SPRINTF(" %02x", command[i]);
+	SPRINTF("\n");
+	return pos;
 }
 
 
-/* 
+/*
  * Function : void NCR5380_init (struct Scsi_Host *instance)
  *
  * Purpose : initializes *instance and corresponding 5380 chip.
  *
- * Inputs : instance - instantiation of the 5380 driver.  
+ * Inputs : instance - instantiation of the 5380 driver.
  *
  * Notes : I assume that the host, hostno, and id bits have been
- * 	set correctly.  I don't care about the irq and other fields. 
- * 
+ *	set correctly.  I don't care about the irq and other fields.
+ *
  */
 
-static int NCR5380_init (struct Scsi_Host *instance, int flags)
+static int NCR5380_init(struct Scsi_Host *instance, int flags)
 {
-    int i;
-    SETUP_HOSTDATA(instance);
+	int i;
+	SETUP_HOSTDATA(instance);
 
-    NCR5380_all_init();
+	NCR5380_all_init();
 
-    hostdata->aborted = 0;
-    hostdata->id_mask = 1 << instance->this_id;
-    hostdata->id_higher_mask = 0;
-    for (i = hostdata->id_mask; i <= 0x80; i <<= 1)
-	if (i > hostdata->id_mask)
-	    hostdata->id_higher_mask |= i;
-    for (i = 0; i < 8; ++i)
-	hostdata->busy[i] = 0;
+	hostdata->aborted = 0;
+	hostdata->id_mask = 1 << instance->this_id;
+	hostdata->id_higher_mask = 0;
+	for (i = hostdata->id_mask; i <= 0x80; i <<= 1)
+		if (i > hostdata->id_mask)
+			hostdata->id_higher_mask |= i;
+	for (i = 0; i < 8; ++i)
+		hostdata->busy[i] = 0;
 #ifdef SUPPORT_TAGS
-    init_tags();
+	init_tags();
 #endif
 #if defined (REAL_DMA)
-    hostdata->dma_len = 0;
+	hostdata->dma_len = 0;
 #endif
-    hostdata->targets_present = 0;
-    hostdata->connected = NULL;
-    hostdata->issue_queue = NULL;
-    hostdata->disconnected_queue = NULL;
-    hostdata->flags = FLAG_CHECK_LAST_BYTE_SENT;
+	hostdata->targets_present = 0;
+	hostdata->connected = NULL;
+	hostdata->issue_queue = NULL;
+	hostdata->disconnected_queue = NULL;
+	hostdata->flags = FLAG_CHECK_LAST_BYTE_SENT;
 
-    if (!the_template) {
-	the_template = instance->hostt;
-	first_instance = instance;
-    }
-	
+	if (!the_template) {
+		the_template = instance->hostt;
+		first_instance = instance;
+	}
 
 #ifndef AUTOSENSE
-    if ((instance->cmd_per_lun > 1) || (instance->can_queue > 1))
-	 printk("scsi%d: WARNING : support for multiple outstanding commands enabled\n"
-	        "        without AUTOSENSE option, contingent allegiance conditions may\n"
-	        "        be incorrectly cleared.\n", HOSTNO);
+	if ((instance->cmd_per_lun > 1) || (instance->can_queue > 1))
+		printk("scsi%d: WARNING : support for multiple outstanding commands enabled\n"
+		       "        without AUTOSENSE option, contingent allegiance conditions may\n"
+		       "        be incorrectly cleared.\n", HOSTNO);
 #endif /* def AUTOSENSE */
 
-    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
-    NCR5380_write(MODE_REG, MR_BASE);
-    NCR5380_write(TARGET_COMMAND_REG, 0);
-    NCR5380_write(SELECT_ENABLE_REG, 0);
+	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+	NCR5380_write(MODE_REG, MR_BASE);
+	NCR5380_write(TARGET_COMMAND_REG, 0);
+	NCR5380_write(SELECT_ENABLE_REG, 0);
 
-    return 0;
+	return 0;
 }
 
-/* 
- * Function : int NCR5380_queue_command (Scsi_Cmnd *cmd, 
- *	void (*done)(Scsi_Cmnd *)) 
+/*
+ * our own old-style timeout update
+ */
+/*
+ * The strategy is to cause the timer code to call scsi_times_out()
+ * when the soonest timeout is pending.
+ * The arguments are used when we are queueing a new command, because
+ * we do not want to subtract the time used from this time, but when we
+ * set the timer, we want to take this value into account.
+ */
+
+int atari_scsi_update_timeout(Scsi_Cmnd * SCset, int timeout)
+{
+	int rtn;
+
+	/*
+	 * We are using the new error handling code to actually register/deregister
+	 * timers for timeout.
+	 */
+
+	if (!timer_pending(&SCset->eh_timeout))
+		rtn = 0;
+	else
+		rtn = SCset->eh_timeout.expires - jiffies;
+
+	if (timeout == 0) {
+		del_timer(&SCset->eh_timeout);
+		SCset->eh_timeout.data = (unsigned long)NULL;
+		SCset->eh_timeout.expires = 0;
+	} else {
+		if (SCset->eh_timeout.data != (unsigned long)NULL)
+			del_timer(&SCset->eh_timeout);
+		SCset->eh_timeout.data = (unsigned long)SCset;
+		SCset->eh_timeout.expires = jiffies + timeout;
+		add_timer(&SCset->eh_timeout);
+	}
+	return rtn;
+}
+
+/*
+ * Function : int NCR5380_queue_command (Scsi_Cmnd *cmd,
+ *	void (*done)(Scsi_Cmnd *))
  *
  * Purpose :  enqueues a SCSI command
  *
  * Inputs : cmd - SCSI command, done - function called on completion, with
  *	a pointer to the command descriptor.
- * 
+ *
  * Returns : 0
  *
- * Side effects : 
- *      cmd is added to the per instance issue_queue, with minor 
- *	twiddling done to the host specific fields of cmd.  If the 
+ * Side effects :
+ *      cmd is added to the per instance issue_queue, with minor
+ *	twiddling done to the host specific fields of cmd.  If the
  *	main coroutine is not running, it is restarted.
  *
  */
 
-static
-int NCR5380_queue_command (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *))
+static int NCR5380_queue_command(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *))
 {
-    SETUP_HOSTDATA(cmd->device->host);
-    Scsi_Cmnd *tmp;
-    int oldto;
-    unsigned long flags;
-    extern int update_timeout(Scsi_Cmnd * SCset, int timeout);
+	SETUP_HOSTDATA(cmd->device->host);
+	Scsi_Cmnd *tmp;
+	int oldto;
+	unsigned long flags;
+	// extern int update_timeout(Scsi_Cmnd * SCset, int timeout);
 
 #if (NDEBUG & NDEBUG_NO_WRITE)
-    switch (cmd->cmnd[0]) {
-    case WRITE_6:
-    case WRITE_10:
-	printk(KERN_NOTICE "scsi%d: WRITE attempted with NO_WRITE debugging flag set\n",
-	       H_NO(cmd));
-	cmd->result = (DID_ERROR << 16);
-	done(cmd);
-	return 0;
-    }
+	switch (cmd->cmnd[0]) {
+	case WRITE_6:
+	case WRITE_10:
+		printk(KERN_NOTICE "scsi%d: WRITE attempted with NO_WRITE debugging flag set\n",
+		       H_NO(cmd));
+		cmd->result = (DID_ERROR << 16);
+		done(cmd);
+		return 0;
+	}
 #endif /* (NDEBUG & NDEBUG_NO_WRITE) */
 
-
 #ifdef NCR5380_STATS
 # if 0
-    if (!hostdata->connected && !hostdata->issue_queue &&
-	!hostdata->disconnected_queue) {
-	hostdata->timebase = jiffies;
-    }
+	if (!hostdata->connected && !hostdata->issue_queue &&
+	    !hostdata->disconnected_queue) {
+		hostdata->timebase = jiffies;
+	}
 # endif
 # ifdef NCR5380_STAT_LIMIT
-    if (cmd->request_bufflen > NCR5380_STAT_LIMIT)
+	if (cmd->request_bufflen > NCR5380_STAT_LIMIT)
 # endif
-	switch (cmd->cmnd[0])
-	{
-	    case WRITE:
-	    case WRITE_6:
-	    case WRITE_10:
-		hostdata->time_write[cmd->device->id] -= (jiffies - hostdata->timebase);
-		hostdata->bytes_write[cmd->device->id] += cmd->request_bufflen;
-		hostdata->pendingw++;
-		break;
-	    case READ:
-	    case READ_6:
-	    case READ_10:
-		hostdata->time_read[cmd->device->id] -= (jiffies - hostdata->timebase);
-		hostdata->bytes_read[cmd->device->id] += cmd->request_bufflen;
-		hostdata->pendingr++;
-		break;
-	}
+		switch (cmd->cmnd[0]) {
+		case WRITE:
+		case WRITE_6:
+		case WRITE_10:
+			hostdata->time_write[cmd->device->id] -= (jiffies - hostdata->timebase);
+			hostdata->bytes_write[cmd->device->id] += cmd->request_bufflen;
+			hostdata->pendingw++;
+			break;
+		case READ:
+		case READ_6:
+		case READ_10:
+			hostdata->time_read[cmd->device->id] -= (jiffies - hostdata->timebase);
+			hostdata->bytes_read[cmd->device->id] += cmd->request_bufflen;
+			hostdata->pendingr++;
+			break;
+		}
 #endif
 
-    /* 
-     * We use the host_scribble field as a pointer to the next command  
-     * in a queue 
-     */
+	/*
+	 * We use the host_scribble field as a pointer to the next command
+	 * in a queue
+	 */
 
-    NEXT(cmd) = NULL;
-    cmd->scsi_done = done;
+	SET_NEXT(cmd, NULL);
+	cmd->scsi_done = done;
 
-    cmd->result = 0;
+	cmd->result = 0;
 
+	/*
+	 * Insert the cmd into the issue queue. Note that REQUEST SENSE
+	 * commands are added to the head of the queue since any command will
+	 * clear the contingent allegiance condition that exists and the
+	 * sense data is only guaranteed to be valid while the condition exists.
+	 */
 
-    /* 
-     * Insert the cmd into the issue queue. Note that REQUEST SENSE 
-     * commands are added to the head of the queue since any command will
-     * clear the contingent allegiance condition that exists and the 
-     * sense data is only guaranteed to be valid while the condition exists.
-     */
+	local_irq_save(flags);
+	/* ++guenther: now that the issue queue is being set up, we can lock ST-DMA.
+	 * Otherwise a running NCR5380_main may steal the lock.
+	 * Lock before actually inserting due to fairness reasons explained in
+	 * atari_scsi.c. If we insert first, then it's impossible for this driver
+	 * to release the lock.
+	 * Stop timer for this command while waiting for the lock, or timeouts
+	 * may happen (and they really do), and it's no good if the command doesn't
+	 * appear in any of the queues.
+	 * ++roman: Just disabling the NCR interrupt isn't sufficient here,
+	 * because also a timer int can trigger an abort or reset, which would
+	 * alter queues and touch the lock.
+	 */
+	if (!IS_A_TT()) {
+		oldto = atari_scsi_update_timeout(cmd, 0);
+		falcon_get_lock();
+		atari_scsi_update_timeout(cmd, oldto);
+	}
+	if (!(hostdata->issue_queue) || (cmd->cmnd[0] == REQUEST_SENSE)) {
+		LIST(cmd, hostdata->issue_queue);
+		SET_NEXT(cmd, hostdata->issue_queue);
+		hostdata->issue_queue = cmd;
+	} else {
+		for (tmp = (Scsi_Cmnd *)hostdata->issue_queue;
+		     NEXT(tmp); tmp = NEXT(tmp))
+			;
+		LIST(cmd, tmp);
+		SET_NEXT(tmp, cmd);
+	}
+	local_irq_restore(flags);
 
-    local_irq_save(flags);
-    /* ++guenther: now that the issue queue is being set up, we can lock ST-DMA.
-     * Otherwise a running NCR5380_main may steal the lock.
-     * Lock before actually inserting due to fairness reasons explained in
-     * atari_scsi.c. If we insert first, then it's impossible for this driver
-     * to release the lock.
-     * Stop timer for this command while waiting for the lock, or timeouts
-     * may happen (and they really do), and it's no good if the command doesn't
-     * appear in any of the queues.
-     * ++roman: Just disabling the NCR interrupt isn't sufficient here,
-     * because also a timer int can trigger an abort or reset, which would
-     * alter queues and touch the lock.
-     */
-    if (!IS_A_TT()) {
-	oldto = update_timeout(cmd, 0);
-	falcon_get_lock();
-	update_timeout(cmd, oldto);
-    }
-    if (!(hostdata->issue_queue) || (cmd->cmnd[0] == REQUEST_SENSE)) {
-	LIST(cmd, hostdata->issue_queue);
-	NEXT(cmd) = hostdata->issue_queue;
-	hostdata->issue_queue = cmd;
-    } else {
-	for (tmp = (Scsi_Cmnd *)hostdata->issue_queue;
-	     NEXT(tmp); tmp = NEXT(tmp))
-	    ;
-	LIST(cmd, tmp);
-	NEXT(tmp) = cmd;
-    }
-    local_irq_restore(flags);
+	QU_PRINTK("scsi%d: command added to %s of queue\n", H_NO(cmd),
+		  (cmd->cmnd[0] == REQUEST_SENSE) ? "head" : "tail");
 
-    QU_PRINTK("scsi%d: command added to %s of queue\n", H_NO(cmd),
-	      (cmd->cmnd[0] == REQUEST_SENSE) ? "head" : "tail");
-
-    /* If queue_command() is called from an interrupt (real one or bottom
-     * half), we let queue_main() do the job of taking care about main. If it
-     * is already running, this is a no-op, else main will be queued.
-     *
-     * If we're not in an interrupt, we can call NCR5380_main()
-     * unconditionally, because it cannot be already running.
-     */
-    if (in_interrupt() || ((flags >> 8) & 7) >= 6)
-	queue_main();
-    else
-	NCR5380_main(NULL);
-    return 0;
+	/* If queue_command() is called from an interrupt (real one or bottom
+	 * half), we let queue_main() do the job of taking care about main. If it
+	 * is already running, this is a no-op, else main will be queued.
+	 *
+	 * If we're not in an interrupt, we can call NCR5380_main()
+	 * unconditionally, because it cannot be already running.
+	 */
+	if (in_interrupt() || ((flags >> 8) & 7) >= 6)
+		queue_main();
+	else
+		NCR5380_main(NULL);
+	return 0;
 }
 
 /*
- * Function : NCR5380_main (void) 
+ * Function : NCR5380_main (void)
  *
- * Purpose : NCR5380_main is a coroutine that runs as long as more work can 
- *	be done on the NCR5380 host adapters in a system.  Both 
- *	NCR5380_queue_command() and NCR5380_intr() will try to start it 
+ * Purpose : NCR5380_main is a coroutine that runs as long as more work can
+ *	be done on the NCR5380 host adapters in a system.  Both
+ *	NCR5380_queue_command() and NCR5380_intr() will try to start it
  *	in case it is not running.
- * 
- * NOTE : NCR5380_main exits with interrupts *disabled*, the caller should 
+ *
+ * NOTE : NCR5380_main exits with interrupts *disabled*, the caller should
  *  reenable them.  This prevents reentrancy and kernel stack overflow.
- */ 	
-    
-static void NCR5380_main (void *bl)
+ */
+
+static void NCR5380_main(struct work_struct *work)
 {
-    Scsi_Cmnd *tmp, *prev;
-    struct Scsi_Host *instance = first_instance;
-    struct NCR5380_hostdata *hostdata = HOSTDATA(instance);
-    int done;
-    unsigned long flags;
-    
-    /*
-     * We run (with interrupts disabled) until we're sure that none of 
-     * the host adapters have anything that can be done, at which point 
-     * we set main_running to 0 and exit.
-     *
-     * Interrupts are enabled before doing various other internal 
-     * instructions, after we've decided that we need to run through
-     * the loop again.
-     *
-     * this should prevent any race conditions.
-     * 
-     * ++roman: Just disabling the NCR interrupt isn't sufficient here,
-     * because also a timer int can trigger an abort or reset, which can
-     * alter queues and touch the Falcon lock.
-     */
+	Scsi_Cmnd *tmp, *prev;
+	struct Scsi_Host *instance = first_instance;
+	struct NCR5380_hostdata *hostdata = HOSTDATA(instance);
+	int done;
+	unsigned long flags;
 
-    /* Tell int handlers main() is now already executing.  Note that
-       no races are possible here. If an int comes in before
-       'main_running' is set here, and queues/executes main via the
-       task queue, it doesn't do any harm, just this instance of main
-       won't find any work left to do. */
-    if (main_running)
-    	return;
-    main_running = 1;
+	/*
+	 * We run (with interrupts disabled) until we're sure that none of
+	 * the host adapters have anything that can be done, at which point
+	 * we set main_running to 0 and exit.
+	 *
+	 * Interrupts are enabled before doing various other internal
+	 * instructions, after we've decided that we need to run through
+	 * the loop again.
+	 *
+	 * this should prevent any race conditions.
+	 *
+	 * ++roman: Just disabling the NCR interrupt isn't sufficient here,
+	 * because also a timer int can trigger an abort or reset, which can
+	 * alter queues and touch the Falcon lock.
+	 */
 
-    local_save_flags(flags);
-    do {
-	local_irq_disable(); /* Freeze request queues */
-	done = 1;
-	
-	if (!hostdata->connected) {
-	    MAIN_PRINTK( "scsi%d: not connected\n", HOSTNO );
-	    /*
-	     * Search through the issue_queue for a command destined
-	     * for a target that's not busy.
-	     */
+	/* Tell int handlers main() is now already executing.  Note that
+	   no races are possible here. If an int comes in before
+	   'main_running' is set here, and queues/executes main via the
+	   task queue, it doesn't do any harm, just this instance of main
+	   won't find any work left to do. */
+	if (main_running)
+		return;
+	main_running = 1;
+
+	local_save_flags(flags);
+	do {
+		local_irq_disable();	/* Freeze request queues */
+		done = 1;
+
+		if (!hostdata->connected) {
+			MAIN_PRINTK("scsi%d: not connected\n", HOSTNO);
+			/*
+			 * Search through the issue_queue for a command destined
+			 * for a target that's not busy.
+			 */
 #if (NDEBUG & NDEBUG_LISTS)
-	    for (tmp = (Scsi_Cmnd *) hostdata->issue_queue, prev = NULL;
-		 tmp && (tmp != prev); prev = tmp, tmp = NEXT(tmp))
-		;
-		/*printk("%p  ", tmp);*/
-	    if ((tmp == prev) && tmp) printk(" LOOP\n");/* else printk("\n");*/
+			for (tmp = (Scsi_Cmnd *) hostdata->issue_queue, prev = NULL;
+			     tmp && (tmp != prev); prev = tmp, tmp = NEXT(tmp))
+				;
+			/*printk("%p  ", tmp);*/
+			if ((tmp == prev) && tmp)
+				printk(" LOOP\n");
+			/* else printk("\n"); */
 #endif
-	    for (tmp = (Scsi_Cmnd *) hostdata->issue_queue, 
-		 prev = NULL; tmp; prev = tmp, tmp = NEXT(tmp) ) {
+			for (tmp = (Scsi_Cmnd *) hostdata->issue_queue,
+			     prev = NULL; tmp; prev = tmp, tmp = NEXT(tmp)) {
 
 #if (NDEBUG & NDEBUG_LISTS)
-		if (prev != tmp)
-		    printk("MAIN tmp=%p   target=%d   busy=%d lun=%d\n",
-			   tmp, tmp->device->id, hostdata->busy[tmp->device->id],
-			   tmp->device->lun);
+				if (prev != tmp)
+					printk("MAIN tmp=%p   target=%d   busy=%d lun=%d\n",
+					       tmp, tmp->device->id, hostdata->busy[tmp->device->id],
+					       tmp->device->lun);
 #endif
-		/*  When we find one, remove it from the issue queue. */
-		/* ++guenther: possible race with Falcon locking */
-		if (
+				/*  When we find one, remove it from the issue queue. */
+				/* ++guenther: possible race with Falcon locking */
+				if (
 #ifdef SUPPORT_TAGS
-		    !is_lun_busy( tmp, tmp->cmnd[0] != REQUEST_SENSE)
+				    !is_lun_busy( tmp, tmp->cmnd[0] != REQUEST_SENSE)
 #else
-		    !(hostdata->busy[tmp->device->id] & (1 << tmp->device->lun))
+				    !(hostdata->busy[tmp->device->id] & (1 << tmp->device->lun))
+#endif
+				    ) {
+					/* ++guenther: just to be sure, this must be atomic */
+					local_irq_disable();
+					if (prev) {
+						REMOVE(prev, NEXT(prev), tmp, NEXT(tmp));
+						SET_NEXT(prev, NEXT(tmp));
+					} else {
+						REMOVE(-1, hostdata->issue_queue, tmp, NEXT(tmp));
+						hostdata->issue_queue = NEXT(tmp);
+					}
+					SET_NEXT(tmp, NULL);
+					falcon_dont_release++;
+
+					/* reenable interrupts after finding one */
+					local_irq_restore(flags);
+
+					/*
+					 * Attempt to establish an I_T_L nexus here.
+					 * On success, instance->hostdata->connected is set.
+					 * On failure, we must add the command back to the
+					 *   issue queue so we can keep trying.
+					 */
+					MAIN_PRINTK("scsi%d: main(): command for target %d "
+						    "lun %d removed from issue_queue\n",
+						    HOSTNO, tmp->device->id, tmp->device->lun);
+					/*
+					 * REQUEST SENSE commands are issued without tagged
+					 * queueing, even on SCSI-II devices because the
+					 * contingent allegiance condition exists for the
+					 * entire unit.
+					 */
+					/* ++roman: ...and the standard also requires that
+					 * REQUEST SENSE command are untagged.
+					 */
+
+#ifdef SUPPORT_TAGS
+					cmd_get_tag(tmp, tmp->cmnd[0] != REQUEST_SENSE);
+#endif
+					if (!NCR5380_select(instance, tmp,
+					    (tmp->cmnd[0] == REQUEST_SENSE) ? TAG_NONE :
+					    TAG_NEXT)) {
+						falcon_dont_release--;
+						/* release if target did not response! */
+						falcon_release_lock_if_possible(hostdata);
+						break;
+					} else {
+						local_irq_disable();
+						LIST(tmp, hostdata->issue_queue);
+						SET_NEXT(tmp, hostdata->issue_queue);
+						hostdata->issue_queue = tmp;
+#ifdef SUPPORT_TAGS
+						cmd_free_tag(tmp);
+#endif
+						falcon_dont_release--;
+						local_irq_restore(flags);
+						MAIN_PRINTK("scsi%d: main(): select() failed, "
+							    "returned to issue_queue\n", HOSTNO);
+						if (hostdata->connected)
+							break;
+					}
+				} /* if target/lun/target queue is not busy */
+			} /* for issue_queue */
+		} /* if (!hostdata->connected) */
+
+		if (hostdata->connected
+#ifdef REAL_DMA
+		    && !hostdata->dma_len
 #endif
 		    ) {
-		    /* ++guenther: just to be sure, this must be atomic */
-		    local_irq_disable();
-		    if (prev) {
-		        REMOVE(prev, NEXT(prev), tmp, NEXT(tmp));
-			NEXT(prev) = NEXT(tmp);
-		    } else {
-		        REMOVE(-1, hostdata->issue_queue, tmp, NEXT(tmp));
-			hostdata->issue_queue = NEXT(tmp);
-		    }
-		    NEXT(tmp) = NULL;
-		    falcon_dont_release++;
-		    
-		    /* reenable interrupts after finding one */
-		    local_irq_restore(flags);
-		    
-		    /* 
-		     * Attempt to establish an I_T_L nexus here. 
-		     * On success, instance->hostdata->connected is set.
-		     * On failure, we must add the command back to the
-		     *   issue queue so we can keep trying.	
-		     */
-		    MAIN_PRINTK("scsi%d: main(): command for target %d "
-				"lun %d removed from issue_queue\n",
-				HOSTNO, tmp->device->id, tmp->device->lun);
-		    /* 
-		     * REQUEST SENSE commands are issued without tagged
-		     * queueing, even on SCSI-II devices because the 
-		     * contingent allegiance condition exists for the 
-		     * entire unit.
-		     */
-		    /* ++roman: ...and the standard also requires that
-		     * REQUEST SENSE command are untagged.
-		     */
-		    
-#ifdef SUPPORT_TAGS
-		    cmd_get_tag( tmp, tmp->cmnd[0] != REQUEST_SENSE );
-#endif
-		    if (!NCR5380_select(instance, tmp, 
-			    (tmp->cmnd[0] == REQUEST_SENSE) ? TAG_NONE : 
-			    TAG_NEXT)) {
-			falcon_dont_release--;
-			/* release if target did not response! */
-			falcon_release_lock_if_possible( hostdata );
-			break;
-		    } else {
-			local_irq_disable();
-			LIST(tmp, hostdata->issue_queue);
-			NEXT(tmp) = hostdata->issue_queue;
-			hostdata->issue_queue = tmp;
-#ifdef SUPPORT_TAGS
-			cmd_free_tag( tmp );
-#endif
-			falcon_dont_release--;
 			local_irq_restore(flags);
-			MAIN_PRINTK("scsi%d: main(): select() failed, "
-				    "returned to issue_queue\n", HOSTNO);
-			if (hostdata->connected)
-			    break;
-		    }
-		} /* if target/lun/target queue is not busy */
-	    } /* for issue_queue */
-	} /* if (!hostdata->connected) */
-		
-	if (hostdata->connected 
-#ifdef REAL_DMA
-	    && !hostdata->dma_len
-#endif
-	    ) {
-	    local_irq_restore(flags);
-	    MAIN_PRINTK("scsi%d: main: performing information transfer\n",
-			HOSTNO);
-	    NCR5380_information_transfer(instance);
-	    MAIN_PRINTK("scsi%d: main: done set false\n", HOSTNO);
-	    done = 0;
-	}
-    } while (!done);
+			MAIN_PRINTK("scsi%d: main: performing information transfer\n",
+				    HOSTNO);
+			NCR5380_information_transfer(instance);
+			MAIN_PRINTK("scsi%d: main: done set false\n", HOSTNO);
+			done = 0;
+		}
+	} while (!done);
 
-    /* Better allow ints _after_ 'main_running' has been cleared, else
-       an interrupt could believe we'll pick up the work it left for
-       us, but we won't see it anymore here... */
-    main_running = 0;
-    local_irq_restore(flags);
+	/* Better allow ints _after_ 'main_running' has been cleared, else
+	   an interrupt could believe we'll pick up the work it left for
+	   us, but we won't see it anymore here... */
+	main_running = 0;
+	local_irq_restore(flags);
 }
 
 
@@ -1183,1441 +1236,1439 @@
  * Function : void NCR5380_dma_complete (struct Scsi_Host *instance)
  *
  * Purpose : Called by interrupt handler when DMA finishes or a phase
- *	mismatch occurs (which would finish the DMA transfer).  
+ *	mismatch occurs (which would finish the DMA transfer).
  *
  * Inputs : instance - this instance of the NCR5380.
  *
  */
 
-static void NCR5380_dma_complete( struct Scsi_Host *instance )
+static void NCR5380_dma_complete(struct Scsi_Host *instance)
 {
-    SETUP_HOSTDATA(instance);
-    int           transfered, saved_data = 0, overrun = 0, cnt, toPIO;
-    unsigned char **data, p;
-    volatile int  *count;
+	SETUP_HOSTDATA(instance);
+	int transfered, saved_data = 0, overrun = 0, cnt, toPIO;
+	unsigned char **data, p;
+	volatile int *count;
 
-    if (!hostdata->connected) {
-	printk(KERN_WARNING "scsi%d: received end of DMA interrupt with "
-	       "no connected cmd\n", HOSTNO);
-	return;
-    }
-    
-    if (atari_read_overruns) {
-	p = hostdata->connected->SCp.phase;
-	if (p & SR_IO) {
-	    udelay(10);
-	    if ((((NCR5380_read(BUS_AND_STATUS_REG)) &
-		  (BASR_PHASE_MATCH|BASR_ACK)) ==
-		 (BASR_PHASE_MATCH|BASR_ACK))) {
-		saved_data = NCR5380_read(INPUT_DATA_REG);
-		overrun = 1;
-		DMA_PRINTK("scsi%d: read overrun handled\n", HOSTNO);
-	    }
+	if (!hostdata->connected) {
+		printk(KERN_WARNING "scsi%d: received end of DMA interrupt with "
+		       "no connected cmd\n", HOSTNO);
+		return;
 	}
-    }
 
-    DMA_PRINTK("scsi%d: real DMA transfer complete, basr 0x%X, sr 0x%X\n",
-	       HOSTNO, NCR5380_read(BUS_AND_STATUS_REG),
-	       NCR5380_read(STATUS_REG));
-
-    (void) NCR5380_read(RESET_PARITY_INTERRUPT_REG);
-    NCR5380_write(MODE_REG, MR_BASE);
-    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
-
-    transfered = hostdata->dma_len - NCR5380_dma_residual(instance);
-    hostdata->dma_len = 0;
-
-    data = (unsigned char **) &(hostdata->connected->SCp.ptr);
-    count = &(hostdata->connected->SCp.this_residual);
-    *data += transfered;
-    *count -= transfered;
-
-    if (atari_read_overruns) {
-	if ((NCR5380_read(STATUS_REG) & PHASE_MASK) == p && (p & SR_IO)) {
-	    cnt = toPIO = atari_read_overruns;
-	    if (overrun) {
-		DMA_PRINTK("Got an input overrun, using saved byte\n");
-		*(*data)++ = saved_data;
-		(*count)--;
-		cnt--;
-		toPIO--;
-	    }
-	    DMA_PRINTK("Doing %d-byte PIO to 0x%08lx\n", cnt, (long)*data);
-	    NCR5380_transfer_pio(instance, &p, &cnt, data);
-	    *count -= toPIO - cnt;
+	if (atari_read_overruns) {
+		p = hostdata->connected->SCp.phase;
+		if (p & SR_IO) {
+			udelay(10);
+			if ((NCR5380_read(BUS_AND_STATUS_REG) &
+			     (BASR_PHASE_MATCH|BASR_ACK)) ==
+			    (BASR_PHASE_MATCH|BASR_ACK)) {
+				saved_data = NCR5380_read(INPUT_DATA_REG);
+				overrun = 1;
+				DMA_PRINTK("scsi%d: read overrun handled\n", HOSTNO);
+			}
+		}
 	}
-    }
+
+	DMA_PRINTK("scsi%d: real DMA transfer complete, basr 0x%X, sr 0x%X\n",
+		   HOSTNO, NCR5380_read(BUS_AND_STATUS_REG),
+		   NCR5380_read(STATUS_REG));
+
+	(void)NCR5380_read(RESET_PARITY_INTERRUPT_REG);
+	NCR5380_write(MODE_REG, MR_BASE);
+	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+
+	transfered = hostdata->dma_len - NCR5380_dma_residual(instance);
+	hostdata->dma_len = 0;
+
+	data = (unsigned char **)&hostdata->connected->SCp.ptr;
+	count = &hostdata->connected->SCp.this_residual;
+	*data += transfered;
+	*count -= transfered;
+
+	if (atari_read_overruns) {
+		if ((NCR5380_read(STATUS_REG) & PHASE_MASK) == p && (p & SR_IO)) {
+			cnt = toPIO = atari_read_overruns;
+			if (overrun) {
+				DMA_PRINTK("Got an input overrun, using saved byte\n");
+				*(*data)++ = saved_data;
+				(*count)--;
+				cnt--;
+				toPIO--;
+			}
+			DMA_PRINTK("Doing %d-byte PIO to 0x%08lx\n", cnt, (long)*data);
+			NCR5380_transfer_pio(instance, &p, &cnt, data);
+			*count -= toPIO - cnt;
+		}
+	}
 }
 #endif /* REAL_DMA */
 
 
 /*
  * Function : void NCR5380_intr (int irq)
- * 
+ *
  * Purpose : handle interrupts, reestablishing I_T_L or I_T_L_Q nexuses
- *	from the disconnected queue, and restarting NCR5380_main() 
+ *	from the disconnected queue, and restarting NCR5380_main()
  *	as required.
  *
  * Inputs : int irq, irq that caused this interrupt.
  *
  */
 
-static irqreturn_t NCR5380_intr (int irq, void *dev_id)
+static irqreturn_t NCR5380_intr(int irq, void *dev_id)
 {
-    struct Scsi_Host *instance = first_instance;
-    int done = 1, handled = 0;
-    unsigned char basr;
+	struct Scsi_Host *instance = first_instance;
+	int done = 1, handled = 0;
+	unsigned char basr;
 
-    INT_PRINTK("scsi%d: NCR5380 irq triggered\n", HOSTNO);
+	INT_PRINTK("scsi%d: NCR5380 irq triggered\n", HOSTNO);
 
-    /* Look for pending interrupts */
-    basr = NCR5380_read(BUS_AND_STATUS_REG);
-    INT_PRINTK("scsi%d: BASR=%02x\n", HOSTNO, basr);
-    /* dispatch to appropriate routine if found and done=0 */
-    if (basr & BASR_IRQ) {
-	NCR_PRINT(NDEBUG_INTR);
-	if ((NCR5380_read(STATUS_REG) & (SR_SEL|SR_IO)) == (SR_SEL|SR_IO)) {
-	    done = 0;
-	    ENABLE_IRQ();
-	    INT_PRINTK("scsi%d: SEL interrupt\n", HOSTNO);
-	    NCR5380_reselect(instance);
-	    (void) NCR5380_read(RESET_PARITY_INTERRUPT_REG);
-	}
-	else if (basr & BASR_PARITY_ERROR) {
-	    INT_PRINTK("scsi%d: PARITY interrupt\n", HOSTNO);
-	    (void) NCR5380_read(RESET_PARITY_INTERRUPT_REG);
-	}
-	else if ((NCR5380_read(STATUS_REG) & SR_RST) == SR_RST) {
-	    INT_PRINTK("scsi%d: RESET interrupt\n", HOSTNO);
-	    (void)NCR5380_read(RESET_PARITY_INTERRUPT_REG);
-	}
-	else {
-	    /*  
-	     * The rest of the interrupt conditions can occur only during a
-	     * DMA transfer
-	     */
+	/* Look for pending interrupts */
+	basr = NCR5380_read(BUS_AND_STATUS_REG);
+	INT_PRINTK("scsi%d: BASR=%02x\n", HOSTNO, basr);
+	/* dispatch to appropriate routine if found and done=0 */
+	if (basr & BASR_IRQ) {
+		NCR_PRINT(NDEBUG_INTR);
+		if ((NCR5380_read(STATUS_REG) & (SR_SEL|SR_IO)) == (SR_SEL|SR_IO)) {
+			done = 0;
+			ENABLE_IRQ();
+			INT_PRINTK("scsi%d: SEL interrupt\n", HOSTNO);
+			NCR5380_reselect(instance);
+			(void)NCR5380_read(RESET_PARITY_INTERRUPT_REG);
+		} else if (basr & BASR_PARITY_ERROR) {
+			INT_PRINTK("scsi%d: PARITY interrupt\n", HOSTNO);
+			(void)NCR5380_read(RESET_PARITY_INTERRUPT_REG);
+		} else if ((NCR5380_read(STATUS_REG) & SR_RST) == SR_RST) {
+			INT_PRINTK("scsi%d: RESET interrupt\n", HOSTNO);
+			(void)NCR5380_read(RESET_PARITY_INTERRUPT_REG);
+		} else {
+			/*
+			 * The rest of the interrupt conditions can occur only during a
+			 * DMA transfer
+			 */
 
 #if defined(REAL_DMA)
-	    /*
-	     * We should only get PHASE MISMATCH and EOP interrupts if we have
-	     * DMA enabled, so do a sanity check based on the current setting
-	     * of the MODE register.
-	     */
+			/*
+			 * We should only get PHASE MISMATCH and EOP interrupts if we have
+			 * DMA enabled, so do a sanity check based on the current setting
+			 * of the MODE register.
+			 */
 
-	    if ((NCR5380_read(MODE_REG) & MR_DMA_MODE) &&
-		((basr & BASR_END_DMA_TRANSFER) || 
-		 !(basr & BASR_PHASE_MATCH))) {
-		    
-		INT_PRINTK("scsi%d: PHASE MISM or EOP interrupt\n", HOSTNO);
-		NCR5380_dma_complete( instance );
-		done = 0;
-		ENABLE_IRQ();
-	    } else
+			if ((NCR5380_read(MODE_REG) & MR_DMA_MODE) &&
+			    ((basr & BASR_END_DMA_TRANSFER) ||
+			     !(basr & BASR_PHASE_MATCH))) {
+
+				INT_PRINTK("scsi%d: PHASE MISM or EOP interrupt\n", HOSTNO);
+				NCR5380_dma_complete( instance );
+				done = 0;
+				ENABLE_IRQ();
+			} else
 #endif /* REAL_DMA */
-	    {
+			{
 /* MS: Ignore unknown phase mismatch interrupts (caused by EOP interrupt) */
-		if (basr & BASR_PHASE_MATCH)
-		    printk(KERN_NOTICE "scsi%d: unknown interrupt, "
-			   "BASR 0x%x, MR 0x%x, SR 0x%x\n",
-			   HOSTNO, basr, NCR5380_read(MODE_REG),
-			   NCR5380_read(STATUS_REG));
-		(void) NCR5380_read(RESET_PARITY_INTERRUPT_REG);
-	    }
-	} /* if !(SELECTION || PARITY) */
-	handled = 1;
-    } /* BASR & IRQ */
-    else {
-	printk(KERN_NOTICE "scsi%d: interrupt without IRQ bit set in BASR, "
-	       "BASR 0x%X, MR 0x%X, SR 0x%x\n", HOSTNO, basr,
-	       NCR5380_read(MODE_REG), NCR5380_read(STATUS_REG));
-	(void) NCR5380_read(RESET_PARITY_INTERRUPT_REG);
-    }
-    
-    if (!done) {
-	INT_PRINTK("scsi%d: in int routine, calling main\n", HOSTNO);
-	/* Put a call to NCR5380_main() on the queue... */
-	queue_main();
-    }
-    return IRQ_RETVAL(handled);
+				if (basr & BASR_PHASE_MATCH)
+					printk(KERN_NOTICE "scsi%d: unknown interrupt, "
+					       "BASR 0x%x, MR 0x%x, SR 0x%x\n",
+					       HOSTNO, basr, NCR5380_read(MODE_REG),
+					       NCR5380_read(STATUS_REG));
+				(void)NCR5380_read(RESET_PARITY_INTERRUPT_REG);
+			}
+		} /* if !(SELECTION || PARITY) */
+		handled = 1;
+	} /* BASR & IRQ */ else {
+		printk(KERN_NOTICE "scsi%d: interrupt without IRQ bit set in BASR, "
+		       "BASR 0x%X, MR 0x%X, SR 0x%x\n", HOSTNO, basr,
+		       NCR5380_read(MODE_REG), NCR5380_read(STATUS_REG));
+		(void)NCR5380_read(RESET_PARITY_INTERRUPT_REG);
+	}
+
+	if (!done) {
+		INT_PRINTK("scsi%d: in int routine, calling main\n", HOSTNO);
+		/* Put a call to NCR5380_main() on the queue... */
+		queue_main();
+	}
+	return IRQ_RETVAL(handled);
 }
 
 #ifdef NCR5380_STATS
-static void collect_stats(struct NCR5380_hostdata* hostdata, Scsi_Cmnd* cmd)
+static void collect_stats(struct NCR5380_hostdata* hostdata, Scsi_Cmnd *cmd)
 {
 # ifdef NCR5380_STAT_LIMIT
-    if (cmd->request_bufflen > NCR5380_STAT_LIMIT)
+	if (cmd->request_bufflen > NCR5380_STAT_LIMIT)
 # endif
-	switch (cmd->cmnd[0])
-	{
-	    case WRITE:
-	    case WRITE_6:
-	    case WRITE_10:
-		hostdata->time_write[cmd->device->id] += (jiffies - hostdata->timebase);
-		/*hostdata->bytes_write[cmd->device->id] += cmd->request_bufflen;*/
-		hostdata->pendingw--;
-		break;
-	    case READ:
-	    case READ_6:
-	    case READ_10:
-		hostdata->time_read[cmd->device->id] += (jiffies - hostdata->timebase);
-		/*hostdata->bytes_read[cmd->device->id] += cmd->request_bufflen;*/
-		hostdata->pendingr--;
-		break;
-	}
+		switch (cmd->cmnd[0]) {
+		case WRITE:
+		case WRITE_6:
+		case WRITE_10:
+			hostdata->time_write[cmd->device->id] += (jiffies - hostdata->timebase);
+			/*hostdata->bytes_write[cmd->device->id] += cmd->request_bufflen;*/
+			hostdata->pendingw--;
+			break;
+		case READ:
+		case READ_6:
+		case READ_10:
+			hostdata->time_read[cmd->device->id] += (jiffies - hostdata->timebase);
+			/*hostdata->bytes_read[cmd->device->id] += cmd->request_bufflen;*/
+			hostdata->pendingr--;
+			break;
+		}
 }
 #endif
 
-/* 
- * Function : int NCR5380_select (struct Scsi_Host *instance, Scsi_Cmnd *cmd, 
+/*
+ * Function : int NCR5380_select (struct Scsi_Host *instance, Scsi_Cmnd *cmd,
  *	int tag);
  *
  * Purpose : establishes I_T_L or I_T_L_Q nexus for new or existing command,
- *	including ARBITRATION, SELECTION, and initial message out for 
- *	IDENTIFY and queue messages. 
+ *	including ARBITRATION, SELECTION, and initial message out for
+ *	IDENTIFY and queue messages.
  *
- * Inputs : instance - instantiation of the 5380 driver on which this 
- * 	target lives, cmd - SCSI command to execute, tag - set to TAG_NEXT for 
- *	new tag, TAG_NONE for untagged queueing, otherwise set to the tag for 
+ * Inputs : instance - instantiation of the 5380 driver on which this
+ *	target lives, cmd - SCSI command to execute, tag - set to TAG_NEXT for
+ *	new tag, TAG_NONE for untagged queueing, otherwise set to the tag for
  *	the command that is presently connected.
- * 
- * Returns : -1 if selection could not execute for some reason,
- *	0 if selection succeeded or failed because the target 
- * 	did not respond.
  *
- * Side effects : 
- * 	If bus busy, arbitration failed, etc, NCR5380_select() will exit 
+ * Returns : -1 if selection could not execute for some reason,
+ *	0 if selection succeeded or failed because the target
+ *	did not respond.
+ *
+ * Side effects :
+ *	If bus busy, arbitration failed, etc, NCR5380_select() will exit
  *		with registers as they should have been on entry - ie
  *		SELECT_ENABLE will be set appropriately, the NCR5380
  *		will cease to drive any SCSI bus signals.
  *
- *	If successful : I_T_L or I_T_L_Q nexus will be established, 
- *		instance->connected will be set to cmd.  
- * 		SELECT interrupt will be disabled.
+ *	If successful : I_T_L or I_T_L_Q nexus will be established,
+ *		instance->connected will be set to cmd.
+ *		SELECT interrupt will be disabled.
  *
- *	If failed (no target) : cmd->scsi_done() will be called, and the 
+ *	If failed (no target) : cmd->scsi_done() will be called, and the
  *		cmd->result host byte set to DID_BAD_TARGET.
  */
 
-static int NCR5380_select (struct Scsi_Host *instance, Scsi_Cmnd *cmd, int tag)
+static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd *cmd, int tag)
 {
-    SETUP_HOSTDATA(instance);
-    unsigned char tmp[3], phase;
-    unsigned char *data;
-    int len;
-    unsigned long timeout;
-    unsigned long flags;
+	SETUP_HOSTDATA(instance);
+	unsigned char tmp[3], phase;
+	unsigned char *data;
+	int len;
+	unsigned long timeout;
+	unsigned long flags;
 
-    hostdata->restart_select = 0;
-    NCR_PRINT(NDEBUG_ARBITRATION);
-    ARB_PRINTK("scsi%d: starting arbitration, id = %d\n", HOSTNO,
-	       instance->this_id);
+	hostdata->restart_select = 0;
+	NCR_PRINT(NDEBUG_ARBITRATION);
+	ARB_PRINTK("scsi%d: starting arbitration, id = %d\n", HOSTNO,
+		   instance->this_id);
 
-    /* 
-     * Set the phase bits to 0, otherwise the NCR5380 won't drive the 
-     * data bus during SELECTION.
-     */
+	/*
+	 * Set the phase bits to 0, otherwise the NCR5380 won't drive the
+	 * data bus during SELECTION.
+	 */
 
-    local_irq_save(flags);
-    if (hostdata->connected) {
+	local_irq_save(flags);
+	if (hostdata->connected) {
+		local_irq_restore(flags);
+		return -1;
+	}
+	NCR5380_write(TARGET_COMMAND_REG, 0);
+
+	/*
+	 * Start arbitration.
+	 */
+
+	NCR5380_write(OUTPUT_DATA_REG, hostdata->id_mask);
+	NCR5380_write(MODE_REG, MR_ARBITRATE);
+
 	local_irq_restore(flags);
-	return -1;
-    }
-    NCR5380_write(TARGET_COMMAND_REG, 0);
 
+	/* Wait for arbitration logic to complete */
+#if defined(NCR_TIMEOUT)
+	{
+		unsigned long timeout = jiffies + 2*NCR_TIMEOUT;
 
-    /* 
-     * Start arbitration.
-     */
-    
-    NCR5380_write(OUTPUT_DATA_REG, hostdata->id_mask);
-    NCR5380_write(MODE_REG, MR_ARBITRATE);
-
-    local_irq_restore(flags);
-
-    /* Wait for arbitration logic to complete */
-#if NCR_TIMEOUT
-    {
-      unsigned long timeout = jiffies + 2*NCR_TIMEOUT;
-
-      while (!(NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_PROGRESS)
-	   && time_before(jiffies, timeout) && !hostdata->connected)
-	;
-      if (time_after_eq(jiffies, timeout))
-      {
-	printk("scsi : arbitration timeout at %d\n", __LINE__);
-	NCR5380_write(MODE_REG, MR_BASE);
-	NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
-	return -1;
-      }
-    }
+		while (!(NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_PROGRESS) &&
+		       time_before(jiffies, timeout) && !hostdata->connected)
+			;
+		if (time_after_eq(jiffies, timeout)) {
+			printk("scsi : arbitration timeout at %d\n", __LINE__);
+			NCR5380_write(MODE_REG, MR_BASE);
+			NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
+			return -1;
+		}
+	}
 #else /* NCR_TIMEOUT */
-    while (!(NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_PROGRESS)
-	 && !hostdata->connected);
+	while (!(NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_PROGRESS) &&
+	       !hostdata->connected)
+		;
 #endif
 
-    ARB_PRINTK("scsi%d: arbitration complete\n", HOSTNO);
+	ARB_PRINTK("scsi%d: arbitration complete\n", HOSTNO);
 
-    if (hostdata->connected) {
-	NCR5380_write(MODE_REG, MR_BASE); 
-	return -1;
-    }
-    /* 
-     * The arbitration delay is 2.2us, but this is a minimum and there is 
-     * no maximum so we can safely sleep for ceil(2.2) usecs to accommodate
-     * the integral nature of udelay().
-     *
-     */
+	if (hostdata->connected) {
+		NCR5380_write(MODE_REG, MR_BASE);
+		return -1;
+	}
+	/*
+	 * The arbitration delay is 2.2us, but this is a minimum and there is
+	 * no maximum so we can safely sleep for ceil(2.2) usecs to accommodate
+	 * the integral nature of udelay().
+	 *
+	 */
 
-    udelay(3);
+	udelay(3);
 
-    /* Check for lost arbitration */
-    if ((NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST) ||
-	(NCR5380_read(CURRENT_SCSI_DATA_REG) & hostdata->id_higher_mask) ||
-	(NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST) ||
-	hostdata->connected) {
-	NCR5380_write(MODE_REG, MR_BASE); 
-	ARB_PRINTK("scsi%d: lost arbitration, deasserting MR_ARBITRATE\n",
-		   HOSTNO);
-	return -1;
-    }
+	/* Check for lost arbitration */
+	if ((NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST) ||
+	    (NCR5380_read(CURRENT_SCSI_DATA_REG) & hostdata->id_higher_mask) ||
+	    (NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST) ||
+	    hostdata->connected) {
+		NCR5380_write(MODE_REG, MR_BASE);
+		ARB_PRINTK("scsi%d: lost arbitration, deasserting MR_ARBITRATE\n",
+			   HOSTNO);
+		return -1;
+	}
 
-     /* after/during arbitration, BSY should be asserted.
-	IBM DPES-31080 Version S31Q works now */
-     /* Tnx to Thomas_Roesch@m2.maus.de for finding this! (Roman) */
-    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_SEL |
-					 ICR_ASSERT_BSY ) ;
-    
-    if ((NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST) ||
-	hostdata->connected) {
-	NCR5380_write(MODE_REG, MR_BASE);
-	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
-	ARB_PRINTK("scsi%d: lost arbitration, deasserting ICR_ASSERT_SEL\n",
-		   HOSTNO);
-	return -1;
-    }
+	/* after/during arbitration, BSY should be asserted.
+	   IBM DPES-31080 Version S31Q works now */
+	/* Tnx to Thomas_Roesch@m2.maus.de for finding this! (Roman) */
+	NCR5380_write(INITIATOR_COMMAND_REG,
+		      ICR_BASE | ICR_ASSERT_SEL | ICR_ASSERT_BSY);
 
-    /* 
-     * Again, bus clear + bus settle time is 1.2us, however, this is 
-     * a minimum so we'll udelay ceil(1.2)
-     */
+	if ((NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST) ||
+	    hostdata->connected) {
+		NCR5380_write(MODE_REG, MR_BASE);
+		NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+		ARB_PRINTK("scsi%d: lost arbitration, deasserting ICR_ASSERT_SEL\n",
+			   HOSTNO);
+		return -1;
+	}
+
+	/*
+	 * Again, bus clear + bus settle time is 1.2us, however, this is
+	 * a minimum so we'll udelay ceil(1.2)
+	 */
 
 #ifdef CONFIG_ATARI_SCSI_TOSHIBA_DELAY
-    /* ++roman: But some targets (see above :-) seem to need a bit more... */
-    udelay(15);
+	/* ++roman: But some targets (see above :-) seem to need a bit more... */
+	udelay(15);
 #else
-    udelay(2);
+	udelay(2);
 #endif
-    
-    if (hostdata->connected) {
+
+	if (hostdata->connected) {
+		NCR5380_write(MODE_REG, MR_BASE);
+		NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+		return -1;
+	}
+
+	ARB_PRINTK("scsi%d: won arbitration\n", HOSTNO);
+
+	/*
+	 * Now that we have won arbitration, start Selection process, asserting
+	 * the host and target ID's on the SCSI bus.
+	 */
+
+	NCR5380_write(OUTPUT_DATA_REG, (hostdata->id_mask | (1 << cmd->device->id)));
+
+	/*
+	 * Raise ATN while SEL is true before BSY goes false from arbitration,
+	 * since this is the only way to guarantee that we'll get a MESSAGE OUT
+	 * phase immediately after selection.
+	 */
+
+	NCR5380_write(INITIATOR_COMMAND_REG, (ICR_BASE | ICR_ASSERT_BSY |
+		      ICR_ASSERT_DATA | ICR_ASSERT_ATN | ICR_ASSERT_SEL ));
 	NCR5380_write(MODE_REG, MR_BASE);
-	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
-	return -1;
-    }
 
-    ARB_PRINTK("scsi%d: won arbitration\n", HOSTNO);
+	/*
+	 * Reselect interrupts must be turned off prior to the dropping of BSY,
+	 * otherwise we will trigger an interrupt.
+	 */
 
-    /* 
-     * Now that we have won arbitration, start Selection process, asserting 
-     * the host and target ID's on the SCSI bus.
-     */
+	if (hostdata->connected) {
+		NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+		return -1;
+	}
 
-    NCR5380_write(OUTPUT_DATA_REG, (hostdata->id_mask | (1 << cmd->device->id)));
+	NCR5380_write(SELECT_ENABLE_REG, 0);
 
-    /* 
-     * Raise ATN while SEL is true before BSY goes false from arbitration,
-     * since this is the only way to guarantee that we'll get a MESSAGE OUT
-     * phase immediately after selection.
-     */
+	/*
+	 * The initiator shall then wait at least two deskew delays and release
+	 * the BSY signal.
+	 */
+	udelay(1);        /* wingel -- wait two bus deskew delay >2*45ns */
 
-    NCR5380_write(INITIATOR_COMMAND_REG, (ICR_BASE | ICR_ASSERT_BSY | 
-	ICR_ASSERT_DATA | ICR_ASSERT_ATN | ICR_ASSERT_SEL ));
-    NCR5380_write(MODE_REG, MR_BASE);
+	/* Reset BSY */
+	NCR5380_write(INITIATOR_COMMAND_REG, (ICR_BASE | ICR_ASSERT_DATA |
+		      ICR_ASSERT_ATN | ICR_ASSERT_SEL));
 
-    /* 
-     * Reselect interrupts must be turned off prior to the dropping of BSY,
-     * otherwise we will trigger an interrupt.
-     */
+	/*
+	 * Something weird happens when we cease to drive BSY - looks
+	 * like the board/chip is letting us do another read before the
+	 * appropriate propagation delay has expired, and we're confusing
+	 * a BSY signal from ourselves as the target's response to SELECTION.
+	 *
+	 * A small delay (the 'C++' frontend breaks the pipeline with an
+	 * unnecessary jump, making it work on my 386-33/Trantor T128, the
+	 * tighter 'C' code breaks and requires this) solves the problem -
+	 * the 1 us delay is arbitrary, and only used because this delay will
+	 * be the same on other platforms and since it works here, it should
+	 * work there.
+	 *
+	 * wingel suggests that this could be due to failing to wait
+	 * one deskew delay.
+	 */
 
-    if (hostdata->connected) {
-	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
-	return -1;
-    }
+	udelay(1);
 
-    NCR5380_write(SELECT_ENABLE_REG, 0);
+	SEL_PRINTK("scsi%d: selecting target %d\n", HOSTNO, cmd->device->id);
 
-    /*
-     * The initiator shall then wait at least two deskew delays and release 
-     * the BSY signal.
-     */
-    udelay(1);        /* wingel -- wait two bus deskew delay >2*45ns */
+	/*
+	 * The SCSI specification calls for a 250 ms timeout for the actual
+	 * selection.
+	 */
 
-    /* Reset BSY */
-    NCR5380_write(INITIATOR_COMMAND_REG, (ICR_BASE | ICR_ASSERT_DATA | 
-	ICR_ASSERT_ATN | ICR_ASSERT_SEL));
+	timeout = jiffies + 25;
 
-    /* 
-     * Something weird happens when we cease to drive BSY - looks
-     * like the board/chip is letting us do another read before the 
-     * appropriate propagation delay has expired, and we're confusing
-     * a BSY signal from ourselves as the target's response to SELECTION.
-     *
-     * A small delay (the 'C++' frontend breaks the pipeline with an
-     * unnecessary jump, making it work on my 386-33/Trantor T128, the
-     * tighter 'C' code breaks and requires this) solves the problem - 
-     * the 1 us delay is arbitrary, and only used because this delay will 
-     * be the same on other platforms and since it works here, it should 
-     * work there.
-     *
-     * wingel suggests that this could be due to failing to wait
-     * one deskew delay.
-     */
-
-    udelay(1);
-
-    SEL_PRINTK("scsi%d: selecting target %d\n", HOSTNO, cmd->device->id);
-
-    /* 
-     * The SCSI specification calls for a 250 ms timeout for the actual 
-     * selection.
-     */
-
-    timeout = jiffies + 25; 
-
-    /* 
-     * XXX very interesting - we're seeing a bounce where the BSY we 
-     * asserted is being reflected / still asserted (propagation delay?)
-     * and it's detecting as true.  Sigh.
-     */
+	/*
+	 * XXX very interesting - we're seeing a bounce where the BSY we
+	 * asserted is being reflected / still asserted (propagation delay?)
+	 * and it's detecting as true.  Sigh.
+	 */
 
 #if 0
-    /* ++roman: If a target conformed to the SCSI standard, it wouldn't assert
-     * IO while SEL is true. But again, there are some disks out the in the
-     * world that do that nevertheless. (Somebody claimed that this announces
-     * reselection capability of the target.) So we better skip that test and
-     * only wait for BSY... (Famous german words: Der Klügere gibt nach :-)
-     */
+	/* ++roman: If a target conformed to the SCSI standard, it wouldn't assert
+	 * IO while SEL is true. But again, there are some disks out the in the
+	 * world that do that nevertheless. (Somebody claimed that this announces
+	 * reselection capability of the target.) So we better skip that test and
+	 * only wait for BSY... (Famous german words: Der Klügere gibt nach :-)
+	 */
 
-    while (time_before(jiffies, timeout) && !(NCR5380_read(STATUS_REG) & 
-	(SR_BSY | SR_IO)));
+	while (time_before(jiffies, timeout) &&
+	       !(NCR5380_read(STATUS_REG) & (SR_BSY | SR_IO)))
+		;
 
-    if ((NCR5380_read(STATUS_REG) & (SR_SEL | SR_IO)) == 
-	    (SR_SEL | SR_IO)) {
-	    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
-	    NCR5380_reselect(instance);
-	    printk (KERN_ERR "scsi%d: reselection after won arbitration?\n",
-		    HOSTNO);
-	    NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
-	    return -1;
-    }
-#else
-    while (time_before(jiffies, timeout) && !(NCR5380_read(STATUS_REG) & SR_BSY));
-#endif
-
-    /* 
-     * No less than two deskew delays after the initiator detects the 
-     * BSY signal is true, it shall release the SEL signal and may 
-     * change the DATA BUS.                                     -wingel
-     */
-
-    udelay(1);
-
-    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
-
-    if (!(NCR5380_read(STATUS_REG) & SR_BSY)) {
-	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
-	if (hostdata->targets_present & (1 << cmd->device->id)) {
-	    printk(KERN_ERR "scsi%d: weirdness\n", HOSTNO);
-	    if (hostdata->restart_select)
-		printk(KERN_NOTICE "\trestart select\n");
-	    NCR_PRINT(NDEBUG_ANY);
-	    NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
-	    return -1;
+	if ((NCR5380_read(STATUS_REG) & (SR_SEL | SR_IO)) == (SR_SEL | SR_IO)) {
+		NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+		NCR5380_reselect(instance);
+		printk(KERN_ERR "scsi%d: reselection after won arbitration?\n",
+		       HOSTNO);
+		NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
+		return -1;
 	}
-	cmd->result = DID_BAD_TARGET << 16;
-#ifdef NCR5380_STATS
-	collect_stats(hostdata, cmd);
-#endif
-#ifdef SUPPORT_TAGS
-	cmd_free_tag( cmd );
-#endif
-	cmd->scsi_done(cmd);
-	NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
-	SEL_PRINTK("scsi%d: target did not respond within 250ms\n", HOSTNO);
-	NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
-	return 0;
-    } 
-
-    hostdata->targets_present |= (1 << cmd->device->id);
-
-    /*
-     * Since we followed the SCSI spec, and raised ATN while SEL 
-     * was true but before BSY was false during selection, the information
-     * transfer phase should be a MESSAGE OUT phase so that we can send the
-     * IDENTIFY message.
-     * 
-     * If SCSI-II tagged queuing is enabled, we also send a SIMPLE_QUEUE_TAG
-     * message (2 bytes) with a tag ID that we increment with every command
-     * until it wraps back to 0.
-     *
-     * XXX - it turns out that there are some broken SCSI-II devices,
-     *	     which claim to support tagged queuing but fail when more than
-     *	     some number of commands are issued at once.
-     */
-
-    /* Wait for start of REQ/ACK handshake */
-    while (!(NCR5380_read(STATUS_REG) & SR_REQ));
-
-    SEL_PRINTK("scsi%d: target %d selected, going into MESSAGE OUT phase.\n",
-	       HOSTNO, cmd->device->id);
-    tmp[0] = IDENTIFY(1, cmd->device->lun);
-
-#ifdef SUPPORT_TAGS
-    if (cmd->tag != TAG_NONE) {
-	tmp[1] = hostdata->last_message = SIMPLE_QUEUE_TAG;
-	tmp[2] = cmd->tag;
-	len = 3;
-    } else 
-	len = 1;
 #else
-    len = 1;
-    cmd->tag=0;
+	while (time_before(jiffies, timeout) && !(NCR5380_read(STATUS_REG) & SR_BSY))
+		;
+#endif
+
+	/*
+	 * No less than two deskew delays after the initiator detects the
+	 * BSY signal is true, it shall release the SEL signal and may
+	 * change the DATA BUS.                                     -wingel
+	 */
+
+	udelay(1);
+
+	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
+
+	if (!(NCR5380_read(STATUS_REG) & SR_BSY)) {
+		NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+		if (hostdata->targets_present & (1 << cmd->device->id)) {
+			printk(KERN_ERR "scsi%d: weirdness\n", HOSTNO);
+			if (hostdata->restart_select)
+				printk(KERN_NOTICE "\trestart select\n");
+			NCR_PRINT(NDEBUG_ANY);
+			NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
+			return -1;
+		}
+		cmd->result = DID_BAD_TARGET << 16;
+#ifdef NCR5380_STATS
+		collect_stats(hostdata, cmd);
+#endif
+#ifdef SUPPORT_TAGS
+		cmd_free_tag(cmd);
+#endif
+		cmd->scsi_done(cmd);
+		NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
+		SEL_PRINTK("scsi%d: target did not respond within 250ms\n", HOSTNO);
+		NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
+		return 0;
+	}
+
+	hostdata->targets_present |= (1 << cmd->device->id);
+
+	/*
+	 * Since we followed the SCSI spec, and raised ATN while SEL
+	 * was true but before BSY was false during selection, the information
+	 * transfer phase should be a MESSAGE OUT phase so that we can send the
+	 * IDENTIFY message.
+	 *
+	 * If SCSI-II tagged queuing is enabled, we also send a SIMPLE_QUEUE_TAG
+	 * message (2 bytes) with a tag ID that we increment with every command
+	 * until it wraps back to 0.
+	 *
+	 * XXX - it turns out that there are some broken SCSI-II devices,
+	 *	     which claim to support tagged queuing but fail when more than
+	 *	     some number of commands are issued at once.
+	 */
+
+	/* Wait for start of REQ/ACK handshake */
+	while (!(NCR5380_read(STATUS_REG) & SR_REQ))
+		;
+
+	SEL_PRINTK("scsi%d: target %d selected, going into MESSAGE OUT phase.\n",
+		   HOSTNO, cmd->device->id);
+	tmp[0] = IDENTIFY(1, cmd->device->lun);
+
+#ifdef SUPPORT_TAGS
+	if (cmd->tag != TAG_NONE) {
+		tmp[1] = hostdata->last_message = SIMPLE_QUEUE_TAG;
+		tmp[2] = cmd->tag;
+		len = 3;
+	} else
+		len = 1;
+#else
+	len = 1;
+	cmd->tag = 0;
 #endif /* SUPPORT_TAGS */
 
-    /* Send message(s) */
-    data = tmp;
-    phase = PHASE_MSGOUT;
-    NCR5380_transfer_pio(instance, &phase, &len, &data);
-    SEL_PRINTK("scsi%d: nexus established.\n", HOSTNO);
-    /* XXX need to handle errors here */
-    hostdata->connected = cmd;
+	/* Send message(s) */
+	data = tmp;
+	phase = PHASE_MSGOUT;
+	NCR5380_transfer_pio(instance, &phase, &len, &data);
+	SEL_PRINTK("scsi%d: nexus established.\n", HOSTNO);
+	/* XXX need to handle errors here */
+	hostdata->connected = cmd;
 #ifndef SUPPORT_TAGS
-    hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun);
-#endif    
+	hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun);
+#endif
 
-    initialize_SCp(cmd);
+	initialize_SCp(cmd);
 
-
-    return 0;
+	return 0;
 }
 
-/* 
- * Function : int NCR5380_transfer_pio (struct Scsi_Host *instance, 
+/*
+ * Function : int NCR5380_transfer_pio (struct Scsi_Host *instance,
  *      unsigned char *phase, int *count, unsigned char **data)
  *
  * Purpose : transfers data in given phase using polled I/O
  *
- * Inputs : instance - instance of driver, *phase - pointer to 
- *	what phase is expected, *count - pointer to number of 
+ * Inputs : instance - instance of driver, *phase - pointer to
+ *	what phase is expected, *count - pointer to number of
  *	bytes to transfer, **data - pointer to data pointer.
- * 
+ *
  * Returns : -1 when different phase is entered without transferring
  *	maximum number of bytes, 0 if all bytes are transfered or exit
  *	is in same phase.
  *
- * 	Also, *phase, *count, *data are modified in place.
+ *	Also, *phase, *count, *data are modified in place.
  *
  * XXX Note : handling for bus free may be useful.
  */
 
 /*
- * Note : this code is not as quick as it could be, however it 
+ * Note : this code is not as quick as it could be, however it
  * IS 100% reliable, and for the actual data transfer where speed
  * counts, we will always do a pseudo DMA or DMA transfer.
  */
 
-static int NCR5380_transfer_pio( struct Scsi_Host *instance, 
-				 unsigned char *phase, int *count,
-				 unsigned char **data)
+static int NCR5380_transfer_pio(struct Scsi_Host *instance,
+				unsigned char *phase, int *count,
+				unsigned char **data)
 {
-    register unsigned char p = *phase, tmp;
-    register int c = *count;
-    register unsigned char *d = *data;
+	register unsigned char p = *phase, tmp;
+	register int c = *count;
+	register unsigned char *d = *data;
 
-    /* 
-     * The NCR5380 chip will only drive the SCSI bus when the 
-     * phase specified in the appropriate bits of the TARGET COMMAND
-     * REGISTER match the STATUS REGISTER
-     */
-
-    NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(p));
-
-    do {
-	/* 
-	 * Wait for assertion of REQ, after which the phase bits will be 
-	 * valid 
-	 */
-	while (!((tmp = NCR5380_read(STATUS_REG)) & SR_REQ));
-
-	HSH_PRINTK("scsi%d: REQ detected\n", HOSTNO);
-
-	/* Check for phase mismatch */	
-	if ((tmp & PHASE_MASK) != p) {
-	    PIO_PRINTK("scsi%d: phase mismatch\n", HOSTNO);
-	    NCR_PRINT_PHASE(NDEBUG_PIO);
-	    break;
-	}
-
-	/* Do actual transfer from SCSI bus to / from memory */
-	if (!(p & SR_IO)) 
-	    NCR5380_write(OUTPUT_DATA_REG, *d);
-	else 
-	    *d = NCR5380_read(CURRENT_SCSI_DATA_REG);
-
-	++d;
-
-	/* 
-	 * The SCSI standard suggests that in MSGOUT phase, the initiator
-	 * should drop ATN on the last byte of the message phase
-	 * after REQ has been asserted for the handshake but before
-	 * the initiator raises ACK.
+	/*
+	 * The NCR5380 chip will only drive the SCSI bus when the
+	 * phase specified in the appropriate bits of the TARGET COMMAND
+	 * REGISTER match the STATUS REGISTER
 	 */
 
-	if (!(p & SR_IO)) {
-	    if (!((p & SR_MSG) && c > 1)) {
-		NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | 
-		    ICR_ASSERT_DATA);
-		NCR_PRINT(NDEBUG_PIO);
-		NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | 
-			ICR_ASSERT_DATA | ICR_ASSERT_ACK);
-	    } else {
-		NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE |
-		    ICR_ASSERT_DATA | ICR_ASSERT_ATN);
-		NCR_PRINT(NDEBUG_PIO);
-		NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | 
-		    ICR_ASSERT_DATA | ICR_ASSERT_ATN | ICR_ASSERT_ACK);
-	    }
-	} else {
-	    NCR_PRINT(NDEBUG_PIO);
-	    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ACK);
-	}
+	NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(p));
 
-	while (NCR5380_read(STATUS_REG) & SR_REQ);
+	do {
+		/*
+		 * Wait for assertion of REQ, after which the phase bits will be
+		 * valid
+		 */
+		while (!((tmp = NCR5380_read(STATUS_REG)) & SR_REQ))
+			;
 
-	HSH_PRINTK("scsi%d: req false, handshake complete\n", HOSTNO);
+		HSH_PRINTK("scsi%d: REQ detected\n", HOSTNO);
 
-/*
- * We have several special cases to consider during REQ/ACK handshaking : 
- * 1.  We were in MSGOUT phase, and we are on the last byte of the 
- *	message.  ATN must be dropped as ACK is dropped.
- *
- * 2.  We are in a MSGIN phase, and we are on the last byte of the  
- *	message.  We must exit with ACK asserted, so that the calling
- *	code may raise ATN before dropping ACK to reject the message.
- *
- * 3.  ACK and ATN are clear and the target may proceed as normal.
- */
-	if (!(p == PHASE_MSGIN && c == 1)) {  
-	    if (p == PHASE_MSGOUT && c > 1)
-		NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
-	    else
-		NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
-	} 
-    } while (--c);
+		/* Check for phase mismatch */
+		if ((tmp & PHASE_MASK) != p) {
+			PIO_PRINTK("scsi%d: phase mismatch\n", HOSTNO);
+			NCR_PRINT_PHASE(NDEBUG_PIO);
+			break;
+		}
 
-    PIO_PRINTK("scsi%d: residual %d\n", HOSTNO, c);
+		/* Do actual transfer from SCSI bus to / from memory */
+		if (!(p & SR_IO))
+			NCR5380_write(OUTPUT_DATA_REG, *d);
+		else
+			*d = NCR5380_read(CURRENT_SCSI_DATA_REG);
 
-    *count = c;
-    *data = d;
-    tmp = NCR5380_read(STATUS_REG);
-    /* The phase read from the bus is valid if either REQ is (already)
-     * asserted or if ACK hasn't been released yet. The latter is the case if
-     * we're in MSGIN and all wanted bytes have been received. */
-    if ((tmp & SR_REQ) || (p == PHASE_MSGIN && c == 0))
-	*phase = tmp & PHASE_MASK;
-    else 
-	*phase = PHASE_UNKNOWN;
+		++d;
 
-    if (!c || (*phase == p))
-	return 0;
-    else 
-	return -1;
+		/*
+		 * The SCSI standard suggests that in MSGOUT phase, the initiator
+		 * should drop ATN on the last byte of the message phase
+		 * after REQ has been asserted for the handshake but before
+		 * the initiator raises ACK.
+		 */
+
+		if (!(p & SR_IO)) {
+			if (!((p & SR_MSG) && c > 1)) {
+				NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA);
+				NCR_PRINT(NDEBUG_PIO);
+				NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE |
+					      ICR_ASSERT_DATA | ICR_ASSERT_ACK);
+			} else {
+				NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE |
+					      ICR_ASSERT_DATA | ICR_ASSERT_ATN);
+				NCR_PRINT(NDEBUG_PIO);
+				NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE |
+					      ICR_ASSERT_DATA | ICR_ASSERT_ATN | ICR_ASSERT_ACK);
+			}
+		} else {
+			NCR_PRINT(NDEBUG_PIO);
+			NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ACK);
+		}
+
+		while (NCR5380_read(STATUS_REG) & SR_REQ)
+			;
+
+		HSH_PRINTK("scsi%d: req false, handshake complete\n", HOSTNO);
+
+		/*
+		 * We have several special cases to consider during REQ/ACK handshaking :
+		 * 1.  We were in MSGOUT phase, and we are on the last byte of the
+		 *	message.  ATN must be dropped as ACK is dropped.
+		 *
+		 * 2.  We are in a MSGIN phase, and we are on the last byte of the
+		 *	message.  We must exit with ACK asserted, so that the calling
+		 *	code may raise ATN before dropping ACK to reject the message.
+		 *
+		 * 3.  ACK and ATN are clear and the target may proceed as normal.
+		 */
+		if (!(p == PHASE_MSGIN && c == 1)) {
+			if (p == PHASE_MSGOUT && c > 1)
+				NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
+			else
+				NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+		}
+	} while (--c);
+
+	PIO_PRINTK("scsi%d: residual %d\n", HOSTNO, c);
+
+	*count = c;
+	*data = d;
+	tmp = NCR5380_read(STATUS_REG);
+	/* The phase read from the bus is valid if either REQ is (already)
+	 * asserted or if ACK hasn't been released yet. The latter is the case if
+	 * we're in MSGIN and all wanted bytes have been received.
+	 */
+	if ((tmp & SR_REQ) || (p == PHASE_MSGIN && c == 0))
+		*phase = tmp & PHASE_MASK;
+	else
+		*phase = PHASE_UNKNOWN;
+
+	if (!c || (*phase == p))
+		return 0;
+	else
+		return -1;
 }
 
 /*
  * Function : do_abort (Scsi_Host *host)
- * 
- * Purpose : abort the currently established nexus.  Should only be 
- * 	called from a routine which can drop into a 
- * 
+ *
+ * Purpose : abort the currently established nexus.  Should only be
+ *	called from a routine which can drop into a
+ *
  * Returns : 0 on success, -1 on failure.
  */
 
-static int do_abort (struct Scsi_Host *host) 
+static int do_abort(struct Scsi_Host *host)
 {
-    unsigned char tmp, *msgptr, phase;
-    int len;
+	unsigned char tmp, *msgptr, phase;
+	int len;
 
-    /* Request message out phase */
-    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
-
-    /* 
-     * Wait for the target to indicate a valid phase by asserting 
-     * REQ.  Once this happens, we'll have either a MSGOUT phase 
-     * and can immediately send the ABORT message, or we'll have some 
-     * other phase and will have to source/sink data.
-     * 
-     * We really don't care what value was on the bus or what value
-     * the target sees, so we just handshake.
-     */
-    
-    while (!(tmp = NCR5380_read(STATUS_REG)) & SR_REQ);
-
-    NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(tmp));
-
-    if ((tmp & PHASE_MASK) != PHASE_MSGOUT) {
-	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN | 
-		      ICR_ASSERT_ACK);
-	while (NCR5380_read(STATUS_REG) & SR_REQ);
+	/* Request message out phase */
 	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
-    }
-   
-    tmp = ABORT;
-    msgptr = &tmp;
-    len = 1;
-    phase = PHASE_MSGOUT;
-    NCR5380_transfer_pio (host, &phase, &len, &msgptr);
 
-    /*
-     * If we got here, and the command completed successfully,
-     * we're about to go into bus free state.
-     */
+	/*
+	 * Wait for the target to indicate a valid phase by asserting
+	 * REQ.  Once this happens, we'll have either a MSGOUT phase
+	 * and can immediately send the ABORT message, or we'll have some
+	 * other phase and will have to source/sink data.
+	 *
+	 * We really don't care what value was on the bus or what value
+	 * the target sees, so we just handshake.
+	 */
 
-    return len ? -1 : 0;
+	while (!(tmp = NCR5380_read(STATUS_REG)) & SR_REQ)
+		;
+
+	NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(tmp));
+
+	if ((tmp & PHASE_MASK) != PHASE_MSGOUT) {
+		NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN |
+			      ICR_ASSERT_ACK);
+		while (NCR5380_read(STATUS_REG) & SR_REQ)
+			;
+		NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
+	}
+
+	tmp = ABORT;
+	msgptr = &tmp;
+	len = 1;
+	phase = PHASE_MSGOUT;
+	NCR5380_transfer_pio(host, &phase, &len, &msgptr);
+
+	/*
+	 * If we got here, and the command completed successfully,
+	 * we're about to go into bus free state.
+	 */
+
+	return len ? -1 : 0;
 }
 
 #if defined(REAL_DMA)
-/* 
- * Function : int NCR5380_transfer_dma (struct Scsi_Host *instance, 
+/*
+ * Function : int NCR5380_transfer_dma (struct Scsi_Host *instance,
  *      unsigned char *phase, int *count, unsigned char **data)
  *
  * Purpose : transfers data in given phase using either real
  *	or pseudo DMA.
  *
- * Inputs : instance - instance of driver, *phase - pointer to 
- *	what phase is expected, *count - pointer to number of 
+ * Inputs : instance - instance of driver, *phase - pointer to
+ *	what phase is expected, *count - pointer to number of
  *	bytes to transfer, **data - pointer to data pointer.
- * 
+ *
  * Returns : -1 when different phase is entered without transferring
  *	maximum number of bytes, 0 if all bytes or transfered or exit
  *	is in same phase.
  *
- * 	Also, *phase, *count, *data are modified in place.
+ *	Also, *phase, *count, *data are modified in place.
  *
  */
 
 
-static int NCR5380_transfer_dma( struct Scsi_Host *instance, 
-				 unsigned char *phase, int *count,
-				 unsigned char **data)
+static int NCR5380_transfer_dma(struct Scsi_Host *instance,
+				unsigned char *phase, int *count,
+				unsigned char **data)
 {
-    SETUP_HOSTDATA(instance);
-    register int c = *count;
-    register unsigned char p = *phase;
-    register unsigned char *d = *data;
-    unsigned char tmp;
-    unsigned long flags;
+	SETUP_HOSTDATA(instance);
+	register int c = *count;
+	register unsigned char p = *phase;
+	register unsigned char *d = *data;
+	unsigned char tmp;
+	unsigned long flags;
 
-    if ((tmp = (NCR5380_read(STATUS_REG) & PHASE_MASK)) != p) {
-        *phase = tmp;
-        return -1;
-    }
+	if ((tmp = (NCR5380_read(STATUS_REG) & PHASE_MASK)) != p) {
+		*phase = tmp;
+		return -1;
+	}
 
-    if (atari_read_overruns && (p & SR_IO)) {
-	c -= atari_read_overruns;
-    }
+	if (atari_read_overruns && (p & SR_IO))
+		c -= atari_read_overruns;
 
-    DMA_PRINTK("scsi%d: initializing DMA for %s, %d bytes %s %p\n",
-	       HOSTNO, (p & SR_IO) ? "reading" : "writing",
-	       c, (p & SR_IO) ? "to" : "from", d);
+	DMA_PRINTK("scsi%d: initializing DMA for %s, %d bytes %s %p\n",
+		   HOSTNO, (p & SR_IO) ? "reading" : "writing",
+		   c, (p & SR_IO) ? "to" : "from", d);
 
-    NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(p));
+	NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(p));
 
 #ifdef REAL_DMA
-    NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_ENABLE_EOP_INTR | MR_MONITOR_BSY);
+	NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_ENABLE_EOP_INTR | MR_MONITOR_BSY);
 #endif /* def REAL_DMA  */
 
-    if (IS_A_TT()) {
-	/* On the Medusa, it is a must to initialize the DMA before
-	 * starting the NCR. This is also the cleaner way for the TT.
-	 */
-	local_irq_save(flags);
-	hostdata->dma_len = (p & SR_IO) ?
-	    NCR5380_dma_read_setup(instance, d, c) : 
-	    NCR5380_dma_write_setup(instance, d, c);
-	local_irq_restore(flags);
-    }
-    
-    if (p & SR_IO)
-	NCR5380_write(START_DMA_INITIATOR_RECEIVE_REG, 0);
-    else {
-	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA);
-	NCR5380_write(START_DMA_SEND_REG, 0);
-    }
+	if (IS_A_TT()) {
+		/* On the Medusa, it is a must to initialize the DMA before
+		 * starting the NCR. This is also the cleaner way for the TT.
+		 */
+		local_irq_save(flags);
+		hostdata->dma_len = (p & SR_IO) ?
+			NCR5380_dma_read_setup(instance, d, c) :
+			NCR5380_dma_write_setup(instance, d, c);
+		local_irq_restore(flags);
+	}
 
-    if (!IS_A_TT()) {
-	/* On the Falcon, the DMA setup must be done after the last */
-	/* NCR access, else the DMA setup gets trashed!
-	 */
-	local_irq_save(flags);
-	hostdata->dma_len = (p & SR_IO) ?
-	    NCR5380_dma_read_setup(instance, d, c) : 
-	    NCR5380_dma_write_setup(instance, d, c);
-	local_irq_restore(flags);
-    }
-    return 0;
+	if (p & SR_IO)
+		NCR5380_write(START_DMA_INITIATOR_RECEIVE_REG, 0);
+	else {
+		NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA);
+		NCR5380_write(START_DMA_SEND_REG, 0);
+	}
+
+	if (!IS_A_TT()) {
+		/* On the Falcon, the DMA setup must be done after the last */
+		/* NCR access, else the DMA setup gets trashed!
+		 */
+		local_irq_save(flags);
+		hostdata->dma_len = (p & SR_IO) ?
+			NCR5380_dma_read_setup(instance, d, c) :
+			NCR5380_dma_write_setup(instance, d, c);
+		local_irq_restore(flags);
+	}
+	return 0;
 }
 #endif /* defined(REAL_DMA) */
 
 /*
  * Function : NCR5380_information_transfer (struct Scsi_Host *instance)
  *
- * Purpose : run through the various SCSI phases and do as the target 
- * 	directs us to.  Operates on the currently connected command, 
+ * Purpose : run through the various SCSI phases and do as the target
+ *	directs us to.  Operates on the currently connected command,
  *	instance->connected.
  *
  * Inputs : instance, instance for which we are doing commands
  *
- * Side effects : SCSI things happen, the disconnected queue will be 
+ * Side effects : SCSI things happen, the disconnected queue will be
  *	modified if a command disconnects, *instance->connected will
  *	change.
  *
- * XXX Note : we need to watch for bus free or a reset condition here 
- * 	to recover from an unexpected bus free condition.
+ * XXX Note : we need to watch for bus free or a reset condition here
+ *	to recover from an unexpected bus free condition.
  */
- 
-static void NCR5380_information_transfer (struct Scsi_Host *instance)
+
+static void NCR5380_information_transfer(struct Scsi_Host *instance)
 {
-    SETUP_HOSTDATA(instance);
-    unsigned long flags;
-    unsigned char msgout = NOP;
-    int sink = 0;
-    int len;
+	SETUP_HOSTDATA(instance);
+	unsigned long flags;
+	unsigned char msgout = NOP;
+	int sink = 0;
+	int len;
 #if defined(REAL_DMA)
-    int transfersize;
+	int transfersize;
 #endif
-    unsigned char *data;
-    unsigned char phase, tmp, extended_msg[10], old_phase=0xff;
-    Scsi_Cmnd *cmd = (Scsi_Cmnd *) hostdata->connected;
+	unsigned char *data;
+	unsigned char phase, tmp, extended_msg[10], old_phase = 0xff;
+	Scsi_Cmnd *cmd = (Scsi_Cmnd *) hostdata->connected;
 
-    while (1) {
-	tmp = NCR5380_read(STATUS_REG);
-	/* We only have a valid SCSI phase when REQ is asserted */
-	if (tmp & SR_REQ) {
-	    phase = (tmp & PHASE_MASK); 
-	    if (phase != old_phase) {
-		old_phase = phase;
-		NCR_PRINT_PHASE(NDEBUG_INFORMATION);
-	    }
-	    
-	    if (sink && (phase != PHASE_MSGOUT)) {
-		NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(tmp));
-
-		NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN | 
-		    ICR_ASSERT_ACK);
-		while (NCR5380_read(STATUS_REG) & SR_REQ);
-		NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | 
-		    ICR_ASSERT_ATN);
-		sink = 0;
-		continue;
-	    }
-
-	    switch (phase) {
-	    case PHASE_DATAOUT:
-#if (NDEBUG & NDEBUG_NO_DATAOUT)
-		printk("scsi%d: NDEBUG_NO_DATAOUT set, attempted DATAOUT "
-		       "aborted\n", HOSTNO);
-		sink = 1;
-		do_abort(instance);
-		cmd->result = DID_ERROR  << 16;
-		cmd->done(cmd);
-		return;
-#endif
-	    case PHASE_DATAIN:
-		/* 
-		 * If there is no room left in the current buffer in the
-		 * scatter-gather list, move onto the next one.
-		 */
-
-		if (!cmd->SCp.this_residual && cmd->SCp.buffers_residual) {
-		    ++cmd->SCp.buffer;
-		    --cmd->SCp.buffers_residual;
-		    cmd->SCp.this_residual = cmd->SCp.buffer->length;
-		    cmd->SCp.ptr = page_address(cmd->SCp.buffer->page)+
-				   cmd->SCp.buffer->offset;
-		    /* ++roman: Try to merge some scatter-buffers if
-		     * they are at contiguous physical addresses.
-		     */
-		    merge_contiguous_buffers( cmd );
-		    INF_PRINTK("scsi%d: %d bytes and %d buffers left\n",
-			       HOSTNO, cmd->SCp.this_residual,
-			       cmd->SCp.buffers_residual);
-		}
-
-		/*
-		 * The preferred transfer method is going to be 
-		 * PSEUDO-DMA for systems that are strictly PIO,
-		 * since we can let the hardware do the handshaking.
-		 *
-		 * For this to work, we need to know the transfersize
-		 * ahead of time, since the pseudo-DMA code will sit
-		 * in an unconditional loop.
-		 */
-
-/* ++roman: I suggest, this should be
- *   #if def(REAL_DMA)
- * instead of leaving REAL_DMA out.
- */
-
-#if defined(REAL_DMA)
-		if (!cmd->device->borken &&
-		    (transfersize = NCR5380_dma_xfer_len(instance,cmd,phase)) > 31) {
-		    len = transfersize;
-		    cmd->SCp.phase = phase;
-		    if (NCR5380_transfer_dma(instance, &phase,
-			&len, (unsigned char **) &cmd->SCp.ptr)) {
-			/*
-			 * If the watchdog timer fires, all future
-			 * accesses to this device will use the
-			 * polled-IO. */ 
-			printk(KERN_NOTICE "scsi%d: switching target %d "
-			       "lun %d to slow handshake\n", HOSTNO,
-			       cmd->device->id, cmd->device->lun);
-			cmd->device->borken = 1;
-			NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | 
-			    ICR_ASSERT_ATN);
-			sink = 1;
-			do_abort(instance);
-			cmd->result = DID_ERROR  << 16;
-			cmd->done(cmd);
-			/* XXX - need to source or sink data here, as appropriate */
-		    } else {
-#ifdef REAL_DMA
-			/* ++roman: When using real DMA,
-			 * information_transfer() should return after
-			 * starting DMA since it has nothing more to
-			 * do.
-			 */
-			return;
-#else			
-			cmd->SCp.this_residual -= transfersize - len;
-#endif
-		    }
-		} else
-#endif /* defined(REAL_DMA) */
-		  NCR5380_transfer_pio(instance, &phase, 
-		    (int *) &cmd->SCp.this_residual, (unsigned char **)
-		    &cmd->SCp.ptr);
-		break;
-	    case PHASE_MSGIN:
-		len = 1;
-		data = &tmp;
-		NCR5380_write(SELECT_ENABLE_REG, 0); 	/* disable reselects */
-		NCR5380_transfer_pio(instance, &phase, &len, &data);
-		cmd->SCp.Message = tmp;
-
-		switch (tmp) {
-		/*
-		 * Linking lets us reduce the time required to get the 
-		 * next command out to the device, hopefully this will
-		 * mean we don't waste another revolution due to the delays
-		 * required by ARBITRATION and another SELECTION.
-		 *
-		 * In the current implementation proposal, low level drivers
-		 * merely have to start the next command, pointed to by 
-		 * next_link, done() is called as with unlinked commands.
-		 */
-#ifdef LINKED
-		case LINKED_CMD_COMPLETE:
-		case LINKED_FLG_CMD_COMPLETE:
-		    /* Accept message by clearing ACK */
-		    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
-		    
-		    LNK_PRINTK("scsi%d: target %d lun %d linked command "
-			       "complete.\n", HOSTNO, cmd->device->id, cmd->device->lun);
-
-		    /* Enable reselect interrupts */
-		    NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
-		    /*
-		     * Sanity check : A linked command should only terminate
-		     * with one of these messages if there are more linked
-		     * commands available.
-		     */
-
-		    if (!cmd->next_link) {
-			 printk(KERN_NOTICE "scsi%d: target %d lun %d "
-				"linked command complete, no next_link\n",
-				HOSTNO, cmd->device->id, cmd->device->lun);
-			    sink = 1;
-			    do_abort (instance);
-			    return;
-		    }
-
-		    initialize_SCp(cmd->next_link);
-		    /* The next command is still part of this process; copy it
-		     * and don't free it! */
-		    cmd->next_link->tag = cmd->tag;
-		    cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8); 
-		    LNK_PRINTK("scsi%d: target %d lun %d linked request "
-			       "done, calling scsi_done().\n",
-			       HOSTNO, cmd->device->id, cmd->device->lun);
-#ifdef NCR5380_STATS
-		    collect_stats(hostdata, cmd);
-#endif
-		    cmd->scsi_done(cmd);
-		    cmd = hostdata->connected;
-		    break;
-#endif /* def LINKED */
-		case ABORT:
-		case COMMAND_COMPLETE: 
-		    /* Accept message by clearing ACK */
-		    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
-		    /* ++guenther: possible race with Falcon locking */
-		    falcon_dont_release++;
-		    hostdata->connected = NULL;
-		    QU_PRINTK("scsi%d: command for target %d, lun %d "
-			      "completed\n", HOSTNO, cmd->device->id, cmd->device->lun);
-#ifdef SUPPORT_TAGS
-		    cmd_free_tag( cmd );
-		    if (status_byte(cmd->SCp.Status) == QUEUE_FULL) {
-			/* Turn a QUEUE FULL status into BUSY, I think the
-			 * mid level cannot handle QUEUE FULL :-( (The
-			 * command is retried after BUSY). Also update our
-			 * queue size to the number of currently issued
-			 * commands now.
-			 */
-			/* ++Andreas: the mid level code knows about
-			   QUEUE_FULL now. */
-			TAG_ALLOC *ta = &TagAlloc[cmd->device->id][cmd->device->lun];
-			TAG_PRINTK("scsi%d: target %d lun %d returned "
-				   "QUEUE_FULL after %d commands\n",
-				   HOSTNO, cmd->device->id, cmd->device->lun,
-				   ta->nr_allocated);
-			if (ta->queue_size > ta->nr_allocated)
-			    ta->nr_allocated = ta->queue_size;
-		    }
-#else
-		    hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun);
-#endif
-		    /* Enable reselect interrupts */
-		    NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
-
-		    /* 
-		     * I'm not sure what the correct thing to do here is : 
-		     * 
-		     * If the command that just executed is NOT a request 
-		     * sense, the obvious thing to do is to set the result
-		     * code to the values of the stored parameters.
-		     * 
-		     * If it was a REQUEST SENSE command, we need some way to
-		     * differentiate between the failure code of the original
-		     * and the failure code of the REQUEST sense - the obvious
-		     * case is success, where we fall through and leave the
-		     * result code unchanged.
-		     * 
-		     * The non-obvious place is where the REQUEST SENSE failed
-		     */
-
-		    if (cmd->cmnd[0] != REQUEST_SENSE) 
-			cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8); 
-		    else if (status_byte(cmd->SCp.Status) != GOOD)
-			cmd->result = (cmd->result & 0x00ffff) | (DID_ERROR << 16);
-		    
-#ifdef AUTOSENSE
-		    if ((cmd->cmnd[0] != REQUEST_SENSE) && 
-			(status_byte(cmd->SCp.Status) == CHECK_CONDITION)) {
-			ASEN_PRINTK("scsi%d: performing request sense\n",
-				    HOSTNO);
-			cmd->cmnd[0] = REQUEST_SENSE;
-			cmd->cmnd[1] &= 0xe0;
-			cmd->cmnd[2] = 0;
-			cmd->cmnd[3] = 0;
-			cmd->cmnd[4] = sizeof(cmd->sense_buffer);
-			cmd->cmnd[5] = 0;
-			cmd->cmd_len = COMMAND_SIZE(cmd->cmnd[0]);
-
-			cmd->use_sg = 0;
-			/* this is initialized from initialize_SCp 
-			cmd->SCp.buffer = NULL;
-			cmd->SCp.buffers_residual = 0;
-			*/
-			cmd->request_buffer = (char *) cmd->sense_buffer;
-			cmd->request_bufflen = sizeof(cmd->sense_buffer);
-
-			local_irq_save(flags);
-			LIST(cmd,hostdata->issue_queue);
-			NEXT(cmd) = hostdata->issue_queue;
-		        hostdata->issue_queue = (Scsi_Cmnd *) cmd;
-		        local_irq_restore(flags);
-			QU_PRINTK("scsi%d: REQUEST SENSE added to head of "
-				  "issue queue\n", H_NO(cmd));
-		   } else
-#endif /* def AUTOSENSE */
-		   {
-#ifdef NCR5380_STATS
-		       collect_stats(hostdata, cmd);
-#endif
-		       cmd->scsi_done(cmd);
-		    }
-
-		    NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
-		    /* 
-		     * Restore phase bits to 0 so an interrupted selection, 
-		     * arbitration can resume.
-		     */
-		    NCR5380_write(TARGET_COMMAND_REG, 0);
-		    
-		    while ((NCR5380_read(STATUS_REG) & SR_BSY) && !hostdata->connected)
-			barrier();
-
-		    falcon_dont_release--;
-		    /* ++roman: For Falcon SCSI, release the lock on the
-		     * ST-DMA here if no other commands are waiting on the
-		     * disconnected queue.
-		     */
-		    falcon_release_lock_if_possible( hostdata );
-		    return;
-		case MESSAGE_REJECT:
-		    /* Accept message by clearing ACK */
-		    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
-		    /* Enable reselect interrupts */
-		    NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
-		    switch (hostdata->last_message) {
-		    case HEAD_OF_QUEUE_TAG:
-		    case ORDERED_QUEUE_TAG:
-		    case SIMPLE_QUEUE_TAG:
-			/* The target obviously doesn't support tagged
-			 * queuing, even though it announced this ability in
-			 * its INQUIRY data ?!? (maybe only this LUN?) Ok,
-			 * clear 'tagged_supported' and lock the LUN, since
-			 * the command is treated as untagged further on.
-			 */
-			cmd->device->tagged_supported = 0;
-			hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun);
-			cmd->tag = TAG_NONE;
-			TAG_PRINTK("scsi%d: target %d lun %d rejected "
-				   "QUEUE_TAG message; tagged queuing "
-				   "disabled\n",
-				   HOSTNO, cmd->device->id, cmd->device->lun);
-			break;
-		    }
-		    break;
-		case DISCONNECT:
-		    /* Accept message by clearing ACK */
-		    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
-		    local_irq_save(flags);
-		    cmd->device->disconnect = 1;
-		    LIST(cmd,hostdata->disconnected_queue);
-		    NEXT(cmd) = hostdata->disconnected_queue;
-		    hostdata->connected = NULL;
-		    hostdata->disconnected_queue = cmd;
-		    local_irq_restore(flags);
-		    QU_PRINTK("scsi%d: command for target %d lun %d was "
-			      "moved from connected to the "
-			      "disconnected_queue\n", HOSTNO, 
-			      cmd->device->id, cmd->device->lun);
-		    /* 
-		     * Restore phase bits to 0 so an interrupted selection, 
-		     * arbitration can resume.
-		     */
-		    NCR5380_write(TARGET_COMMAND_REG, 0);
-
-		    /* Enable reselect interrupts */
-		    NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
-		    /* Wait for bus free to avoid nasty timeouts */
-		    while ((NCR5380_read(STATUS_REG) & SR_BSY) && !hostdata->connected)
-		    	barrier();
-		    return;
-		/* 
-		 * The SCSI data pointer is *IMPLICITLY* saved on a disconnect
-		 * operation, in violation of the SCSI spec so we can safely 
-		 * ignore SAVE/RESTORE pointers calls.
-		 *
-		 * Unfortunately, some disks violate the SCSI spec and 
-		 * don't issue the required SAVE_POINTERS message before
-		 * disconnecting, and we have to break spec to remain 
-		 * compatible.
-		 */
-		case SAVE_POINTERS:
-		case RESTORE_POINTERS:
-		    /* Accept message by clearing ACK */
-		    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
-		    /* Enable reselect interrupts */
-		    NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
-		    break;
-		case EXTENDED_MESSAGE:
-/* 
- * Extended messages are sent in the following format :
- * Byte 	
- * 0		EXTENDED_MESSAGE == 1
- * 1		length (includes one byte for code, doesn't 
- *		include first two bytes)
- * 2 		code
- * 3..length+1	arguments
- *
- * Start the extended message buffer with the EXTENDED_MESSAGE
- * byte, since spi_print_msg() wants the whole thing.  
- */
-		    extended_msg[0] = EXTENDED_MESSAGE;
-		    /* Accept first byte by clearing ACK */
-		    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
-
-		    EXT_PRINTK("scsi%d: receiving extended message\n", HOSTNO);
-
-		    len = 2;
-		    data = extended_msg + 1;
-		    phase = PHASE_MSGIN;
-		    NCR5380_transfer_pio(instance, &phase, &len, &data);
-		    EXT_PRINTK("scsi%d: length=%d, code=0x%02x\n", HOSTNO,
-			       (int)extended_msg[1], (int)extended_msg[2]);
-
-		    if (!len && extended_msg[1] <= 
-			(sizeof (extended_msg) - 1)) {
-			/* Accept third byte by clearing ACK */
-			NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
-			len = extended_msg[1] - 1;
-			data = extended_msg + 3;
-			phase = PHASE_MSGIN;
-
-			NCR5380_transfer_pio(instance, &phase, &len, &data);
-			EXT_PRINTK("scsi%d: message received, residual %d\n",
-				   HOSTNO, len);
-
-			switch (extended_msg[2]) {
-			case EXTENDED_SDTR:
-			case EXTENDED_WDTR:
-			case EXTENDED_MODIFY_DATA_POINTER:
-			case EXTENDED_EXTENDED_IDENTIFY:
-			    tmp = 0;
+	while (1) {
+		tmp = NCR5380_read(STATUS_REG);
+		/* We only have a valid SCSI phase when REQ is asserted */
+		if (tmp & SR_REQ) {
+			phase = (tmp & PHASE_MASK);
+			if (phase != old_phase) {
+				old_phase = phase;
+				NCR_PRINT_PHASE(NDEBUG_INFORMATION);
 			}
-		    } else if (len) {
-			printk(KERN_NOTICE "scsi%d: error receiving "
-			       "extended message\n", HOSTNO);
-			tmp = 0;
-		    } else {
-			printk(KERN_NOTICE "scsi%d: extended message "
-			       "code %02x length %d is too long\n",
-			       HOSTNO, extended_msg[2], extended_msg[1]);
-			tmp = 0;
-		    }
-		/* Fall through to reject message */
 
-		/* 
-  		 * If we get something weird that we aren't expecting, 
- 		 * reject it.
-		 */
-		default:
-		    if (!tmp) {
-			printk(KERN_DEBUG "scsi%d: rejecting message ", HOSTNO);
-			spi_print_msg(extended_msg);
-			printk("\n");
-		    } else if (tmp != EXTENDED_MESSAGE)
-			printk(KERN_DEBUG "scsi%d: rejecting unknown "
-			       "message %02x from target %d, lun %d\n",
-			       HOSTNO, tmp, cmd->device->id, cmd->device->lun);
-		    else
-			printk(KERN_DEBUG "scsi%d: rejecting unknown "
-			       "extended message "
-			       "code %02x, length %d from target %d, lun %d\n",
-			       HOSTNO, extended_msg[1], extended_msg[0],
-			       cmd->device->id, cmd->device->lun);
-   
+			if (sink && (phase != PHASE_MSGOUT)) {
+				NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(tmp));
 
-		    msgout = MESSAGE_REJECT;
-		    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | 
-			ICR_ASSERT_ATN);
-		    break;
-		} /* switch (tmp) */
-		break;
-	    case PHASE_MSGOUT:
-		len = 1;
-		data = &msgout;
-		hostdata->last_message = msgout;
-		NCR5380_transfer_pio(instance, &phase, &len, &data);
-		if (msgout == ABORT) {
-#ifdef SUPPORT_TAGS
-		    cmd_free_tag( cmd );
+				NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN |
+					      ICR_ASSERT_ACK);
+				while (NCR5380_read(STATUS_REG) & SR_REQ)
+					;
+				NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE |
+					      ICR_ASSERT_ATN);
+				sink = 0;
+				continue;
+			}
+
+			switch (phase) {
+			case PHASE_DATAOUT:
+#if (NDEBUG & NDEBUG_NO_DATAOUT)
+				printk("scsi%d: NDEBUG_NO_DATAOUT set, attempted DATAOUT "
+				       "aborted\n", HOSTNO);
+				sink = 1;
+				do_abort(instance);
+				cmd->result = DID_ERROR << 16;
+				cmd->done(cmd);
+				return;
+#endif
+			case PHASE_DATAIN:
+				/*
+				 * If there is no room left in the current buffer in the
+				 * scatter-gather list, move onto the next one.
+				 */
+
+				if (!cmd->SCp.this_residual && cmd->SCp.buffers_residual) {
+					++cmd->SCp.buffer;
+					--cmd->SCp.buffers_residual;
+					cmd->SCp.this_residual = cmd->SCp.buffer->length;
+					cmd->SCp.ptr = page_address(cmd->SCp.buffer->page) +
+						   cmd->SCp.buffer->offset;
+					/* ++roman: Try to merge some scatter-buffers if
+					 * they are at contiguous physical addresses.
+					 */
+					merge_contiguous_buffers(cmd);
+					INF_PRINTK("scsi%d: %d bytes and %d buffers left\n",
+						   HOSTNO, cmd->SCp.this_residual,
+						   cmd->SCp.buffers_residual);
+				}
+
+				/*
+				 * The preferred transfer method is going to be
+				 * PSEUDO-DMA for systems that are strictly PIO,
+				 * since we can let the hardware do the handshaking.
+				 *
+				 * For this to work, we need to know the transfersize
+				 * ahead of time, since the pseudo-DMA code will sit
+				 * in an unconditional loop.
+				 */
+
+				/* ++roman: I suggest, this should be
+				 *   #if def(REAL_DMA)
+				 * instead of leaving REAL_DMA out.
+				 */
+
+#if defined(REAL_DMA)
+				if (!cmd->device->borken &&
+				    (transfersize = NCR5380_dma_xfer_len(instance,cmd,phase)) > 31) {
+					len = transfersize;
+					cmd->SCp.phase = phase;
+					if (NCR5380_transfer_dma(instance, &phase,
+					    &len, (unsigned char **)&cmd->SCp.ptr)) {
+						/*
+						 * If the watchdog timer fires, all future
+						 * accesses to this device will use the
+						 * polled-IO. */
+						printk(KERN_NOTICE "scsi%d: switching target %d "
+							   "lun %d to slow handshake\n", HOSTNO,
+							   cmd->device->id, cmd->device->lun);
+						cmd->device->borken = 1;
+						NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE |
+							ICR_ASSERT_ATN);
+						sink = 1;
+						do_abort(instance);
+						cmd->result = DID_ERROR << 16;
+						cmd->done(cmd);
+						/* XXX - need to source or sink data here, as appropriate */
+					} else {
+#ifdef REAL_DMA
+						/* ++roman: When using real DMA,
+						 * information_transfer() should return after
+						 * starting DMA since it has nothing more to
+						 * do.
+						 */
+						return;
 #else
-		    hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun);
+						cmd->SCp.this_residual -= transfersize - len;
 #endif
-		    hostdata->connected = NULL;
-		    cmd->result = DID_ERROR << 16;
+					}
+				} else
+#endif /* defined(REAL_DMA) */
+					NCR5380_transfer_pio(instance, &phase,
+							     (int *)&cmd->SCp.this_residual,
+							     (unsigned char **)&cmd->SCp.ptr);
+				break;
+			case PHASE_MSGIN:
+				len = 1;
+				data = &tmp;
+				NCR5380_write(SELECT_ENABLE_REG, 0);	/* disable reselects */
+				NCR5380_transfer_pio(instance, &phase, &len, &data);
+				cmd->SCp.Message = tmp;
+
+				switch (tmp) {
+				/*
+				 * Linking lets us reduce the time required to get the
+				 * next command out to the device, hopefully this will
+				 * mean we don't waste another revolution due to the delays
+				 * required by ARBITRATION and another SELECTION.
+				 *
+				 * In the current implementation proposal, low level drivers
+				 * merely have to start the next command, pointed to by
+				 * next_link, done() is called as with unlinked commands.
+				 */
+#ifdef LINKED
+				case LINKED_CMD_COMPLETE:
+				case LINKED_FLG_CMD_COMPLETE:
+					/* Accept message by clearing ACK */
+					NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+
+					LNK_PRINTK("scsi%d: target %d lun %d linked command "
+						   "complete.\n", HOSTNO, cmd->device->id, cmd->device->lun);
+
+					/* Enable reselect interrupts */
+					NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
+					/*
+					 * Sanity check : A linked command should only terminate
+					 * with one of these messages if there are more linked
+					 * commands available.
+					 */
+
+					if (!cmd->next_link) {
+						 printk(KERN_NOTICE "scsi%d: target %d lun %d "
+							"linked command complete, no next_link\n",
+							HOSTNO, cmd->device->id, cmd->device->lun);
+						sink = 1;
+						do_abort(instance);
+						return;
+					}
+
+					initialize_SCp(cmd->next_link);
+					/* The next command is still part of this process; copy it
+					 * and don't free it! */
+					cmd->next_link->tag = cmd->tag;
+					cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8);
+					LNK_PRINTK("scsi%d: target %d lun %d linked request "
+						   "done, calling scsi_done().\n",
+						   HOSTNO, cmd->device->id, cmd->device->lun);
 #ifdef NCR5380_STATS
-		    collect_stats(hostdata, cmd);
+					collect_stats(hostdata, cmd);
 #endif
-		    cmd->scsi_done(cmd);
-		    NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
-		    falcon_release_lock_if_possible( hostdata );
-		    return;
-		}
-		msgout = NOP;
-		break;
-	    case PHASE_CMDOUT:
-		len = cmd->cmd_len;
-		data = cmd->cmnd;
-		/* 
-		 * XXX for performance reasons, on machines with a 
-		 * PSEUDO-DMA architecture we should probably 
-		 * use the dma transfer function.  
-		 */
-		NCR5380_transfer_pio(instance, &phase, &len, 
-		    &data);
-		break;
-	    case PHASE_STATIN:
-		len = 1;
-		data = &tmp;
-		NCR5380_transfer_pio(instance, &phase, &len, &data);
-		cmd->SCp.Status = tmp;
-		break;
-	    default:
-		printk("scsi%d: unknown phase\n", HOSTNO);
-		NCR_PRINT(NDEBUG_ANY);
-	    } /* switch(phase) */
-	} /* if (tmp * SR_REQ) */ 
-    } /* while (1) */
+					cmd->scsi_done(cmd);
+					cmd = hostdata->connected;
+					break;
+#endif /* def LINKED */
+				case ABORT:
+				case COMMAND_COMPLETE:
+					/* Accept message by clearing ACK */
+					NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+					/* ++guenther: possible race with Falcon locking */
+					falcon_dont_release++;
+					hostdata->connected = NULL;
+					QU_PRINTK("scsi%d: command for target %d, lun %d "
+						  "completed\n", HOSTNO, cmd->device->id, cmd->device->lun);
+#ifdef SUPPORT_TAGS
+					cmd_free_tag(cmd);
+					if (status_byte(cmd->SCp.Status) == QUEUE_FULL) {
+						/* Turn a QUEUE FULL status into BUSY, I think the
+						 * mid level cannot handle QUEUE FULL :-( (The
+						 * command is retried after BUSY). Also update our
+						 * queue size to the number of currently issued
+						 * commands now.
+						 */
+						/* ++Andreas: the mid level code knows about
+						   QUEUE_FULL now. */
+						TAG_ALLOC *ta = &TagAlloc[cmd->device->id][cmd->device->lun];
+						TAG_PRINTK("scsi%d: target %d lun %d returned "
+							   "QUEUE_FULL after %d commands\n",
+							   HOSTNO, cmd->device->id, cmd->device->lun,
+							   ta->nr_allocated);
+						if (ta->queue_size > ta->nr_allocated)
+							ta->nr_allocated = ta->queue_size;
+					}
+#else
+					hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun);
+#endif
+					/* Enable reselect interrupts */
+					NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
+
+					/*
+					 * I'm not sure what the correct thing to do here is :
+					 *
+					 * If the command that just executed is NOT a request
+					 * sense, the obvious thing to do is to set the result
+					 * code to the values of the stored parameters.
+					 *
+					 * If it was a REQUEST SENSE command, we need some way to
+					 * differentiate between the failure code of the original
+					 * and the failure code of the REQUEST sense - the obvious
+					 * case is success, where we fall through and leave the
+					 * result code unchanged.
+					 *
+					 * The non-obvious place is where the REQUEST SENSE failed
+					 */
+
+					if (cmd->cmnd[0] != REQUEST_SENSE)
+						cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8);
+					else if (status_byte(cmd->SCp.Status) != GOOD)
+						cmd->result = (cmd->result & 0x00ffff) | (DID_ERROR << 16);
+
+#ifdef AUTOSENSE
+					if ((cmd->cmnd[0] != REQUEST_SENSE) &&
+					    (status_byte(cmd->SCp.Status) == CHECK_CONDITION)) {
+						ASEN_PRINTK("scsi%d: performing request sense\n", HOSTNO);
+						cmd->cmnd[0] = REQUEST_SENSE;
+						cmd->cmnd[1] &= 0xe0;
+						cmd->cmnd[2] = 0;
+						cmd->cmnd[3] = 0;
+						cmd->cmnd[4] = sizeof(cmd->sense_buffer);
+						cmd->cmnd[5] = 0;
+						cmd->cmd_len = COMMAND_SIZE(cmd->cmnd[0]);
+
+						cmd->use_sg = 0;
+						/* this is initialized from initialize_SCp
+						cmd->SCp.buffer = NULL;
+						cmd->SCp.buffers_residual = 0;
+						*/
+						cmd->request_buffer = (char *) cmd->sense_buffer;
+						cmd->request_bufflen = sizeof(cmd->sense_buffer);
+
+						local_irq_save(flags);
+						LIST(cmd,hostdata->issue_queue);
+						SET_NEXT(cmd, hostdata->issue_queue);
+						hostdata->issue_queue = (Scsi_Cmnd *) cmd;
+						local_irq_restore(flags);
+						QU_PRINTK("scsi%d: REQUEST SENSE added to head of "
+							  "issue queue\n", H_NO(cmd));
+					} else
+#endif /* def AUTOSENSE */
+					{
+#ifdef NCR5380_STATS
+						collect_stats(hostdata, cmd);
+#endif
+						cmd->scsi_done(cmd);
+					}
+
+					NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
+					/*
+					 * Restore phase bits to 0 so an interrupted selection,
+					 * arbitration can resume.
+					 */
+					NCR5380_write(TARGET_COMMAND_REG, 0);
+
+					while ((NCR5380_read(STATUS_REG) & SR_BSY) && !hostdata->connected)
+						barrier();
+
+					falcon_dont_release--;
+					/* ++roman: For Falcon SCSI, release the lock on the
+					 * ST-DMA here if no other commands are waiting on the
+					 * disconnected queue.
+					 */
+					falcon_release_lock_if_possible(hostdata);
+					return;
+				case MESSAGE_REJECT:
+					/* Accept message by clearing ACK */
+					NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+					/* Enable reselect interrupts */
+					NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
+					switch (hostdata->last_message) {
+					case HEAD_OF_QUEUE_TAG:
+					case ORDERED_QUEUE_TAG:
+					case SIMPLE_QUEUE_TAG:
+						/* The target obviously doesn't support tagged
+						 * queuing, even though it announced this ability in
+						 * its INQUIRY data ?!? (maybe only this LUN?) Ok,
+						 * clear 'tagged_supported' and lock the LUN, since
+						 * the command is treated as untagged further on.
+						 */
+						cmd->device->tagged_supported = 0;
+						hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun);
+						cmd->tag = TAG_NONE;
+						TAG_PRINTK("scsi%d: target %d lun %d rejected "
+							   "QUEUE_TAG message; tagged queuing "
+							   "disabled\n",
+							   HOSTNO, cmd->device->id, cmd->device->lun);
+						break;
+					}
+					break;
+				case DISCONNECT:
+					/* Accept message by clearing ACK */
+					NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+					local_irq_save(flags);
+					cmd->device->disconnect = 1;
+					LIST(cmd,hostdata->disconnected_queue);
+					SET_NEXT(cmd, hostdata->disconnected_queue);
+					hostdata->connected = NULL;
+					hostdata->disconnected_queue = cmd;
+					local_irq_restore(flags);
+					QU_PRINTK("scsi%d: command for target %d lun %d was "
+						  "moved from connected to the "
+						  "disconnected_queue\n", HOSTNO,
+						  cmd->device->id, cmd->device->lun);
+					/*
+					 * Restore phase bits to 0 so an interrupted selection,
+					 * arbitration can resume.
+					 */
+					NCR5380_write(TARGET_COMMAND_REG, 0);
+
+					/* Enable reselect interrupts */
+					NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
+					/* Wait for bus free to avoid nasty timeouts */
+					while ((NCR5380_read(STATUS_REG) & SR_BSY) && !hostdata->connected)
+						barrier();
+					return;
+					/*
+					 * The SCSI data pointer is *IMPLICITLY* saved on a disconnect
+					 * operation, in violation of the SCSI spec so we can safely
+					 * ignore SAVE/RESTORE pointers calls.
+					 *
+					 * Unfortunately, some disks violate the SCSI spec and
+					 * don't issue the required SAVE_POINTERS message before
+					 * disconnecting, and we have to break spec to remain
+					 * compatible.
+					 */
+				case SAVE_POINTERS:
+				case RESTORE_POINTERS:
+					/* Accept message by clearing ACK */
+					NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+					/* Enable reselect interrupts */
+					NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
+					break;
+				case EXTENDED_MESSAGE:
+					/*
+					 * Extended messages are sent in the following format :
+					 * Byte
+					 * 0		EXTENDED_MESSAGE == 1
+					 * 1		length (includes one byte for code, doesn't
+					 *		include first two bytes)
+					 * 2		code
+					 * 3..length+1	arguments
+					 *
+					 * Start the extended message buffer with the EXTENDED_MESSAGE
+					 * byte, since spi_print_msg() wants the whole thing.
+					 */
+					extended_msg[0] = EXTENDED_MESSAGE;
+					/* Accept first byte by clearing ACK */
+					NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+
+					EXT_PRINTK("scsi%d: receiving extended message\n", HOSTNO);
+
+					len = 2;
+					data = extended_msg + 1;
+					phase = PHASE_MSGIN;
+					NCR5380_transfer_pio(instance, &phase, &len, &data);
+					EXT_PRINTK("scsi%d: length=%d, code=0x%02x\n", HOSTNO,
+						   (int)extended_msg[1], (int)extended_msg[2]);
+
+					if (!len && extended_msg[1] <=
+					    (sizeof(extended_msg) - 1)) {
+						/* Accept third byte by clearing ACK */
+						NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+						len = extended_msg[1] - 1;
+						data = extended_msg + 3;
+						phase = PHASE_MSGIN;
+
+						NCR5380_transfer_pio(instance, &phase, &len, &data);
+						EXT_PRINTK("scsi%d: message received, residual %d\n",
+							   HOSTNO, len);
+
+						switch (extended_msg[2]) {
+						case EXTENDED_SDTR:
+						case EXTENDED_WDTR:
+						case EXTENDED_MODIFY_DATA_POINTER:
+						case EXTENDED_EXTENDED_IDENTIFY:
+							tmp = 0;
+						}
+					} else if (len) {
+						printk(KERN_NOTICE "scsi%d: error receiving "
+						       "extended message\n", HOSTNO);
+						tmp = 0;
+					} else {
+						printk(KERN_NOTICE "scsi%d: extended message "
+							   "code %02x length %d is too long\n",
+							   HOSTNO, extended_msg[2], extended_msg[1]);
+						tmp = 0;
+					}
+					/* Fall through to reject message */
+
+					/*
+					 * If we get something weird that we aren't expecting,
+					 * reject it.
+					 */
+				default:
+					if (!tmp) {
+						printk(KERN_DEBUG "scsi%d: rejecting message ", HOSTNO);
+						spi_print_msg(extended_msg);
+						printk("\n");
+					} else if (tmp != EXTENDED_MESSAGE)
+						printk(KERN_DEBUG "scsi%d: rejecting unknown "
+						       "message %02x from target %d, lun %d\n",
+						       HOSTNO, tmp, cmd->device->id, cmd->device->lun);
+					else
+						printk(KERN_DEBUG "scsi%d: rejecting unknown "
+						       "extended message "
+						       "code %02x, length %d from target %d, lun %d\n",
+						       HOSTNO, extended_msg[1], extended_msg[0],
+						       cmd->device->id, cmd->device->lun);
+
+
+					msgout = MESSAGE_REJECT;
+					NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
+					break;
+				} /* switch (tmp) */
+				break;
+			case PHASE_MSGOUT:
+				len = 1;
+				data = &msgout;
+				hostdata->last_message = msgout;
+				NCR5380_transfer_pio(instance, &phase, &len, &data);
+				if (msgout == ABORT) {
+#ifdef SUPPORT_TAGS
+					cmd_free_tag(cmd);
+#else
+					hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun);
+#endif
+					hostdata->connected = NULL;
+					cmd->result = DID_ERROR << 16;
+#ifdef NCR5380_STATS
+					collect_stats(hostdata, cmd);
+#endif
+					cmd->scsi_done(cmd);
+					NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
+					falcon_release_lock_if_possible(hostdata);
+					return;
+				}
+				msgout = NOP;
+				break;
+			case PHASE_CMDOUT:
+				len = cmd->cmd_len;
+				data = cmd->cmnd;
+				/*
+				 * XXX for performance reasons, on machines with a
+				 * PSEUDO-DMA architecture we should probably
+				 * use the dma transfer function.
+				 */
+				NCR5380_transfer_pio(instance, &phase, &len, &data);
+				break;
+			case PHASE_STATIN:
+				len = 1;
+				data = &tmp;
+				NCR5380_transfer_pio(instance, &phase, &len, &data);
+				cmd->SCp.Status = tmp;
+				break;
+			default:
+				printk("scsi%d: unknown phase\n", HOSTNO);
+				NCR_PRINT(NDEBUG_ANY);
+			} /* switch(phase) */
+		} /* if (tmp * SR_REQ) */
+	} /* while (1) */
 }
 
 /*
  * Function : void NCR5380_reselect (struct Scsi_Host *instance)
  *
- * Purpose : does reselection, initializing the instance->connected 
- *	field to point to the Scsi_Cmnd for which the I_T_L or I_T_L_Q 
+ * Purpose : does reselection, initializing the instance->connected
+ *	field to point to the Scsi_Cmnd for which the I_T_L or I_T_L_Q
  *	nexus has been reestablished,
- *	
+ *
  * Inputs : instance - this instance of the NCR5380.
  *
  */
 
 
-static void NCR5380_reselect (struct Scsi_Host *instance)
+static void NCR5380_reselect(struct Scsi_Host *instance)
 {
-    SETUP_HOSTDATA(instance);
-    unsigned char target_mask;
-    unsigned char lun, phase;
-    int len;
+	SETUP_HOSTDATA(instance);
+	unsigned char target_mask;
+	unsigned char lun, phase;
+	int len;
 #ifdef SUPPORT_TAGS
-    unsigned char tag;
+	unsigned char tag;
 #endif
-    unsigned char msg[3];
-    unsigned char *data;
-    Scsi_Cmnd *tmp = NULL, *prev;
-/*    unsigned long flags; */
+	unsigned char msg[3];
+	unsigned char *data;
+	Scsi_Cmnd *tmp = NULL, *prev;
+/*	unsigned long flags; */
 
-    /*
-     * Disable arbitration, etc. since the host adapter obviously
-     * lost, and tell an interrupted NCR5380_select() to restart.
-     */
-
-    NCR5380_write(MODE_REG, MR_BASE);
-    hostdata->restart_select = 1;
-
-    target_mask = NCR5380_read(CURRENT_SCSI_DATA_REG) & ~(hostdata->id_mask);
-
-    RSL_PRINTK("scsi%d: reselect\n", HOSTNO);
-
-    /* 
-     * At this point, we have detected that our SCSI ID is on the bus,
-     * SEL is true and BSY was false for at least one bus settle delay
-     * (400 ns).
-     *
-     * We must assert BSY ourselves, until the target drops the SEL
-     * signal.
-     */
-
-    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_BSY);
-    
-    while (NCR5380_read(STATUS_REG) & SR_SEL);
-    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
-
-    /*
-     * Wait for target to go into MSGIN.
-     */
-
-    while (!(NCR5380_read(STATUS_REG) & SR_REQ));
-
-    len = 1;
-    data = msg;
-    phase = PHASE_MSGIN;
-    NCR5380_transfer_pio(instance, &phase, &len, &data);
-
-    if (!(msg[0] & 0x80)) {
-	printk(KERN_DEBUG "scsi%d: expecting IDENTIFY message, got ", HOSTNO);
-	spi_print_msg(msg);
-	do_abort(instance);
-	return;
-    }
-    lun = (msg[0] & 0x07);
-
-#ifdef SUPPORT_TAGS
-    /* If the phase is still MSGIN, the target wants to send some more
-     * messages. In case it supports tagged queuing, this is probably a
-     * SIMPLE_QUEUE_TAG for the I_T_L_Q nexus.
-     */
-    tag = TAG_NONE;
-    if (phase == PHASE_MSGIN && setup_use_tagged_queuing) {
-	/* Accept previous IDENTIFY message by clearing ACK */
-	NCR5380_write( INITIATOR_COMMAND_REG, ICR_BASE );
-	len = 2;
-	data = msg+1;
-	if (!NCR5380_transfer_pio(instance, &phase, &len, &data) &&
-	    msg[1] == SIMPLE_QUEUE_TAG)
-	    tag = msg[2];
-	TAG_PRINTK("scsi%d: target mask %02x, lun %d sent tag %d at "
-		   "reselection\n", HOSTNO, target_mask, lun, tag);
-    }
-#endif
-    
-    /* 
-     * Find the command corresponding to the I_T_L or I_T_L_Q  nexus we 
-     * just reestablished, and remove it from the disconnected queue.
-     */
-
-    for (tmp = (Scsi_Cmnd *) hostdata->disconnected_queue, prev = NULL; 
-	 tmp; prev = tmp, tmp = NEXT(tmp) ) {
-	if ((target_mask == (1 << tmp->device->id)) && (lun == tmp->device->lun)
-#ifdef SUPPORT_TAGS
-	    && (tag == tmp->tag) 
-#endif
-	    ) {
-	    /* ++guenther: prevent race with falcon_release_lock */
-	    falcon_dont_release++;
-	    if (prev) {
-		REMOVE(prev, NEXT(prev), tmp, NEXT(tmp));
-		NEXT(prev) = NEXT(tmp);
-	    } else {
-		REMOVE(-1, hostdata->disconnected_queue, tmp, NEXT(tmp));
-		hostdata->disconnected_queue = NEXT(tmp);
-	    }
-	    NEXT(tmp) = NULL;
-	    break;
-	}
-    }
-    
-    if (!tmp) {
-	printk(KERN_WARNING "scsi%d: warning: target bitmask %02x lun %d "
-#ifdef SUPPORT_TAGS
-		"tag %d "
-#endif
-		"not in disconnected_queue.\n",
-		HOSTNO, target_mask, lun
-#ifdef SUPPORT_TAGS
-		, tag
-#endif
-		);
-	/* 
-	 * Since we have an established nexus that we can't do anything
-	 * with, we must abort it.  
+	/*
+	 * Disable arbitration, etc. since the host adapter obviously
+	 * lost, and tell an interrupted NCR5380_select() to restart.
 	 */
-	do_abort(instance);
-	return;
-    }
 
-    /* Accept message by clearing ACK */
-    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+	NCR5380_write(MODE_REG, MR_BASE);
+	hostdata->restart_select = 1;
 
-    hostdata->connected = tmp;
-    RSL_PRINTK("scsi%d: nexus established, target = %d, lun = %d, tag = %d\n",
-	       HOSTNO, tmp->device->id, tmp->device->lun, tmp->tag);
-    falcon_dont_release--;
+	target_mask = NCR5380_read(CURRENT_SCSI_DATA_REG) & ~(hostdata->id_mask);
+
+	RSL_PRINTK("scsi%d: reselect\n", HOSTNO);
+
+	/*
+	 * At this point, we have detected that our SCSI ID is on the bus,
+	 * SEL is true and BSY was false for at least one bus settle delay
+	 * (400 ns).
+	 *
+	 * We must assert BSY ourselves, until the target drops the SEL
+	 * signal.
+	 */
+
+	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_BSY);
+
+	while (NCR5380_read(STATUS_REG) & SR_SEL)
+		;
+	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+
+	/*
+	 * Wait for target to go into MSGIN.
+	 */
+
+	while (!(NCR5380_read(STATUS_REG) & SR_REQ))
+		;
+
+	len = 1;
+	data = msg;
+	phase = PHASE_MSGIN;
+	NCR5380_transfer_pio(instance, &phase, &len, &data);
+
+	if (!(msg[0] & 0x80)) {
+		printk(KERN_DEBUG "scsi%d: expecting IDENTIFY message, got ", HOSTNO);
+		spi_print_msg(msg);
+		do_abort(instance);
+		return;
+	}
+	lun = (msg[0] & 0x07);
+
+#ifdef SUPPORT_TAGS
+	/* If the phase is still MSGIN, the target wants to send some more
+	 * messages. In case it supports tagged queuing, this is probably a
+	 * SIMPLE_QUEUE_TAG for the I_T_L_Q nexus.
+	 */
+	tag = TAG_NONE;
+	if (phase == PHASE_MSGIN && setup_use_tagged_queuing) {
+		/* Accept previous IDENTIFY message by clearing ACK */
+		NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+		len = 2;
+		data = msg + 1;
+		if (!NCR5380_transfer_pio(instance, &phase, &len, &data) &&
+		    msg[1] == SIMPLE_QUEUE_TAG)
+			tag = msg[2];
+		TAG_PRINTK("scsi%d: target mask %02x, lun %d sent tag %d at "
+			   "reselection\n", HOSTNO, target_mask, lun, tag);
+	}
+#endif
+
+	/*
+	 * Find the command corresponding to the I_T_L or I_T_L_Q  nexus we
+	 * just reestablished, and remove it from the disconnected queue.
+	 */
+
+	for (tmp = (Scsi_Cmnd *) hostdata->disconnected_queue, prev = NULL;
+	     tmp; prev = tmp, tmp = NEXT(tmp)) {
+		if ((target_mask == (1 << tmp->device->id)) && (lun == tmp->device->lun)
+#ifdef SUPPORT_TAGS
+		    && (tag == tmp->tag)
+#endif
+		    ) {
+			/* ++guenther: prevent race with falcon_release_lock */
+			falcon_dont_release++;
+			if (prev) {
+				REMOVE(prev, NEXT(prev), tmp, NEXT(tmp));
+				SET_NEXT(prev, NEXT(tmp));
+			} else {
+				REMOVE(-1, hostdata->disconnected_queue, tmp, NEXT(tmp));
+				hostdata->disconnected_queue = NEXT(tmp);
+			}
+			SET_NEXT(tmp, NULL);
+			break;
+		}
+	}
+
+	if (!tmp) {
+		printk(KERN_WARNING "scsi%d: warning: target bitmask %02x lun %d "
+#ifdef SUPPORT_TAGS
+		       "tag %d "
+#endif
+		       "not in disconnected_queue.\n",
+		       HOSTNO, target_mask, lun
+#ifdef SUPPORT_TAGS
+		       , tag
+#endif
+			);
+		/*
+		 * Since we have an established nexus that we can't do anything
+		 * with, we must abort it.
+		 */
+		do_abort(instance);
+		return;
+	}
+
+	/* Accept message by clearing ACK */
+	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+
+	hostdata->connected = tmp;
+	RSL_PRINTK("scsi%d: nexus established, target = %d, lun = %d, tag = %d\n",
+		   HOSTNO, tmp->device->id, tmp->device->lun, tmp->tag);
+	falcon_dont_release--;
 }
 
 
@@ -2626,362 +2677,361 @@
  *
  * Purpose : abort a command
  *
- * Inputs : cmd - the Scsi_Cmnd to abort, code - code to set the 
- * 	host byte of the result field to, if zero DID_ABORTED is 
+ * Inputs : cmd - the Scsi_Cmnd to abort, code - code to set the
+ *	host byte of the result field to, if zero DID_ABORTED is
  *	used.
  *
  * Returns : 0 - success, -1 on failure.
  *
- * XXX - there is no way to abort the command that is currently 
- * 	 connected, you have to wait for it to complete.  If this is 
+ * XXX - there is no way to abort the command that is currently
+ *	 connected, you have to wait for it to complete.  If this is
  *	 a problem, we could implement longjmp() / setjmp(), setjmp()
- * 	 called where the loop started in NCR5380_main().
+ *	 called where the loop started in NCR5380_main().
  */
 
 static
-int NCR5380_abort (Scsi_Cmnd *cmd)
+int NCR5380_abort(Scsi_Cmnd *cmd)
 {
-    struct Scsi_Host *instance = cmd->device->host;
-    SETUP_HOSTDATA(instance);
-    Scsi_Cmnd *tmp, **prev;
-    unsigned long flags;
+	struct Scsi_Host *instance = cmd->device->host;
+	SETUP_HOSTDATA(instance);
+	Scsi_Cmnd *tmp, **prev;
+	unsigned long flags;
 
-    printk(KERN_NOTICE "scsi%d: aborting command\n", HOSTNO);
-    scsi_print_command(cmd);
+	printk(KERN_NOTICE "scsi%d: aborting command\n", HOSTNO);
+	scsi_print_command(cmd);
 
-    NCR5380_print_status (instance);
+	NCR5380_print_status(instance);
 
-    local_irq_save(flags);
-    
-    if (!IS_A_TT() && !falcon_got_lock)
-	printk(KERN_ERR "scsi%d: !!BINGO!! Falcon has no lock in NCR5380_abort\n",
-	       HOSTNO);
+	local_irq_save(flags);
 
-    ABRT_PRINTK("scsi%d: abort called basr 0x%02x, sr 0x%02x\n", HOSTNO,
-		NCR5380_read(BUS_AND_STATUS_REG),
-		NCR5380_read(STATUS_REG));
+	if (!IS_A_TT() && !falcon_got_lock)
+		printk(KERN_ERR "scsi%d: !!BINGO!! Falcon has no lock in NCR5380_abort\n",
+		       HOSTNO);
+
+	ABRT_PRINTK("scsi%d: abort called basr 0x%02x, sr 0x%02x\n", HOSTNO,
+		    NCR5380_read(BUS_AND_STATUS_REG),
+		    NCR5380_read(STATUS_REG));
 
 #if 1
-/* 
- * Case 1 : If the command is the currently executing command, 
- * we'll set the aborted flag and return control so that 
- * information transfer routine can exit cleanly.
- */
+	/*
+	 * Case 1 : If the command is the currently executing command,
+	 * we'll set the aborted flag and return control so that
+	 * information transfer routine can exit cleanly.
+	 */
 
-    if (hostdata->connected == cmd) {
+	if (hostdata->connected == cmd) {
 
-	ABRT_PRINTK("scsi%d: aborting connected command\n", HOSTNO);
-/*
- * We should perform BSY checking, and make sure we haven't slipped
- * into BUS FREE.
- */
+		ABRT_PRINTK("scsi%d: aborting connected command\n", HOSTNO);
+		/*
+		 * We should perform BSY checking, and make sure we haven't slipped
+		 * into BUS FREE.
+		 */
 
-/*	NCR5380_write(INITIATOR_COMMAND_REG, ICR_ASSERT_ATN); */
-/* 
- * Since we can't change phases until we've completed the current 
- * handshake, we have to source or sink a byte of data if the current
- * phase is not MSGOUT.
- */
+		/*	NCR5380_write(INITIATOR_COMMAND_REG, ICR_ASSERT_ATN); */
+		/*
+		 * Since we can't change phases until we've completed the current
+		 * handshake, we have to source or sink a byte of data if the current
+		 * phase is not MSGOUT.
+		 */
 
-/* 
- * Return control to the executing NCR drive so we can clear the
- * aborted flag and get back into our main loop.
- */ 
+		/*
+		 * Return control to the executing NCR drive so we can clear the
+		 * aborted flag and get back into our main loop.
+		 */
 
-	if (do_abort(instance) == 0) {
-	  hostdata->aborted = 1;
-	  hostdata->connected = NULL;
-	  cmd->result = DID_ABORT << 16;
+		if (do_abort(instance) == 0) {
+			hostdata->aborted = 1;
+			hostdata->connected = NULL;
+			cmd->result = DID_ABORT << 16;
 #ifdef SUPPORT_TAGS
-	  cmd_free_tag( cmd );
+			cmd_free_tag(cmd);
 #else
-	  hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun);
+			hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun);
 #endif
-	  local_irq_restore(flags);
-	  cmd->scsi_done(cmd);
-	  falcon_release_lock_if_possible( hostdata );
-	  return SCSI_ABORT_SUCCESS;
-	} else {
-/*	  local_irq_restore(flags); */
-	  printk("scsi%d: abort of connected command failed!\n", HOSTNO);
-	  return SCSI_ABORT_ERROR;
-	} 
-   }
-#endif
-
-/* 
- * Case 2 : If the command hasn't been issued yet, we simply remove it 
- * 	    from the issue queue.
- */
-    for (prev = (Scsi_Cmnd **) &(hostdata->issue_queue), 
-	tmp = (Scsi_Cmnd *) hostdata->issue_queue;
-	tmp; prev = NEXTADDR(tmp), tmp = NEXT(tmp) )
-	if (cmd == tmp) {
-	    REMOVE(5, *prev, tmp, NEXT(tmp));
-	    (*prev) = NEXT(tmp);
-	    NEXT(tmp) = NULL;
-	    tmp->result = DID_ABORT << 16;
-	    local_irq_restore(flags);
-	    ABRT_PRINTK("scsi%d: abort removed command from issue queue.\n",
-			HOSTNO);
-	    /* Tagged queuing note: no tag to free here, hasn't been assigned
-	     * yet... */
-	    tmp->scsi_done(tmp);
-	    falcon_release_lock_if_possible( hostdata );
-	    return SCSI_ABORT_SUCCESS;
+			local_irq_restore(flags);
+			cmd->scsi_done(cmd);
+			falcon_release_lock_if_possible(hostdata);
+			return SCSI_ABORT_SUCCESS;
+		} else {
+/*			local_irq_restore(flags); */
+			printk("scsi%d: abort of connected command failed!\n", HOSTNO);
+			return SCSI_ABORT_ERROR;
+		}
 	}
-
-/* 
- * Case 3 : If any commands are connected, we're going to fail the abort
- *	    and let the high level SCSI driver retry at a later time or 
- *	    issue a reset.
- *
- *	    Timeouts, and therefore aborted commands, will be highly unlikely
- *          and handling them cleanly in this situation would make the common
- *	    case of noresets less efficient, and would pollute our code.  So,
- *	    we fail.
- */
-
-    if (hostdata->connected) {
-	local_irq_restore(flags);
-	ABRT_PRINTK("scsi%d: abort failed, command connected.\n", HOSTNO);
-        return SCSI_ABORT_SNOOZE;
-    }
-
-/*
- * Case 4: If the command is currently disconnected from the bus, and 
- * 	there are no connected commands, we reconnect the I_T_L or 
- *	I_T_L_Q nexus associated with it, go into message out, and send 
- *      an abort message.
- *
- * This case is especially ugly. In order to reestablish the nexus, we
- * need to call NCR5380_select().  The easiest way to implement this 
- * function was to abort if the bus was busy, and let the interrupt
- * handler triggered on the SEL for reselect take care of lost arbitrations
- * where necessary, meaning interrupts need to be enabled.
- *
- * When interrupts are enabled, the queues may change - so we 
- * can't remove it from the disconnected queue before selecting it
- * because that could cause a failure in hashing the nexus if that 
- * device reselected.
- * 
- * Since the queues may change, we can't use the pointers from when we
- * first locate it.
- *
- * So, we must first locate the command, and if NCR5380_select()
- * succeeds, then issue the abort, relocate the command and remove
- * it from the disconnected queue.
- */
-
-    for (tmp = (Scsi_Cmnd *) hostdata->disconnected_queue; tmp;
-	 tmp = NEXT(tmp)) 
-        if (cmd == tmp) {
-            local_irq_restore(flags);
-	    ABRT_PRINTK("scsi%d: aborting disconnected command.\n", HOSTNO);
-  
-            if (NCR5380_select (instance, cmd, (int) cmd->tag)) 
-		return SCSI_ABORT_BUSY;
-
-	    ABRT_PRINTK("scsi%d: nexus reestablished.\n", HOSTNO);
-
-	    do_abort (instance);
-
-	    local_irq_save(flags);
-	    for (prev = (Scsi_Cmnd **) &(hostdata->disconnected_queue), 
-		tmp = (Scsi_Cmnd *) hostdata->disconnected_queue;
-		tmp; prev = NEXTADDR(tmp), tmp = NEXT(tmp) )
-		    if (cmd == tmp) {
-		    REMOVE(5, *prev, tmp, NEXT(tmp));
-		    *prev = NEXT(tmp);
-		    NEXT(tmp) = NULL;
-		    tmp->result = DID_ABORT << 16;
-		    /* We must unlock the tag/LUN immediately here, since the
-		     * target goes to BUS FREE and doesn't send us another
-		     * message (COMMAND_COMPLETE or the like)
-		     */
-#ifdef SUPPORT_TAGS
-		    cmd_free_tag( tmp );
-#else
-		    hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun);
 #endif
-		    local_irq_restore(flags);
-		    tmp->scsi_done(tmp);
-		    falcon_release_lock_if_possible( hostdata );
-		    return SCSI_ABORT_SUCCESS;
+
+	/*
+	 * Case 2 : If the command hasn't been issued yet, we simply remove it
+	 *	    from the issue queue.
+	 */
+	for (prev = (Scsi_Cmnd **)&(hostdata->issue_queue),
+	     tmp = (Scsi_Cmnd *)hostdata->issue_queue;
+	     tmp; prev = NEXTADDR(tmp), tmp = NEXT(tmp)) {
+		if (cmd == tmp) {
+			REMOVE(5, *prev, tmp, NEXT(tmp));
+			(*prev) = NEXT(tmp);
+			SET_NEXT(tmp, NULL);
+			tmp->result = DID_ABORT << 16;
+			local_irq_restore(flags);
+			ABRT_PRINTK("scsi%d: abort removed command from issue queue.\n",
+				    HOSTNO);
+			/* Tagged queuing note: no tag to free here, hasn't been assigned
+			 * yet... */
+			tmp->scsi_done(tmp);
+			falcon_release_lock_if_possible(hostdata);
+			return SCSI_ABORT_SUCCESS;
 		}
 	}
 
-/*
- * Case 5 : If we reached this point, the command was not found in any of 
- *	    the queues.
- *
- * We probably reached this point because of an unlikely race condition
- * between the command completing successfully and the abortion code,
- * so we won't panic, but we will notify the user in case something really
- * broke.
- */
+	/*
+	 * Case 3 : If any commands are connected, we're going to fail the abort
+	 *	    and let the high level SCSI driver retry at a later time or
+	 *	    issue a reset.
+	 *
+	 *	    Timeouts, and therefore aborted commands, will be highly unlikely
+	 *          and handling them cleanly in this situation would make the common
+	 *	    case of noresets less efficient, and would pollute our code.  So,
+	 *	    we fail.
+	 */
 
-    local_irq_restore(flags);
-    printk(KERN_INFO "scsi%d: warning : SCSI command probably completed successfully\n"
-           KERN_INFO "        before abortion\n", HOSTNO); 
+	if (hostdata->connected) {
+		local_irq_restore(flags);
+		ABRT_PRINTK("scsi%d: abort failed, command connected.\n", HOSTNO);
+		return SCSI_ABORT_SNOOZE;
+	}
 
-/* Maybe it is sufficient just to release the ST-DMA lock... (if
- * possible at all) At least, we should check if the lock could be
- * released after the abort, in case it is kept due to some bug.
- */
-    falcon_release_lock_if_possible( hostdata );
+	/*
+	 * Case 4: If the command is currently disconnected from the bus, and
+	 *	there are no connected commands, we reconnect the I_T_L or
+	 *	I_T_L_Q nexus associated with it, go into message out, and send
+	 *      an abort message.
+	 *
+	 * This case is especially ugly. In order to reestablish the nexus, we
+	 * need to call NCR5380_select().  The easiest way to implement this
+	 * function was to abort if the bus was busy, and let the interrupt
+	 * handler triggered on the SEL for reselect take care of lost arbitrations
+	 * where necessary, meaning interrupts need to be enabled.
+	 *
+	 * When interrupts are enabled, the queues may change - so we
+	 * can't remove it from the disconnected queue before selecting it
+	 * because that could cause a failure in hashing the nexus if that
+	 * device reselected.
+	 *
+	 * Since the queues may change, we can't use the pointers from when we
+	 * first locate it.
+	 *
+	 * So, we must first locate the command, and if NCR5380_select()
+	 * succeeds, then issue the abort, relocate the command and remove
+	 * it from the disconnected queue.
+	 */
 
-    return SCSI_ABORT_NOT_RUNNING;
+	for (tmp = (Scsi_Cmnd *) hostdata->disconnected_queue; tmp;
+	     tmp = NEXT(tmp)) {
+		if (cmd == tmp) {
+			local_irq_restore(flags);
+			ABRT_PRINTK("scsi%d: aborting disconnected command.\n", HOSTNO);
+
+			if (NCR5380_select(instance, cmd, (int)cmd->tag))
+				return SCSI_ABORT_BUSY;
+
+			ABRT_PRINTK("scsi%d: nexus reestablished.\n", HOSTNO);
+
+			do_abort(instance);
+
+			local_irq_save(flags);
+			for (prev = (Scsi_Cmnd **)&(hostdata->disconnected_queue),
+			     tmp = (Scsi_Cmnd *)hostdata->disconnected_queue;
+			     tmp; prev = NEXTADDR(tmp), tmp = NEXT(tmp)) {
+				if (cmd == tmp) {
+					REMOVE(5, *prev, tmp, NEXT(tmp));
+					*prev = NEXT(tmp);
+					SET_NEXT(tmp, NULL);
+					tmp->result = DID_ABORT << 16;
+					/* We must unlock the tag/LUN immediately here, since the
+					 * target goes to BUS FREE and doesn't send us another
+					 * message (COMMAND_COMPLETE or the like)
+					 */
+#ifdef SUPPORT_TAGS
+					cmd_free_tag(tmp);
+#else
+					hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun);
+#endif
+					local_irq_restore(flags);
+					tmp->scsi_done(tmp);
+					falcon_release_lock_if_possible(hostdata);
+					return SCSI_ABORT_SUCCESS;
+				}
+			}
+		}
+	}
+
+	/*
+	 * Case 5 : If we reached this point, the command was not found in any of
+	 *	    the queues.
+	 *
+	 * We probably reached this point because of an unlikely race condition
+	 * between the command completing successfully and the abortion code,
+	 * so we won't panic, but we will notify the user in case something really
+	 * broke.
+	 */
+
+	local_irq_restore(flags);
+	printk(KERN_INFO "scsi%d: warning : SCSI command probably completed successfully\n"
+	       KERN_INFO "        before abortion\n", HOSTNO);
+
+	/* Maybe it is sufficient just to release the ST-DMA lock... (if
+	 * possible at all) At least, we should check if the lock could be
+	 * released after the abort, in case it is kept due to some bug.
+	 */
+	falcon_release_lock_if_possible(hostdata);
+
+	return SCSI_ABORT_NOT_RUNNING;
 }
 
 
-/* 
+/*
  * Function : int NCR5380_reset (Scsi_Cmnd *cmd)
- * 
+ *
  * Purpose : reset the SCSI bus.
  *
  * Returns : SCSI_RESET_WAKEUP
  *
- */ 
+ */
 
-static int NCR5380_bus_reset( Scsi_Cmnd *cmd)
+static int NCR5380_bus_reset(Scsi_Cmnd *cmd)
 {
-    SETUP_HOSTDATA(cmd->device->host);
-    int           i;
-    unsigned long flags;
+	SETUP_HOSTDATA(cmd->device->host);
+	int i;
+	unsigned long flags;
 #if 1
-    Scsi_Cmnd *connected, *disconnected_queue;
+	Scsi_Cmnd *connected, *disconnected_queue;
 #endif
 
-    if (!IS_A_TT() && !falcon_got_lock)
-	printk(KERN_ERR "scsi%d: !!BINGO!! Falcon has no lock in NCR5380_reset\n",
-	       H_NO(cmd) );
+	if (!IS_A_TT() && !falcon_got_lock)
+		printk(KERN_ERR "scsi%d: !!BINGO!! Falcon has no lock in NCR5380_reset\n",
+		       H_NO(cmd));
 
-    NCR5380_print_status (cmd->device->host);
+	NCR5380_print_status(cmd->device->host);
 
-    /* get in phase */
-    NCR5380_write( TARGET_COMMAND_REG,
-		   PHASE_SR_TO_TCR( NCR5380_read(STATUS_REG) ));
-    /* assert RST */
-    NCR5380_write( INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_RST );
-    udelay (40);
-    /* reset NCR registers */
-    NCR5380_write( INITIATOR_COMMAND_REG, ICR_BASE );
-    NCR5380_write( MODE_REG, MR_BASE );
-    NCR5380_write( TARGET_COMMAND_REG, 0 );
-    NCR5380_write( SELECT_ENABLE_REG, 0 );
-    /* ++roman: reset interrupt condition! otherwise no interrupts don't get
-     * through anymore ... */
-    (void)NCR5380_read( RESET_PARITY_INTERRUPT_REG );
+	/* get in phase */
+	NCR5380_write(TARGET_COMMAND_REG,
+		      PHASE_SR_TO_TCR(NCR5380_read(STATUS_REG)));
+	/* assert RST */
+	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_RST);
+	udelay(40);
+	/* reset NCR registers */
+	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+	NCR5380_write(MODE_REG, MR_BASE);
+	NCR5380_write(TARGET_COMMAND_REG, 0);
+	NCR5380_write(SELECT_ENABLE_REG, 0);
+	/* ++roman: reset interrupt condition! otherwise no interrupts don't get
+	 * through anymore ... */
+	(void)NCR5380_read(RESET_PARITY_INTERRUPT_REG);
 
-#if 1 /* XXX Should now be done by midlevel code, but it's broken XXX */
-      /* XXX see below                                            XXX */
+#if 1	/* XXX Should now be done by midlevel code, but it's broken XXX */
+	/* XXX see below                                            XXX */
 
-    /* MSch: old-style reset: actually abort all command processing here */
+	/* MSch: old-style reset: actually abort all command processing here */
 
-    /* After the reset, there are no more connected or disconnected commands
-     * and no busy units; to avoid problems with re-inserting the commands
-     * into the issue_queue (via scsi_done()), the aborted commands are
-     * remembered in local variables first.
-     */
-    local_irq_save(flags);
-    connected = (Scsi_Cmnd *)hostdata->connected;
-    hostdata->connected = NULL;
-    disconnected_queue = (Scsi_Cmnd *)hostdata->disconnected_queue;
-    hostdata->disconnected_queue = NULL;
+	/* After the reset, there are no more connected or disconnected commands
+	 * and no busy units; to avoid problems with re-inserting the commands
+	 * into the issue_queue (via scsi_done()), the aborted commands are
+	 * remembered in local variables first.
+	 */
+	local_irq_save(flags);
+	connected = (Scsi_Cmnd *)hostdata->connected;
+	hostdata->connected = NULL;
+	disconnected_queue = (Scsi_Cmnd *)hostdata->disconnected_queue;
+	hostdata->disconnected_queue = NULL;
 #ifdef SUPPORT_TAGS
-    free_all_tags();
+	free_all_tags();
 #endif
-    for( i = 0; i < 8; ++i )
-	hostdata->busy[i] = 0;
+	for (i = 0; i < 8; ++i)
+		hostdata->busy[i] = 0;
 #ifdef REAL_DMA
-    hostdata->dma_len = 0;
+	hostdata->dma_len = 0;
 #endif
-    local_irq_restore(flags);
+	local_irq_restore(flags);
 
-    /* In order to tell the mid-level code which commands were aborted, 
-     * set the command status to DID_RESET and call scsi_done() !!!
-     * This ultimately aborts processing of these commands in the mid-level.
-     */
+	/* In order to tell the mid-level code which commands were aborted,
+	 * set the command status to DID_RESET and call scsi_done() !!!
+	 * This ultimately aborts processing of these commands in the mid-level.
+	 */
 
-    if ((cmd = connected)) {
-	ABRT_PRINTK("scsi%d: reset aborted a connected command\n", H_NO(cmd));
-	cmd->result = (cmd->result & 0xffff) | (DID_RESET << 16);
-	cmd->scsi_done( cmd );
-    }
+	if ((cmd = connected)) {
+		ABRT_PRINTK("scsi%d: reset aborted a connected command\n", H_NO(cmd));
+		cmd->result = (cmd->result & 0xffff) | (DID_RESET << 16);
+		cmd->scsi_done(cmd);
+	}
 
-    for (i = 0; (cmd = disconnected_queue); ++i) {
-	disconnected_queue = NEXT(cmd);
-	NEXT(cmd) = NULL;
-	cmd->result = (cmd->result & 0xffff) | (DID_RESET << 16);
-	cmd->scsi_done( cmd );
-    }
-    if (i > 0)
-	ABRT_PRINTK("scsi: reset aborted %d disconnected command(s)\n", i);
+	for (i = 0; (cmd = disconnected_queue); ++i) {
+		disconnected_queue = NEXT(cmd);
+		SET_NEXT(cmd, NULL);
+		cmd->result = (cmd->result & 0xffff) | (DID_RESET << 16);
+		cmd->scsi_done(cmd);
+	}
+	if (i > 0)
+		ABRT_PRINTK("scsi: reset aborted %d disconnected command(s)\n", i);
 
-/* The Falcon lock should be released after a reset...
- */
-/* ++guenther: moved to atari_scsi_reset(), to prevent a race between
- * unlocking and enabling dma interrupt.
- */
-/*    falcon_release_lock_if_possible( hostdata );*/
+	/* The Falcon lock should be released after a reset...
+	 */
+	/* ++guenther: moved to atari_scsi_reset(), to prevent a race between
+	 * unlocking and enabling dma interrupt.
+	 */
+/*	falcon_release_lock_if_possible( hostdata );*/
 
-    /* since all commands have been explicitly terminated, we need to tell
-     * the midlevel code that the reset was SUCCESSFUL, and there is no 
-     * need to 'wake up' the commands by a request_sense
-     */
-    return SCSI_RESET_SUCCESS | SCSI_RESET_BUS_RESET;
+	/* since all commands have been explicitly terminated, we need to tell
+	 * the midlevel code that the reset was SUCCESSFUL, and there is no
+	 * need to 'wake up' the commands by a request_sense
+	 */
+	return SCSI_RESET_SUCCESS | SCSI_RESET_BUS_RESET;
 #else /* 1 */
 
-    /* MSch: new-style reset handling: let the mid-level do what it can */
+	/* MSch: new-style reset handling: let the mid-level do what it can */
 
-    /* ++guenther: MID-LEVEL IS STILL BROKEN.
-     * Mid-level is supposed to requeue all commands that were active on the
-     * various low-level queues. In fact it does this, but that's not enough
-     * because all these commands are subject to timeout. And if a timeout
-     * happens for any removed command, *_abort() is called but all queues
-     * are now empty. Abort then gives up the falcon lock, which is fatal,
-     * since the mid-level will queue more commands and must have the lock
-     * (it's all happening inside timer interrupt handler!!).
-     * Even worse, abort will return NOT_RUNNING for all those commands not
-     * on any queue, so they won't be retried ...
-     *
-     * Conclusion: either scsi.c disables timeout for all resetted commands
-     * immediately, or we lose!  As of linux-2.0.20 it doesn't.
-     */
+	/* ++guenther: MID-LEVEL IS STILL BROKEN.
+	 * Mid-level is supposed to requeue all commands that were active on the
+	 * various low-level queues. In fact it does this, but that's not enough
+	 * because all these commands are subject to timeout. And if a timeout
+	 * happens for any removed command, *_abort() is called but all queues
+	 * are now empty. Abort then gives up the falcon lock, which is fatal,
+	 * since the mid-level will queue more commands and must have the lock
+	 * (it's all happening inside timer interrupt handler!!).
+	 * Even worse, abort will return NOT_RUNNING for all those commands not
+	 * on any queue, so they won't be retried ...
+	 *
+	 * Conclusion: either scsi.c disables timeout for all resetted commands
+	 * immediately, or we lose!  As of linux-2.0.20 it doesn't.
+	 */
 
-    /* After the reset, there are no more connected or disconnected commands
-     * and no busy units; so clear the low-level status here to avoid 
-     * conflicts when the mid-level code tries to wake up the affected 
-     * commands!
-     */
+	/* After the reset, there are no more connected or disconnected commands
+	 * and no busy units; so clear the low-level status here to avoid
+	 * conflicts when the mid-level code tries to wake up the affected
+	 * commands!
+	 */
 
-    if (hostdata->issue_queue)
-	ABRT_PRINTK("scsi%d: reset aborted issued command(s)\n", H_NO(cmd));
-    if (hostdata->connected) 
-	ABRT_PRINTK("scsi%d: reset aborted a connected command\n", H_NO(cmd));
-    if (hostdata->disconnected_queue)
-	ABRT_PRINTK("scsi%d: reset aborted disconnected command(s)\n", H_NO(cmd));
+	if (hostdata->issue_queue)
+		ABRT_PRINTK("scsi%d: reset aborted issued command(s)\n", H_NO(cmd));
+	if (hostdata->connected)
+		ABRT_PRINTK("scsi%d: reset aborted a connected command\n", H_NO(cmd));
+	if (hostdata->disconnected_queue)
+		ABRT_PRINTK("scsi%d: reset aborted disconnected command(s)\n", H_NO(cmd));
 
-    local_irq_save(flags);
-    hostdata->issue_queue = NULL;
-    hostdata->connected = NULL;
-    hostdata->disconnected_queue = NULL;
+	local_irq_save(flags);
+	hostdata->issue_queue = NULL;
+	hostdata->connected = NULL;
+	hostdata->disconnected_queue = NULL;
 #ifdef SUPPORT_TAGS
-    free_all_tags();
+	free_all_tags();
 #endif
-    for( i = 0; i < 8; ++i )
-	hostdata->busy[i] = 0;
+	for (i = 0; i < 8; ++i)
+		hostdata->busy[i] = 0;
 #ifdef REAL_DMA
-    hostdata->dma_len = 0;
+	hostdata->dma_len = 0;
 #endif
-    local_irq_restore(flags);
+	local_irq_restore(flags);
 
-    /* we did no complete reset of all commands, so a wakeup is required */
-    return SCSI_RESET_WAKEUP | SCSI_RESET_BUS_RESET;
+	/* we did no complete reset of all commands, so a wakeup is required */
+	return SCSI_RESET_WAKEUP | SCSI_RESET_BUS_RESET;
 #endif /* 1 */
 }
-
-/* Local Variables: */
-/* tab-width: 8     */
-/* End:             */
diff --git a/drivers/scsi/atari_scsi.c b/drivers/scsi/atari_scsi.c
index 642de7b..6f8403b 100644
--- a/drivers/scsi/atari_scsi.c
+++ b/drivers/scsi/atari_scsi.c
@@ -69,9 +69,9 @@
 
 #define NDEBUG (0)
 
-#define NDEBUG_ABORT	0x800000
-#define NDEBUG_TAGS	0x1000000
-#define NDEBUG_MERGING	0x2000000
+#define NDEBUG_ABORT		0x00100000
+#define NDEBUG_TAGS		0x00200000
+#define NDEBUG_MERGING		0x00400000
 
 #define AUTOSENSE
 /* For the Atari version, use only polled IO or REAL_DMA */
@@ -186,38 +186,37 @@
 /***************************** Prototypes *****************************/
 
 #ifdef REAL_DMA
-static int scsi_dma_is_ignored_buserr( unsigned char dma_stat );
-static void atari_scsi_fetch_restbytes( void );
-static long atari_scsi_dma_residual( struct Scsi_Host *instance );
-static int falcon_classify_cmd( Scsi_Cmnd *cmd );
-static unsigned long atari_dma_xfer_len( unsigned long wanted_len,
-                                         Scsi_Cmnd *cmd, int write_flag );
+static int scsi_dma_is_ignored_buserr(unsigned char dma_stat);
+static void atari_scsi_fetch_restbytes(void);
+static long atari_scsi_dma_residual(struct Scsi_Host *instance);
+static int falcon_classify_cmd(Scsi_Cmnd *cmd);
+static unsigned long atari_dma_xfer_len(unsigned long wanted_len,
+					Scsi_Cmnd *cmd, int write_flag);
 #endif
-static irqreturn_t scsi_tt_intr( int irq, void *dummy);
-static irqreturn_t scsi_falcon_intr( int irq, void *dummy);
-static void falcon_release_lock_if_possible( struct NCR5380_hostdata *
-                                             hostdata );
-static void falcon_get_lock( void );
+static irqreturn_t scsi_tt_intr(int irq, void *dummy);
+static irqreturn_t scsi_falcon_intr(int irq, void *dummy);
+static void falcon_release_lock_if_possible(struct NCR5380_hostdata *hostdata);
+static void falcon_get_lock(void);
 #ifdef CONFIG_ATARI_SCSI_RESET_BOOT
-static void atari_scsi_reset_boot( void );
+static void atari_scsi_reset_boot(void);
 #endif
-static unsigned char atari_scsi_tt_reg_read( unsigned char reg );
-static void atari_scsi_tt_reg_write( unsigned char reg, unsigned char value);
-static unsigned char atari_scsi_falcon_reg_read( unsigned char reg );
-static void atari_scsi_falcon_reg_write( unsigned char reg, unsigned char value );
+static unsigned char atari_scsi_tt_reg_read(unsigned char reg);
+static void atari_scsi_tt_reg_write(unsigned char reg, unsigned char value);
+static unsigned char atari_scsi_falcon_reg_read(unsigned char reg);
+static void atari_scsi_falcon_reg_write(unsigned char reg, unsigned char value);
 
 /************************* End of Prototypes **************************/
 
 
-static struct Scsi_Host *atari_scsi_host = NULL;
-static unsigned char (*atari_scsi_reg_read)( unsigned char reg );
-static void (*atari_scsi_reg_write)( unsigned char reg, unsigned char value );
+static struct Scsi_Host *atari_scsi_host;
+static unsigned char (*atari_scsi_reg_read)(unsigned char reg);
+static void (*atari_scsi_reg_write)(unsigned char reg, unsigned char value);
 
 #ifdef REAL_DMA
 static unsigned long	atari_dma_residual, atari_dma_startaddr;
 static short		atari_dma_active;
 /* pointer to the dribble buffer */
-static char		*atari_dma_buffer = NULL;
+static char		*atari_dma_buffer;
 /* precalculated physical address of the dribble buffer */
 static unsigned long	atari_dma_phys_buffer;
 /* != 0 tells the Falcon int handler to copy data from the dribble buffer */
@@ -233,7 +232,7 @@
 static unsigned long	atari_dma_stram_mask;
 #define STRAM_ADDR(a)	(((a) & atari_dma_stram_mask) == 0)
 /* number of bytes to cut from a transfer to handle NCR overruns */
-static int atari_read_overruns = 0;
+static int atari_read_overruns;
 #endif
 
 static int setup_can_queue = -1;
@@ -256,10 +255,10 @@
 
 #if defined(REAL_DMA)
 
-static int scsi_dma_is_ignored_buserr( unsigned char dma_stat )
+static int scsi_dma_is_ignored_buserr(unsigned char dma_stat)
 {
 	int i;
-	unsigned long	addr = SCSI_DMA_READ_P( dma_addr ), end_addr;
+	unsigned long addr = SCSI_DMA_READ_P(dma_addr), end_addr;
 
 	if (dma_stat & 0x01) {
 
@@ -267,15 +266,14 @@
 		 * physical memory chunk (DMA prefetch!), but that doesn't hurt.
 		 * Check for this case:
 		 */
-		
-		for( i = 0; i < m68k_num_memory; ++i ) {
-			end_addr = m68k_memory[i].addr +
-				m68k_memory[i].size;
+
+		for (i = 0; i < m68k_num_memory; ++i) {
+			end_addr = m68k_memory[i].addr + m68k_memory[i].size;
 			if (end_addr <= addr && addr <= end_addr + 4)
-				return( 1 );
+				return 1;
 		}
 	}
-	return( 0 );
+	return 0;
 }
 
 
@@ -284,28 +282,27 @@
  * end-of-DMA, both SCSI ints are triggered simultaneously, so the NCR int has
  * to clear the DMA int pending bit before it allows other level 6 interrupts.
  */
-static void scsi_dma_buserr (int irq, void *dummy)
+static void scsi_dma_buserr(int irq, void *dummy)
 {
-	unsigned char	dma_stat = tt_scsi_dma.dma_ctrl;
+	unsigned char dma_stat = tt_scsi_dma.dma_ctrl;
 
 	/* Don't do anything if a NCR interrupt is pending. Probably it's just
 	 * masked... */
-	if (atari_irq_pending( IRQ_TT_MFP_SCSI ))
+	if (atari_irq_pending(IRQ_TT_MFP_SCSI))
 		return;
-	
+
 	printk("Bad SCSI DMA interrupt! dma_addr=0x%08lx dma_stat=%02x dma_cnt=%08lx\n",
 	       SCSI_DMA_READ_P(dma_addr), dma_stat, SCSI_DMA_READ_P(dma_cnt));
 	if (dma_stat & 0x80) {
-		if (!scsi_dma_is_ignored_buserr( dma_stat ))
-			printk( "SCSI DMA bus error -- bad DMA programming!\n" );
-	}
-	else {
+		if (!scsi_dma_is_ignored_buserr(dma_stat))
+			printk("SCSI DMA bus error -- bad DMA programming!\n");
+	} else {
 		/* Under normal circumstances we never should get to this point,
 		 * since both interrupts are triggered simultaneously and the 5380
 		 * int has higher priority. When this irq is handled, that DMA
 		 * interrupt is cleared. So a warning message is printed here.
 		 */
-		printk( "SCSI DMA intr ?? -- this shouldn't happen!\n" );
+		printk("SCSI DMA intr ?? -- this shouldn't happen!\n");
 	}
 }
 #endif
@@ -313,7 +310,7 @@
 #endif
 
 
-static irqreturn_t scsi_tt_intr (int irq, void *dummy)
+static irqreturn_t scsi_tt_intr(int irq, void *dummy)
 {
 #ifdef REAL_DMA
 	int dma_stat;
@@ -327,7 +324,7 @@
 	 * is that a bus error occurred...
 	 */
 	if (dma_stat & 0x80) {
-		if (!scsi_dma_is_ignored_buserr( dma_stat )) {
+		if (!scsi_dma_is_ignored_buserr(dma_stat)) {
 			printk(KERN_ERR "SCSI DMA caused bus error near 0x%08lx\n",
 			       SCSI_DMA_READ_P(dma_addr));
 			printk(KERN_CRIT "SCSI DMA bus error -- bad DMA programming!");
@@ -344,8 +341,7 @@
 	 * data reg!
 	 */
 	if ((dma_stat & 0x02) && !(dma_stat & 0x40)) {
-		atari_dma_residual = HOSTDATA_DMALEN - (SCSI_DMA_READ_P( dma_addr ) -
-												atari_dma_startaddr);
+		atari_dma_residual = HOSTDATA_DMALEN - (SCSI_DMA_READ_P(dma_addr) - atari_dma_startaddr);
 
 		DMA_PRINTK("SCSI DMA: There are %ld residual bytes.\n",
 			   atari_dma_residual);
@@ -353,28 +349,30 @@
 		if ((signed int)atari_dma_residual < 0)
 			atari_dma_residual = 0;
 		if ((dma_stat & 1) == 0) {
-			/* After read operations, we maybe have to
-			   transport some rest bytes */
+			/*
+			 * After read operations, we maybe have to
+			 * transport some rest bytes
+			 */
 			atari_scsi_fetch_restbytes();
-		}
-		else {
-			/* There seems to be a nasty bug in some SCSI-DMA/NCR
-			   combinations: If a target disconnects while a write
-			   operation is going on, the address register of the
-			   DMA may be a few bytes farer than it actually read.
-			   This is probably due to DMA prefetching and a delay
-			   between DMA and NCR.  Experiments showed that the
-			   dma_addr is 9 bytes to high, but this could vary.
-			   The problem is, that the residual is thus calculated
-			   wrong and the next transfer will start behind where
-			   it should.  So we round up the residual to the next
-			   multiple of a sector size, if it isn't already a
-			   multiple and the originally expected transfer size
-			   was.  The latter condition is there to ensure that
-			   the correction is taken only for "real" data
-			   transfers and not for, e.g., the parameters of some
-			   other command.  These shouldn't disconnect anyway.
-			   */
+		} else {
+			/*
+			 * There seems to be a nasty bug in some SCSI-DMA/NCR
+			 * combinations: If a target disconnects while a write
+			 * operation is going on, the address register of the
+			 * DMA may be a few bytes farer than it actually read.
+			 * This is probably due to DMA prefetching and a delay
+			 * between DMA and NCR.  Experiments showed that the
+			 * dma_addr is 9 bytes to high, but this could vary.
+			 * The problem is, that the residual is thus calculated
+			 * wrong and the next transfer will start behind where
+			 * it should.  So we round up the residual to the next
+			 * multiple of a sector size, if it isn't already a
+			 * multiple and the originally expected transfer size
+			 * was.  The latter condition is there to ensure that
+			 * the correction is taken only for "real" data
+			 * transfers and not for, e.g., the parameters of some
+			 * other command.  These shouldn't disconnect anyway.
+			 */
 			if (atari_dma_residual & 0x1ff) {
 				DMA_PRINTK("SCSI DMA: DMA bug corrected, "
 					   "difference %ld bytes\n",
@@ -394,18 +392,18 @@
 	}
 
 #endif /* REAL_DMA */
-	
-	NCR5380_intr (0, 0, 0);
+
+	NCR5380_intr(0, 0);
 
 #if 0
 	/* To be sure the int is not masked */
-	atari_enable_irq( IRQ_TT_MFP_SCSI );
+	atari_enable_irq(IRQ_TT_MFP_SCSI);
 #endif
 	return IRQ_HANDLED;
 }
 
 
-static irqreturn_t scsi_falcon_intr (int irq, void *dummy)
+static irqreturn_t scsi_falcon_intr(int irq, void *dummy)
 {
 #ifdef REAL_DMA
 	int dma_stat;
@@ -430,7 +428,7 @@
 	 * bytes are stuck in the ST-DMA fifo (there's no way to reach them!)
 	 */
 	if (atari_dma_active && (dma_stat & 0x02)) {
-		unsigned long	transferred;
+		unsigned long transferred;
 
 		transferred = SCSI_DMA_GETADR() - atari_dma_startaddr;
 		/* The ST-DMA address is incremented in 2-byte steps, but the
@@ -445,8 +443,7 @@
 		atari_dma_residual = HOSTDATA_DMALEN - transferred;
 		DMA_PRINTK("SCSI DMA: There are %ld residual bytes.\n",
 			   atari_dma_residual);
-	}
-	else
+	} else
 		atari_dma_residual = 0;
 	atari_dma_active = 0;
 
@@ -461,13 +458,13 @@
 
 #endif /* REAL_DMA */
 
-	NCR5380_intr (0, 0, 0);
+	NCR5380_intr(0, 0);
 	return IRQ_HANDLED;
 }
 
 
 #ifdef REAL_DMA
-static void atari_scsi_fetch_restbytes( void )
+static void atari_scsi_fetch_restbytes(void)
 {
 	int nr;
 	char *src, *dst;
@@ -505,19 +502,17 @@
  * again (but others waiting longer more probably will win).
  */
 
-static void
-falcon_release_lock_if_possible( struct NCR5380_hostdata * hostdata )
+static void falcon_release_lock_if_possible(struct NCR5380_hostdata *hostdata)
 {
 	unsigned long flags;
-		
-	if (IS_A_TT()) return;
-	
+
+	if (IS_A_TT())
+		return;
+
 	local_irq_save(flags);
 
-	if (falcon_got_lock &&
-		!hostdata->disconnected_queue &&
-		!hostdata->issue_queue &&
-		!hostdata->connected) {
+	if (falcon_got_lock && !hostdata->disconnected_queue &&
+	    !hostdata->issue_queue && !hostdata->connected) {
 
 		if (falcon_dont_release) {
 #if 0
@@ -528,7 +523,7 @@
 		}
 		falcon_got_lock = 0;
 		stdma_release();
-		wake_up( &falcon_fairness_wait );
+		wake_up(&falcon_fairness_wait);
 	}
 
 	local_irq_restore(flags);
@@ -549,31 +544,31 @@
  * Complicated, complicated.... Sigh...
  */
 
-static void falcon_get_lock( void )
+static void falcon_get_lock(void)
 {
 	unsigned long flags;
 
-	if (IS_A_TT()) return;
+	if (IS_A_TT())
+		return;
 
 	local_irq_save(flags);
 
-	while( !in_interrupt() && falcon_got_lock && stdma_others_waiting() )
-		sleep_on( &falcon_fairness_wait );
+	while (!in_irq() && falcon_got_lock && stdma_others_waiting())
+		sleep_on(&falcon_fairness_wait);
 
 	while (!falcon_got_lock) {
-		if (in_interrupt())
-			panic( "Falcon SCSI hasn't ST-DMA lock in interrupt" );
+		if (in_irq())
+			panic("Falcon SCSI hasn't ST-DMA lock in interrupt");
 		if (!falcon_trying_lock) {
 			falcon_trying_lock = 1;
 			stdma_lock(scsi_falcon_intr, NULL);
 			falcon_got_lock = 1;
 			falcon_trying_lock = 0;
-			wake_up( &falcon_try_wait );
+			wake_up(&falcon_try_wait);
+		} else {
+			sleep_on(&falcon_try_wait);
 		}
-		else {
-			sleep_on( &falcon_try_wait );
-		}
-	}	
+	}
 
 	local_irq_restore(flags);
 	if (!falcon_got_lock)
@@ -587,18 +582,18 @@
  */
 
 #if 0
-int atari_queue_command (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *))
+int atari_queue_command(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *))
 {
 	/* falcon_get_lock();
 	 * ++guenther: moved to NCR5380_queue_command() to prevent
 	 * race condition, see there for an explanation.
 	 */
-	return( NCR5380_queue_command( cmd, done ) );
+	return NCR5380_queue_command(cmd, done);
 }
 #endif
 
 
-int atari_scsi_detect (struct scsi_host_template *host)
+int atari_scsi_detect(struct scsi_host_template *host)
 {
 	static int called = 0;
 	struct Scsi_Host *instance;
@@ -606,7 +601,7 @@
 	if (!MACH_IS_ATARI ||
 	    (!ATARIHW_PRESENT(ST_SCSI) && !ATARIHW_PRESENT(TT_SCSI)) ||
 	    called)
-		return( 0 );
+		return 0;
 
 	host->proc_name = "Atari";
 
@@ -655,32 +650,33 @@
 	    !ATARIHW_PRESENT(EXTD_DMA) && m68k_num_memory > 1) {
 		atari_dma_buffer = atari_stram_alloc(STRAM_BUFFER_SIZE, "SCSI");
 		if (!atari_dma_buffer) {
-			printk( KERN_ERR "atari_scsi_detect: can't allocate ST-RAM "
-					"double buffer\n" );
-			return( 0 );
+			printk(KERN_ERR "atari_scsi_detect: can't allocate ST-RAM "
+					"double buffer\n");
+			return 0;
 		}
-		atari_dma_phys_buffer = virt_to_phys( atari_dma_buffer );
+		atari_dma_phys_buffer = virt_to_phys(atari_dma_buffer);
 		atari_dma_orig_addr = 0;
 	}
 #endif
-	instance = scsi_register (host, sizeof (struct NCR5380_hostdata));
-	if(instance == NULL)
-	{
+	instance = scsi_register(host, sizeof(struct NCR5380_hostdata));
+	if (instance == NULL) {
 		atari_stram_free(atari_dma_buffer);
 		atari_dma_buffer = 0;
 		return 0;
 	}
 	atari_scsi_host = instance;
-       /* Set irq to 0, to avoid that the mid-level code disables our interrupt
-        * during queue_command calls. This is completely unnecessary, and even
-        * worse causes bad problems on the Falcon, where the int is shared with
-        * IDE and floppy! */
+	/*
+	 * Set irq to 0, to avoid that the mid-level code disables our interrupt
+	 * during queue_command calls. This is completely unnecessary, and even
+	 * worse causes bad problems on the Falcon, where the int is shared with
+	 * IDE and floppy!
+	 */
        instance->irq = 0;
 
 #ifdef CONFIG_ATARI_SCSI_RESET_BOOT
 	atari_scsi_reset_boot();
 #endif
-	NCR5380_init (instance, 0);
+	NCR5380_init(instance, 0);
 
 	if (IS_A_TT()) {
 
@@ -727,11 +723,10 @@
 			 * the rest data bug is fixed, this can be lowered to 1.
 			 */
 			atari_read_overruns = 4;
-		}		
+		}
 #endif /*REAL_DMA*/
-	}
-	else { /* ! IS_A_TT */
-		
+	} else { /* ! IS_A_TT */
+
 		/* Nothing to do for the interrupt: the ST-DMA is initialized
 		 * already by atari_init_INTS()
 		 */
@@ -756,23 +751,21 @@
 			setup_use_tagged_queuing ? "yes" : "no",
 #endif
 			instance->hostt->this_id );
-	NCR5380_print_options (instance);
-	printk ("\n");
+	NCR5380_print_options(instance);
+	printk("\n");
 
 	called = 1;
-	return( 1 );
+	return 1;
 }
 
-#ifdef MODULE
-int atari_scsi_release (struct Scsi_Host *sh)
+int atari_scsi_release(struct Scsi_Host *sh)
 {
 	if (IS_A_TT())
 		free_irq(IRQ_TT_MFP_SCSI, scsi_tt_intr);
 	if (atari_dma_buffer)
-		atari_stram_free (atari_dma_buffer);
+		atari_stram_free(atari_dma_buffer);
 	return 1;
 }
-#endif
 
 void __init atari_scsi_setup(char *str, int *ints)
 {
@@ -781,9 +774,9 @@
 	 * Defaults depend on TT or Falcon, hostid determined at run time.
 	 * Negative values mean don't change.
 	 */
-	
+
 	if (ints[0] < 1) {
-		printk( "atari_scsi_setup: no arguments!\n" );
+		printk("atari_scsi_setup: no arguments!\n");
 		return;
 	}
 
@@ -809,7 +802,7 @@
 		if (ints[4] >= 0 && ints[4] <= 7)
 			setup_hostid = ints[4];
 		else if (ints[4] > 7)
-			printk( "atari_scsi_setup: invalid host ID %d !\n", ints[4] );
+			printk("atari_scsi_setup: invalid host ID %d !\n", ints[4]);
 	}
 #ifdef SUPPORT_TAGS
 	if (ints[0] >= 5) {
@@ -821,7 +814,7 @@
 
 int atari_scsi_bus_reset(Scsi_Cmnd *cmd)
 {
-	int		rv;
+	int rv;
 	struct NCR5380_hostdata *hostdata =
 		(struct NCR5380_hostdata *)cmd->device->host->hostdata;
 
@@ -831,13 +824,12 @@
 	 */
 	/* And abort a maybe active DMA transfer */
 	if (IS_A_TT()) {
-		atari_turnoff_irq( IRQ_TT_MFP_SCSI );
+		atari_turnoff_irq(IRQ_TT_MFP_SCSI);
 #ifdef REAL_DMA
 		tt_scsi_dma.dma_ctrl = 0;
 #endif /* REAL_DMA */
-	}
-	else {
-		atari_turnoff_irq( IRQ_MFP_FSCSI );
+	} else {
+		atari_turnoff_irq(IRQ_MFP_FSCSI);
 #ifdef REAL_DMA
 		st_dma.dma_mode_status = 0x90;
 		atari_dma_active = 0;
@@ -849,52 +841,51 @@
 
 	/* Re-enable ints */
 	if (IS_A_TT()) {
-		atari_turnon_irq( IRQ_TT_MFP_SCSI );
-	}
-	else {
-		atari_turnon_irq( IRQ_MFP_FSCSI );
+		atari_turnon_irq(IRQ_TT_MFP_SCSI);
+	} else {
+		atari_turnon_irq(IRQ_MFP_FSCSI);
 	}
 	if ((rv & SCSI_RESET_ACTION) == SCSI_RESET_SUCCESS)
 		falcon_release_lock_if_possible(hostdata);
 
-	return( rv );
+	return rv;
 }
 
-	
+
 #ifdef CONFIG_ATARI_SCSI_RESET_BOOT
 static void __init atari_scsi_reset_boot(void)
 {
 	unsigned long end;
-	
+
 	/*
 	 * Do a SCSI reset to clean up the bus during initialization. No messing
 	 * with the queues, interrupts, or locks necessary here.
 	 */
 
-	printk( "Atari SCSI: resetting the SCSI bus..." );
+	printk("Atari SCSI: resetting the SCSI bus...");
 
 	/* get in phase */
-	NCR5380_write( TARGET_COMMAND_REG,
-		      PHASE_SR_TO_TCR( NCR5380_read(STATUS_REG) ));
+	NCR5380_write(TARGET_COMMAND_REG,
+		      PHASE_SR_TO_TCR(NCR5380_read(STATUS_REG)));
 
 	/* assert RST */
-	NCR5380_write( INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_RST );
+	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_RST);
 	/* The min. reset hold time is 25us, so 40us should be enough */
-	udelay( 50 );
+	udelay(50);
 	/* reset RST and interrupt */
-	NCR5380_write( INITIATOR_COMMAND_REG, ICR_BASE );
-	NCR5380_read( RESET_PARITY_INTERRUPT_REG );
+	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+	NCR5380_read(RESET_PARITY_INTERRUPT_REG);
 
 	end = jiffies + AFTER_RESET_DELAY;
 	while (time_before(jiffies, end))
 		barrier();
 
-	printk( " done\n" );
+	printk(" done\n");
 }
 #endif
 
 
-const char * atari_scsi_info (struct Scsi_Host *host)
+const char *atari_scsi_info(struct Scsi_Host *host)
 {
 	/* atari_scsi_detect() is verbose enough... */
 	static const char string[] = "Atari native SCSI";
@@ -904,10 +895,10 @@
 
 #if defined(REAL_DMA)
 
-unsigned long atari_scsi_dma_setup( struct Scsi_Host *instance, void *data,
-				   unsigned long count, int dir )
+unsigned long atari_scsi_dma_setup(struct Scsi_Host *instance, void *data,
+				   unsigned long count, int dir)
 {
-	unsigned long addr = virt_to_phys( data );
+	unsigned long addr = virt_to_phys(data);
 
 	DMA_PRINTK("scsi%d: setting up dma, data = %p, phys = %lx, count = %ld, "
 		   "dir = %d\n", instance->host_no, data, addr, count, dir);
@@ -919,38 +910,37 @@
 		 * wanted address.
 		 */
 		if (dir)
-			memcpy( atari_dma_buffer, data, count );
+			memcpy(atari_dma_buffer, data, count);
 		else
 			atari_dma_orig_addr = data;
 		addr = atari_dma_phys_buffer;
 	}
-	
+
 	atari_dma_startaddr = addr;	/* Needed for calculating residual later. */
-  
+
 	/* Cache cleanup stuff: On writes, push any dirty cache out before sending
 	 * it to the peripheral. (Must be done before DMA setup, since at least
 	 * the ST-DMA begins to fill internal buffers right after setup. For
 	 * reads, invalidate any cache, may be altered after DMA without CPU
 	 * knowledge.
-	 * 
+	 *
 	 * ++roman: For the Medusa, there's no need at all for that cache stuff,
 	 * because the hardware does bus snooping (fine!).
 	 */
-	dma_cache_maintenance( addr, count, dir );
+	dma_cache_maintenance(addr, count, dir);
 
 	if (count == 0)
 		printk(KERN_NOTICE "SCSI warning: DMA programmed for 0 bytes !\n");
 
 	if (IS_A_TT()) {
 		tt_scsi_dma.dma_ctrl = dir;
-		SCSI_DMA_WRITE_P( dma_addr, addr );
-		SCSI_DMA_WRITE_P( dma_cnt, count );
+		SCSI_DMA_WRITE_P(dma_addr, addr);
+		SCSI_DMA_WRITE_P(dma_cnt, count);
 		tt_scsi_dma.dma_ctrl = dir | 2;
-	}
-	else { /* ! IS_A_TT */
-  
+	} else { /* ! IS_A_TT */
+
 		/* set address */
-		SCSI_DMA_SETADR( addr );
+		SCSI_DMA_SETADR(addr);
 
 		/* toggle direction bit to clear FIFO and set DMA direction */
 		dir <<= 8;
@@ -968,13 +958,13 @@
 		atari_dma_active = 1;
 	}
 
-	return( count );
+	return count;
 }
 
 
-static long atari_scsi_dma_residual( struct Scsi_Host *instance )
+static long atari_scsi_dma_residual(struct Scsi_Host *instance)
 {
-	return( atari_dma_residual );
+	return atari_dma_residual;
 }
 
 
@@ -982,13 +972,13 @@
 #define	CMD_SURELY_BYTE_MODE	1
 #define	CMD_MODE_UNKNOWN		2
 
-static int falcon_classify_cmd( Scsi_Cmnd *cmd )
+static int falcon_classify_cmd(Scsi_Cmnd *cmd)
 {
 	unsigned char opcode = cmd->cmnd[0];
-	
+
 	if (opcode == READ_DEFECT_DATA || opcode == READ_LONG ||
-		opcode == READ_BUFFER)
-		return( CMD_SURELY_BYTE_MODE );
+	    opcode == READ_BUFFER)
+		return CMD_SURELY_BYTE_MODE;
 	else if (opcode == READ_6 || opcode == READ_10 ||
 		 opcode == 0xa8 /* READ_12 */ || opcode == READ_REVERSE ||
 		 opcode == RECOVER_BUFFERED_DATA) {
@@ -996,12 +986,11 @@
 		 * needed here: The transfer is block-mode only if the 'fixed' bit is
 		 * set! */
 		if (cmd->device->type == TYPE_TAPE && !(cmd->cmnd[1] & 1))
-			return( CMD_SURELY_BYTE_MODE );
+			return CMD_SURELY_BYTE_MODE;
 		else
-			return( CMD_SURELY_BLOCK_MODE );
-	}
-	else
-		return( CMD_MODE_UNKNOWN );
+			return CMD_SURELY_BLOCK_MODE;
+	} else
+		return CMD_MODE_UNKNOWN;
 }
 
 
@@ -1014,19 +1003,18 @@
  * the overrun problem, so this question is academic :-)
  */
 
-static unsigned long atari_dma_xfer_len( unsigned long wanted_len,
-					Scsi_Cmnd *cmd,
-					int write_flag )
+static unsigned long atari_dma_xfer_len(unsigned long wanted_len,
+					Scsi_Cmnd *cmd, int write_flag)
 {
 	unsigned long	possible_len, limit;
 #ifndef CONFIG_TT_DMA_EMUL
 	if (MACH_IS_HADES)
 		/* Hades has no SCSI DMA at all :-( Always force use of PIO */
-		return( 0 );
-#endif	
+		return 0;
+#endif
 	if (IS_A_TT())
 		/* TT SCSI DMA can transfer arbitrary #bytes */
-		return( wanted_len );
+		return wanted_len;
 
 	/* ST DMA chip is stupid -- only multiples of 512 bytes! (and max.
 	 * 255*512 bytes, but this should be enough)
@@ -1062,8 +1050,7 @@
 		 * this).
 		 */
 		possible_len = wanted_len;
-	}
-	else {
+	} else {
 		/* Read operations: if the wanted transfer length is not a multiple of
 		 * 512, we cannot use DMA, since the ST-DMA cannot split transfers
 		 * (no interrupt on DMA finished!)
@@ -1073,15 +1060,15 @@
 		else {
 			/* Now classify the command (see above) and decide whether it is
 			 * allowed to do DMA at all */
-			switch( falcon_classify_cmd( cmd )) {
-			  case CMD_SURELY_BLOCK_MODE:
+			switch (falcon_classify_cmd(cmd)) {
+			case CMD_SURELY_BLOCK_MODE:
 				possible_len = wanted_len;
 				break;
-			  case CMD_SURELY_BYTE_MODE:
+			case CMD_SURELY_BYTE_MODE:
 				possible_len = 0; /* DMA prohibited */
 				break;
-			  case CMD_MODE_UNKNOWN:
-			  default:
+			case CMD_MODE_UNKNOWN:
+			default:
 				/* For unknown commands assume block transfers if the transfer
 				 * size/allocation length is >= 1024 */
 				possible_len = (wanted_len < 1024) ? 0 : wanted_len;
@@ -1089,9 +1076,9 @@
 			}
 		}
 	}
-	
+
 	/* Last step: apply the hard limit on DMA transfers */
-	limit = (atari_dma_buffer && !STRAM_ADDR( virt_to_phys(cmd->SCp.ptr) )) ?
+	limit = (atari_dma_buffer && !STRAM_ADDR(virt_to_phys(cmd->SCp.ptr))) ?
 		    STRAM_BUFFER_SIZE : 255*512;
 	if (possible_len > limit)
 		possible_len = limit;
@@ -1100,7 +1087,7 @@
 		DMA_PRINTK("Sorry, must cut DMA transfer size to %ld bytes "
 			   "instead of %ld\n", possible_len, wanted_len);
 
-	return( possible_len );
+	return possible_len;
 }
 
 
@@ -1114,23 +1101,23 @@
  * NCR5380_write call these functions via function pointers.
  */
 
-static unsigned char atari_scsi_tt_reg_read( unsigned char reg )
+static unsigned char atari_scsi_tt_reg_read(unsigned char reg)
 {
-	return( tt_scsi_regp[reg * 2] );
+	return tt_scsi_regp[reg * 2];
 }
 
-static void atari_scsi_tt_reg_write( unsigned char reg, unsigned char value )
+static void atari_scsi_tt_reg_write(unsigned char reg, unsigned char value)
 {
 	tt_scsi_regp[reg * 2] = value;
 }
 
-static unsigned char atari_scsi_falcon_reg_read( unsigned char reg )
+static unsigned char atari_scsi_falcon_reg_read(unsigned char reg)
 {
 	dma_wd.dma_mode_status= (u_short)(0x88 + reg);
-	return( (u_char)dma_wd.fdc_acces_seccount );
+	return (u_char)dma_wd.fdc_acces_seccount;
 }
 
-static void atari_scsi_falcon_reg_write( unsigned char reg, unsigned char value )
+static void atari_scsi_falcon_reg_write(unsigned char reg, unsigned char value)
 {
 	dma_wd.dma_mode_status = (u_short)(0x88 + reg);
 	dma_wd.fdc_acces_seccount = (u_short)value;
diff --git a/drivers/scsi/atari_scsi.h b/drivers/scsi/atari_scsi.h
index f917bdd..efadb8d5 100644
--- a/drivers/scsi/atari_scsi.h
+++ b/drivers/scsi/atari_scsi.h
@@ -21,11 +21,7 @@
 int atari_scsi_detect (struct scsi_host_template *);
 const char *atari_scsi_info (struct Scsi_Host *);
 int atari_scsi_reset (Scsi_Cmnd *, unsigned int);
-#ifdef MODULE
 int atari_scsi_release (struct Scsi_Host *);
-#else
-#define atari_scsi_release NULL
-#endif
 
 /* The values for CMD_PER_LUN and CAN_QUEUE are somehow arbitrary. Higher
  * values should work, too; try it! (but cmd_per_lun costs memory!) */
@@ -63,6 +59,32 @@
 #define	NCR5380_dma_xfer_len(i,cmd,phase) \
 	atari_dma_xfer_len(cmd->SCp.this_residual,cmd,((phase) & SR_IO) ? 0 : 1)
 
+/* former generic SCSI error handling stuff */
+
+#define SCSI_ABORT_SNOOZE 0
+#define SCSI_ABORT_SUCCESS 1
+#define SCSI_ABORT_PENDING 2
+#define SCSI_ABORT_BUSY 3
+#define SCSI_ABORT_NOT_RUNNING 4
+#define SCSI_ABORT_ERROR 5
+
+#define SCSI_RESET_SNOOZE 0
+#define SCSI_RESET_PUNT 1
+#define SCSI_RESET_SUCCESS 2
+#define SCSI_RESET_PENDING 3
+#define SCSI_RESET_WAKEUP 4
+#define SCSI_RESET_NOT_RUNNING 5
+#define SCSI_RESET_ERROR 6
+
+#define SCSI_RESET_SYNCHRONOUS		0x01
+#define SCSI_RESET_ASYNCHRONOUS		0x02
+#define SCSI_RESET_SUGGEST_BUS_RESET	0x04
+#define SCSI_RESET_SUGGEST_HOST_RESET	0x08
+
+#define SCSI_RESET_BUS_RESET 0x100
+#define SCSI_RESET_HOST_RESET 0x200
+#define SCSI_RESET_ACTION   0xff
+
 /* Debugging printk definitions:
  *
  *  ARB  -> arbitration
@@ -91,144 +113,58 @@
  *
  */
 
-#if NDEBUG & NDEBUG_ARBITRATION
+#define dprint(flg, format...)			\
+({						\
+	if (NDEBUG & (flg))			\
+		printk(KERN_DEBUG format);	\
+})
+
 #define ARB_PRINTK(format, args...) \
-	printk(KERN_DEBUG format , ## args)
-#else
-#define ARB_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_AUTOSENSE
+	dprint(NDEBUG_ARBITRATION, format , ## args)
 #define ASEN_PRINTK(format, args...) \
-	printk(KERN_DEBUG format , ## args)
-#else
-#define ASEN_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_DMA
+	dprint(NDEBUG_AUTOSENSE, format , ## args)
 #define DMA_PRINTK(format, args...) \
-	printk(KERN_DEBUG format , ## args)
-#else
-#define DMA_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_HANDSHAKE
+	dprint(NDEBUG_DMA, format , ## args)
 #define HSH_PRINTK(format, args...) \
-	printk(KERN_DEBUG format , ## args)
-#else
-#define HSH_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_INFORMATION
+	dprint(NDEBUG_HANDSHAKE, format , ## args)
 #define INF_PRINTK(format, args...) \
-	printk(KERN_DEBUG format , ## args)
-#else
-#define INF_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_INIT
+	dprint(NDEBUG_INFORMATION, format , ## args)
 #define INI_PRINTK(format, args...) \
-	printk(KERN_DEBUG format , ## args)
-#else
-#define INI_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_INTR
+	dprint(NDEBUG_INIT, format , ## args)
 #define INT_PRINTK(format, args...) \
-	printk(KERN_DEBUG format , ## args)
-#else
-#define INT_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_LINKED
+	dprint(NDEBUG_INTR, format , ## args)
 #define LNK_PRINTK(format, args...) \
-	printk(KERN_DEBUG format , ## args)
-#else
-#define LNK_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_MAIN
+	dprint(NDEBUG_LINKED, format , ## args)
 #define MAIN_PRINTK(format, args...) \
-	printk(KERN_DEBUG format , ## args)
-#else
-#define MAIN_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_NO_DATAOUT
+	dprint(NDEBUG_MAIN, format , ## args)
 #define NDAT_PRINTK(format, args...) \
-	printk(KERN_DEBUG format , ## args)
-#else
-#define NDAT_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_NO_WRITE
+	dprint(NDEBUG_NO_DATAOUT, format , ## args)
 #define NWR_PRINTK(format, args...) \
-	printk(KERN_DEBUG format , ## args)
-#else
-#define NWR_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_PIO
+	dprint(NDEBUG_NO_WRITE, format , ## args)
 #define PIO_PRINTK(format, args...) \
-	printk(KERN_DEBUG format , ## args)
-#else
-#define PIO_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_PSEUDO_DMA
+	dprint(NDEBUG_PIO, format , ## args)
 #define PDMA_PRINTK(format, args...) \
-	printk(KERN_DEBUG format , ## args)
-#else
-#define PDMA_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_QUEUES
+	dprint(NDEBUG_PSEUDO_DMA, format , ## args)
 #define QU_PRINTK(format, args...) \
-	printk(KERN_DEBUG format , ## args)
-#else
-#define QU_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_RESELECTION
+	dprint(NDEBUG_QUEUES, format , ## args)
 #define RSL_PRINTK(format, args...) \
-	printk(KERN_DEBUG format , ## args)
-#else
-#define RSL_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_SELECTION
+	dprint(NDEBUG_RESELECTION, format , ## args)
 #define SEL_PRINTK(format, args...) \
-	printk(KERN_DEBUG format , ## args)
-#else
-#define SEL_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_USLEEP
+	dprint(NDEBUG_SELECTION, format , ## args)
 #define USL_PRINTK(format, args...) \
-	printk(KERN_DEBUG format , ## args)
-#else
-#define USL_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_LAST_BYTE_SENT
+	dprint(NDEBUG_USLEEP, format , ## args)
 #define LBS_PRINTK(format, args...) \
-	printk(KERN_DEBUG format , ## args)
-#else
-#define LBS_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_RESTART_SELECT
+	dprint(NDEBUG_LAST_BYTE_SENT, format , ## args)
 #define RSS_PRINTK(format, args...) \
-	printk(KERN_DEBUG format , ## args)
-#else
-#define RSS_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_EXTENDED
+	dprint(NDEBUG_RESTART_SELECT, format , ## args)
 #define EXT_PRINTK(format, args...) \
-	printk(KERN_DEBUG format , ## args)
-#else
-#define EXT_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_ABORT
+	dprint(NDEBUG_EXTENDED, format , ## args)
 #define ABRT_PRINTK(format, args...) \
-	printk(KERN_DEBUG format , ## args)
-#else
-#define ABRT_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_TAGS
+	dprint(NDEBUG_ABORT, format , ## args)
 #define TAG_PRINTK(format, args...) \
-	printk(KERN_DEBUG format , ## args)
-#else
-#define TAG_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_MERGING
+	dprint(NDEBUG_TAGS, format , ## args)
 #define MER_PRINTK(format, args...) \
-	printk(KERN_DEBUG format , ## args)
-#else
-#define MER_PRINTK(format, args...)
-#endif
+	dprint(NDEBUG_MERGING, format , ## args)
 
 /* conditional macros for NCR5380_print_{,phase,status} */
 
diff --git a/drivers/scsi/constants.c b/drivers/scsi/constants.c
index 61f6024..2a458d6 100644
--- a/drivers/scsi/constants.c
+++ b/drivers/scsi/constants.c
@@ -202,31 +202,29 @@
 }
 
 /* attempt to guess cdb length if cdb_len==0 . No trailing linefeed. */
-static void print_opcode_name(unsigned char * cdbp, int cdb_len,
-			      int start_of_line)
+static void print_opcode_name(unsigned char * cdbp, int cdb_len)
 {
 	int sa, len, cdb0;
 	const char * name;
-	const char * leadin = start_of_line ? KERN_INFO : "";
 
 	cdb0 = cdbp[0];
 	switch(cdb0) {
 	case VARIABLE_LENGTH_CMD:
 		len = cdbp[7] + 8;
 		if (len < 10) {
-			printk("%sshort variable length command, "
-			       "len=%d ext_len=%d", leadin, len, cdb_len);
+			printk("short variable length command, "
+			       "len=%d ext_len=%d", len, cdb_len);
 			break;
 		}
 		sa = (cdbp[8] << 8) + cdbp[9];
 		name = get_sa_name(maint_in_arr, MAINT_IN_SZ, sa);
 		if (name) {
-			printk("%s%s", leadin, name);
+			printk("%s", name);
 			if ((cdb_len > 0) && (len != cdb_len))
 				printk(", in_cdb_len=%d, ext_len=%d",
 				       len, cdb_len);
 		} else {
-			printk("%scdb[0]=0x%x, sa=0x%x", leadin, cdb0, sa);
+			printk("cdb[0]=0x%x, sa=0x%x", cdb0, sa);
 			if ((cdb_len > 0) && (len != cdb_len))
 				printk(", in_cdb_len=%d, ext_len=%d",
 				       len, cdb_len);
@@ -236,83 +234,80 @@
 		sa = cdbp[1] & 0x1f;
 		name = get_sa_name(maint_in_arr, MAINT_IN_SZ, sa);
 		if (name)
-			printk("%s%s", leadin, name);
+			printk("%s", name);
 		else
-			printk("%scdb[0]=0x%x, sa=0x%x", leadin, cdb0, sa);
+			printk("cdb[0]=0x%x, sa=0x%x", cdb0, sa);
 		break;
 	case MAINTENANCE_OUT:
 		sa = cdbp[1] & 0x1f;
 		name = get_sa_name(maint_out_arr, MAINT_OUT_SZ, sa);
 		if (name)
-			printk("%s%s", leadin, name);
+			printk("%s", name);
 		else
-			printk("%scdb[0]=0x%x, sa=0x%x", leadin, cdb0, sa);
+			printk("cdb[0]=0x%x, sa=0x%x", cdb0, sa);
 		break;
 	case SERVICE_ACTION_IN_12:
 		sa = cdbp[1] & 0x1f;
 		name = get_sa_name(serv_in12_arr, SERV_IN12_SZ, sa);
 		if (name)
-			printk("%s%s", leadin, name);
+			printk("%s", name);
 		else
-			printk("%scdb[0]=0x%x, sa=0x%x", leadin, cdb0, sa);
+			printk("cdb[0]=0x%x, sa=0x%x", cdb0, sa);
 		break;
 	case SERVICE_ACTION_OUT_12:
 		sa = cdbp[1] & 0x1f;
 		name = get_sa_name(serv_out12_arr, SERV_OUT12_SZ, sa);
 		if (name)
-			printk("%s%s", leadin, name);
+			printk("%s", name);
 		else
-			printk("%scdb[0]=0x%x, sa=0x%x", leadin, cdb0, sa);
+			printk("cdb[0]=0x%x, sa=0x%x", cdb0, sa);
 		break;
 	case SERVICE_ACTION_IN_16:
 		sa = cdbp[1] & 0x1f;
 		name = get_sa_name(serv_in16_arr, SERV_IN16_SZ, sa);
 		if (name)
-			printk("%s%s", leadin, name);
+			printk("%s", name);
 		else
-			printk("%scdb[0]=0x%x, sa=0x%x", leadin, cdb0, sa);
+			printk("cdb[0]=0x%x, sa=0x%x", cdb0, sa);
 		break;
 	case SERVICE_ACTION_OUT_16:
 		sa = cdbp[1] & 0x1f;
 		name = get_sa_name(serv_out16_arr, SERV_OUT16_SZ, sa);
 		if (name)
-			printk("%s%s", leadin, name);
+			printk("%s", name);
 		else
-			printk("%scdb[0]=0x%x, sa=0x%x", leadin, cdb0, sa);
+			printk("cdb[0]=0x%x, sa=0x%x", cdb0, sa);
 		break;
 	default:
 		if (cdb0 < 0xc0) {
 			name = cdb_byte0_names[cdb0];
 			if (name)
-				printk("%s%s", leadin, name);
+				printk("%s", name);
 			else
-				printk("%scdb[0]=0x%x (reserved)",
-				       leadin, cdb0);
+				printk("cdb[0]=0x%x (reserved)", cdb0);
 		} else
-			printk("%scdb[0]=0x%x (vendor)", leadin, cdb0);
+			printk("cdb[0]=0x%x (vendor)", cdb0);
 		break;
 	}
 }
 
 #else /* ifndef CONFIG_SCSI_CONSTANTS */
 
-static void print_opcode_name(unsigned char * cdbp, int cdb_len,
-			      int start_of_line)
+static void print_opcode_name(unsigned char * cdbp, int cdb_len)
 {
 	int sa, len, cdb0;
-	const char * leadin = start_of_line ? KERN_INFO : "";
 
 	cdb0 = cdbp[0];
 	switch(cdb0) {
 	case VARIABLE_LENGTH_CMD:
 		len = cdbp[7] + 8;
 		if (len < 10) {
-			printk("%sshort opcode=0x%x command, len=%d "
-			       "ext_len=%d", leadin, cdb0, len, cdb_len);
+			printk("short opcode=0x%x command, len=%d "
+			       "ext_len=%d", cdb0, len, cdb_len);
 			break;
 		}
 		sa = (cdbp[8] << 8) + cdbp[9];
-		printk("%scdb[0]=0x%x, sa=0x%x", leadin, cdb0, sa);
+		printk("cdb[0]=0x%x, sa=0x%x", cdb0, sa);
 		if (len != cdb_len)
 			printk(", in_cdb_len=%d, ext_len=%d", len, cdb_len);
 		break;
@@ -323,49 +318,48 @@
 	case SERVICE_ACTION_IN_16:
 	case SERVICE_ACTION_OUT_16:
 		sa = cdbp[1] & 0x1f;
-		printk("%scdb[0]=0x%x, sa=0x%x", leadin, cdb0, sa);
+		printk("cdb[0]=0x%x, sa=0x%x", cdb0, sa);
 		break;
 	default:
 		if (cdb0 < 0xc0)
-			printk("%scdb[0]=0x%x", leadin, cdb0);
+			printk("cdb[0]=0x%x", cdb0);
 		else
-			printk("%scdb[0]=0x%x (vendor)", leadin, cdb0);
+			printk("cdb[0]=0x%x (vendor)", cdb0);
 		break;
 	}
 }
 #endif  
 
-void __scsi_print_command(unsigned char *command)
+void __scsi_print_command(unsigned char *cdb)
 {
 	int k, len;
 
-	print_opcode_name(command, 0, 1);
-	if (VARIABLE_LENGTH_CMD == command[0])
-		len = command[7] + 8;
+	print_opcode_name(cdb, 0);
+	if (VARIABLE_LENGTH_CMD == cdb[0])
+		len = cdb[7] + 8;
 	else
-		len = COMMAND_SIZE(command[0]);
+		len = COMMAND_SIZE(cdb[0]);
 	/* print out all bytes in cdb */
 	for (k = 0; k < len; ++k) 
-		printk(" %02x", command[k]);
+		printk(" %02x", cdb[k]);
 	printk("\n");
 }
 EXPORT_SYMBOL(__scsi_print_command);
 
-/* This function (perhaps with the addition of peripheral device type)
- * is more approriate than __scsi_print_command(). Perhaps that static
- * can be dropped later if it replaces the __scsi_print_command version.
- */
-static void scsi_print_cdb(unsigned char *cdb, int cdb_len, int start_of_line)
+void scsi_print_command(struct scsi_cmnd *cmd)
 {
 	int k;
 
-	print_opcode_name(cdb, cdb_len, start_of_line);
+	scmd_printk(KERN_INFO, cmd, "CDB: ");
+	print_opcode_name(cmd->cmnd, cmd->cmd_len);
+
 	/* print out all bytes in cdb */
 	printk(":");
-	for (k = 0; k < cdb_len; ++k) 
-		printk(" %02x", cdb[k]);
+	for (k = 0; k < cmd->cmd_len; ++k)
+		printk(" %02x", cmd->cmnd[k]);
 	printk("\n");
 }
+EXPORT_SYMBOL(scsi_print_command);
 
 /**
  *
@@ -410,7 +404,11 @@
 	const char * text;
 };
 
-static struct error_info additional[] =
+/*
+ * The canonical list of T10 Additional Sense Codes is available at:
+ * http://www.t10.org/lists/asc-num.txt
+ */
+static const struct error_info additional[] =
 {
 	{0x0000, "No additional sense information"},
 	{0x0001, "Filemark detected"},
@@ -714,6 +712,7 @@
 
 	{0x2F00, "Commands cleared by another initiator"},
 	{0x2F01, "Commands cleared by power loss notification"},
+	{0x2F02, "Commands cleared by device server"},
 
 	{0x3000, "Incompatible medium installed"},
 	{0x3001, "Cannot read medium - unknown format"},
@@ -1176,67 +1175,77 @@
 }
 EXPORT_SYMBOL(scsi_extd_sense_format);
 
-/* Print extended sense information; no leadin, no linefeed */
-static void
+void
 scsi_show_extd_sense(unsigned char asc, unsigned char ascq)
 {
-	const char *extd_sense_fmt = scsi_extd_sense_format(asc, ascq);
+        const char *extd_sense_fmt = scsi_extd_sense_format(asc, ascq);
 
 	if (extd_sense_fmt) {
 		if (strstr(extd_sense_fmt, "%x")) {
-			printk("Additional sense: ");
+			printk("Add. Sense: ");
 			printk(extd_sense_fmt, ascq);
 		} else
-			printk("Additional sense: %s", extd_sense_fmt);
+			printk("Add. Sense: %s", extd_sense_fmt);
 	} else {
 		if (asc >= 0x80)
-			printk("<<vendor>> ASC=0x%x ASCQ=0x%x", asc, ascq);
+			printk("<<vendor>> ASC=0x%x ASCQ=0x%x", asc,
+			       ascq);
 		if (ascq >= 0x80)
-			printk("ASC=0x%x <<vendor>> ASCQ=0x%x", asc, ascq);
+			printk("ASC=0x%x <<vendor>> ASCQ=0x%x", asc,
+			       ascq);
 		else
 			printk("ASC=0x%x ASCQ=0x%x", asc, ascq);
 	}
+
+	printk("\n");
 }
+EXPORT_SYMBOL(scsi_show_extd_sense);
 
 void
-scsi_print_sense_hdr(const char *name, struct scsi_sense_hdr *sshdr)
+scsi_show_sense_hdr(struct scsi_sense_hdr *sshdr)
 {
 	const char *sense_txt;
-	/* An example of deferred is when an earlier write to disk cache
-	 * succeeded, but now the disk discovers that it cannot write the
-	 * data to the magnetic media.
-	 */
-	const char *error = scsi_sense_is_deferred(sshdr) ? 
-		"<<DEFERRED>>" : "Current";
-	printk(KERN_INFO "%s: %s", name, error);
-	if (sshdr->response_code >= 0x72)
-		printk(" [descriptor]");
 
 	sense_txt = scsi_sense_key_string(sshdr->sense_key);
 	if (sense_txt)
-		printk(": sense key: %s\n", sense_txt);
+		printk("Sense Key : %s ", sense_txt);
 	else
-		printk(": sense key=0x%x\n", sshdr->sense_key);
-	printk(KERN_INFO "    ");
-	scsi_show_extd_sense(sshdr->asc, sshdr->ascq);
+		printk("Sense Key : 0x%x ", sshdr->sense_key);
+
+	printk("%s", scsi_sense_is_deferred(sshdr) ? "[deferred] " :
+	       "[current] ");
+
+	if (sshdr->response_code >= 0x72)
+		printk("[descriptor]");
+
 	printk("\n");
 }
+EXPORT_SYMBOL(scsi_show_sense_hdr);
+
+/*
+ * Print normalized SCSI sense header with a prefix.
+ */
+void
+scsi_print_sense_hdr(const char *name, struct scsi_sense_hdr *sshdr)
+{
+	printk(KERN_INFO "%s: ", name);
+	scsi_show_sense_hdr(sshdr);
+	printk(KERN_INFO "%s: ", name);
+	scsi_show_extd_sense(sshdr->asc, sshdr->ascq);
+}
 EXPORT_SYMBOL(scsi_print_sense_hdr);
 
-/* Print sense information */
 void
-__scsi_print_sense(const char *name, const unsigned char *sense_buffer,
-		   int sense_len)
+scsi_decode_sense_buffer(const unsigned char *sense_buffer, int sense_len,
+		       struct scsi_sense_hdr *sshdr)
 {
 	int k, num, res;
-	unsigned int info;
-	struct scsi_sense_hdr ssh;
     
-	res = scsi_normalize_sense(sense_buffer, sense_len, &ssh);
+	res = scsi_normalize_sense(sense_buffer, sense_len, sshdr);
 	if (0 == res) {
 		/* this may be SCSI-1 sense data */
 		num = (sense_len < 32) ? sense_len : 32;
-		printk(KERN_INFO "Unrecognized sense data (in hex):");
+		printk("Unrecognized sense data (in hex):");
 		for (k = 0; k < num; ++k) {
 			if (0 == (k % 16)) {
 				printk("\n");
@@ -1247,11 +1256,20 @@
 		printk("\n");
 		return;
 	}
-	scsi_print_sense_hdr(name, &ssh);
-	if (ssh.response_code < 0x72) {
+}
+
+void
+scsi_decode_sense_extras(const unsigned char *sense_buffer, int sense_len,
+			 struct scsi_sense_hdr *sshdr)
+{
+	int k, num, res;
+
+	if (sshdr->response_code < 0x72)
+	{
 		/* only decode extras for "fixed" format now */
 		char buff[80];
 		int blen, fixed_valid;
+		unsigned int info;
 
 		fixed_valid = sense_buffer[0] & 0x80;
 		info = ((sense_buffer[3] << 24) | (sense_buffer[4] << 16) |
@@ -1281,13 +1299,13 @@
 			res += snprintf(buff + res, blen - res, "ILI");
 		}
 		if (res > 0)
-			printk(KERN_INFO "%s\n", buff);
-	} else if (ssh.additional_length > 0) {
+			printk("%s\n", buff);
+	} else if (sshdr->additional_length > 0) {
 		/* descriptor format with sense descriptors */
-		num = 8 + ssh.additional_length;
+		num = 8 + sshdr->additional_length;
 		num = (sense_len < num) ? sense_len : num;
-		printk(KERN_INFO "Descriptor sense data with sense "
-		       "descriptors (in hex):");
+		printk("Descriptor sense data with sense descriptors "
+		       "(in hex):");
 		for (k = 0; k < num; ++k) {
 			if (0 == (k % 16)) {
 				printk("\n");
@@ -1295,30 +1313,43 @@
 			}
 			printk("%02x ", sense_buffer[k]);
 		}
+
 		printk("\n");
 	}
+
+}
+
+/* Normalize and print sense buffer with name prefix */
+void __scsi_print_sense(const char *name, const unsigned char *sense_buffer,
+			int sense_len)
+{
+	struct scsi_sense_hdr sshdr;
+
+	printk(KERN_INFO "%s: ", name);
+	scsi_decode_sense_buffer(sense_buffer, sense_len, &sshdr);
+	scsi_show_sense_hdr(&sshdr);
+	scsi_decode_sense_extras(sense_buffer, sense_len, &sshdr);
+	printk(KERN_INFO "%s: ", name);
+	scsi_show_extd_sense(sshdr.asc, sshdr.ascq);
 }
 EXPORT_SYMBOL(__scsi_print_sense);
 
-void scsi_print_sense(const char *devclass, struct scsi_cmnd *cmd)
+/* Normalize and print sense buffer in SCSI command */
+void scsi_print_sense(char *name, struct scsi_cmnd *cmd)
 {
-	const char *name = devclass;
+	struct scsi_sense_hdr sshdr;
 
-	if (cmd->request->rq_disk)
-		name = cmd->request->rq_disk->disk_name;
-	__scsi_print_sense(name, cmd->sense_buffer, SCSI_SENSE_BUFFERSIZE);
+	scmd_printk(KERN_INFO, cmd, "");
+	scsi_decode_sense_buffer(cmd->sense_buffer, SCSI_SENSE_BUFFERSIZE,
+				 &sshdr);
+	scsi_show_sense_hdr(&sshdr);
+	scsi_decode_sense_extras(cmd->sense_buffer, SCSI_SENSE_BUFFERSIZE,
+				 &sshdr);
+	scmd_printk(KERN_INFO, cmd, "");
+	scsi_show_extd_sense(sshdr.asc, sshdr.ascq);
 }
 EXPORT_SYMBOL(scsi_print_sense);
 
-void scsi_print_command(struct scsi_cmnd *cmd)
-{
-	/* Assume appended output (i.e. not at start of line) */
-	sdev_printk("", cmd->device, "\n");
-	printk(KERN_INFO "        command: ");
-	scsi_print_cdb(cmd->cmnd, cmd->cmd_len, 0);
-}
-EXPORT_SYMBOL(scsi_print_command);
-
 #ifdef CONFIG_SCSI_CONSTANTS
 
 static const char * const hostbyte_table[]={
@@ -1327,25 +1358,6 @@
 "DID_PASSTHROUGH", "DID_SOFT_ERROR", "DID_IMM_RETRY"};
 #define NUM_HOSTBYTE_STRS ARRAY_SIZE(hostbyte_table)
 
-void scsi_print_hostbyte(int scsiresult)
-{
-	int hb = host_byte(scsiresult);
-
-	printk("Hostbyte=0x%02x", hb);
-	if (hb < NUM_HOSTBYTE_STRS)
-		printk("(%s) ", hostbyte_table[hb]);
-	else
-		printk("is invalid ");
-}
-#else
-void scsi_print_hostbyte(int scsiresult)
-{
-	printk("Hostbyte=0x%02x ", host_byte(scsiresult));
-}
-#endif
-
-#ifdef CONFIG_SCSI_CONSTANTS
-
 static const char * const driverbyte_table[]={
 "DRIVER_OK", "DRIVER_BUSY", "DRIVER_SOFT",  "DRIVER_MEDIA", "DRIVER_ERROR",
 "DRIVER_INVALID", "DRIVER_TIMEOUT", "DRIVER_HARD", "DRIVER_SENSE"};
@@ -1356,19 +1368,35 @@
 "SUGGEST_5", "SUGGEST_6", "SUGGEST_7", "SUGGEST_SENSE"};
 #define NUM_SUGGEST_STRS ARRAY_SIZE(driversuggest_table)
 
-void scsi_print_driverbyte(int scsiresult)
+void scsi_show_result(int result)
 {
-	int dr = (driver_byte(scsiresult) & DRIVER_MASK);
-	int su = ((driver_byte(scsiresult) & SUGGEST_MASK) >> 4);
+	int hb = host_byte(result);
+	int db = (driver_byte(result) & DRIVER_MASK);
+	int su = ((driver_byte(result) & SUGGEST_MASK) >> 4);
 
-	printk("Driverbyte=0x%02x ", driver_byte(scsiresult));
-	printk("(%s,%s) ",
-	       (dr < NUM_DRIVERBYTE_STRS ? driverbyte_table[dr] : "invalid"),
+	printk("Result: hostbyte=%s driverbyte=%s,%s\n",
+	       (hb < NUM_HOSTBYTE_STRS ? hostbyte_table[hb]     : "invalid"),
+	       (db < NUM_DRIVERBYTE_STRS ? driverbyte_table[db] : "invalid"),
 	       (su < NUM_SUGGEST_STRS ? driversuggest_table[su] : "invalid"));
 }
+
 #else
-void scsi_print_driverbyte(int scsiresult)
+
+void scsi_show_result(int result)
 {
-	printk("Driverbyte=0x%02x ", driver_byte(scsiresult));
+	printk("Result: hostbyte=0x%02x driverbyte=0x%02x\n",
+	       host_byte(result), driver_byte(result));
 }
+
 #endif
+EXPORT_SYMBOL(scsi_show_result);
+
+
+void scsi_print_result(struct scsi_cmnd *cmd)
+{
+	scmd_printk(KERN_INFO, cmd, "");
+	scsi_show_result(cmd->result);
+}
+EXPORT_SYMBOL(scsi_print_result);
+
+
diff --git a/drivers/scsi/dpt/dpti_i2o.h b/drivers/scsi/dpt/dpti_i2o.h
index 5a49216..100b49ba 100644
--- a/drivers/scsi/dpt/dpti_i2o.h
+++ b/drivers/scsi/dpt/dpti_i2o.h
@@ -31,7 +31,7 @@
  *	Tunable parameters first
  */
 
-/* How many different OSM's are we allowing */ 
+/* How many different OSM's are we allowing */
 #define MAX_I2O_MODULES		64
 
 #define I2O_EVT_CAPABILITY_OTHER		0x01
@@ -63,7 +63,7 @@
 	u16	size;
 	u32	target_tid:12;
 	u32	init_tid:12;
-	u32	function:8;	
+	u32	function:8;
 	u32	initiator_context;
 	/* List follows */
 };
@@ -77,7 +77,7 @@
 
 	char dev_name[8];		/* linux /dev name if available */
 	i2o_lct_entry lct_data;/* Device LCT information */
-	u32 flags;		
+	u32 flags;
 	struct proc_dir_entry* proc_entry;	/* /proc dir */
 	struct adpt_device *owner;
 	struct _adpt_hba *controller;	/* Controlling IOP */
@@ -86,7 +86,7 @@
 /*
  *	Each I2O controller has one of these objects
  */
- 
+
 struct i2o_controller
 {
 	char name[16];
@@ -111,9 +111,9 @@
 	u32	iop_id:12;
 	u32	reserved2:20;
 	u16	seg_num:12;
-	u16 	i2o_version:4;
-	u8 	iop_state;
-	u8 	msg_type;
+	u16	i2o_version:4;
+	u8	iop_state;
+	u8	msg_type;
 	u16	frame_size;
 	u16	reserved3;
 	u32	last_changed;
@@ -124,14 +124,14 @@
 
 struct i2o_sys_tbl
 {
-	u8 	num_entries;
-	u8 	version;
-	u16 	reserved1;
+	u8	num_entries;
+	u8	version;
+	u16	reserved1;
 	u32	change_ind;
 	u32	reserved2;
 	u32	reserved3;
 	struct i2o_sys_tbl_entry iops[0];
-};	
+};
 
 /*
  *	I2O classes / subclasses
@@ -146,7 +146,7 @@
 /*  Class code names
  *  (from v1.5 Table 6-1 Class Code Assignments.)
  */
- 
+
 #define    I2O_CLASS_EXECUTIVE                         0x000
 #define    I2O_CLASS_DDM                               0x001
 #define    I2O_CLASS_RANDOM_BLOCK_STORAGE              0x010
@@ -166,7 +166,7 @@
 
 /*  Rest of 0x092 - 0x09f reserved for peer-to-peer classes
  */
- 
+
 #define    I2O_CLASS_MATCH_ANYCLASS                    0xffffffff
 
 /*  Subclasses
@@ -175,7 +175,7 @@
 #define    I2O_SUBCLASS_i960                           0x001
 #define    I2O_SUBCLASS_HDM                            0x020
 #define    I2O_SUBCLASS_ISM                            0x021
- 
+
 /* Operation functions */
 
 #define I2O_PARAMS_FIELD_GET	0x0001
@@ -219,7 +219,7 @@
 /*
  *	Messaging API values
  */
- 
+
 #define	I2O_CMD_ADAPTER_ASSIGN		0xB3
 #define	I2O_CMD_ADAPTER_READ		0xB2
 #define	I2O_CMD_ADAPTER_RELEASE		0xB5
@@ -284,16 +284,16 @@
 #define I2O_PRIVATE_MSG			0xFF
 
 /*
- *	Init Outbound Q status 
+ *	Init Outbound Q status
  */
- 
+
 #define I2O_CMD_OUTBOUND_INIT_IN_PROGRESS	0x01
 #define I2O_CMD_OUTBOUND_INIT_REJECTED		0x02
 #define I2O_CMD_OUTBOUND_INIT_FAILED		0x03
 #define I2O_CMD_OUTBOUND_INIT_COMPLETE		0x04
 
 /*
- *	I2O Get Status State values 
+ *	I2O Get Status State values
  */
 
 #define	ADAPTER_STATE_INITIALIZING		0x01
@@ -303,7 +303,7 @@
 #define	ADAPTER_STATE_OPERATIONAL		0x08
 #define	ADAPTER_STATE_FAILED			0x10
 #define	ADAPTER_STATE_FAULTED			0x11
-	
+
 /* I2O API function return values */
 
 #define I2O_RTN_NO_ERROR			0
@@ -321,9 +321,9 @@
 
 /* Reply message status defines for all messages */
 
-#define I2O_REPLY_STATUS_SUCCESS                    	0x00
-#define I2O_REPLY_STATUS_ABORT_DIRTY                	0x01
-#define I2O_REPLY_STATUS_ABORT_NO_DATA_TRANSFER     	0x02
+#define I2O_REPLY_STATUS_SUCCESS			0x00
+#define I2O_REPLY_STATUS_ABORT_DIRTY			0x01
+#define I2O_REPLY_STATUS_ABORT_NO_DATA_TRANSFER		0x02
 #define	I2O_REPLY_STATUS_ABORT_PARTIAL_TRANSFER		0x03
 #define	I2O_REPLY_STATUS_ERROR_DIRTY			0x04
 #define	I2O_REPLY_STATUS_ERROR_NO_DATA_TRANSFER		0x05
@@ -338,7 +338,7 @@
 
 #define I2O_PARAMS_STATUS_SUCCESS		0x00
 #define I2O_PARAMS_STATUS_BAD_KEY_ABORT		0x01
-#define I2O_PARAMS_STATUS_BAD_KEY_CONTINUE   	0x02
+#define I2O_PARAMS_STATUS_BAD_KEY_CONTINUE	0x02
 #define I2O_PARAMS_STATUS_BUFFER_FULL		0x03
 #define I2O_PARAMS_STATUS_BUFFER_TOO_SMALL	0x04
 #define I2O_PARAMS_STATUS_FIELD_UNREADABLE	0x05
@@ -390,7 +390,7 @@
 #define	I2O_CLAIM_MANAGEMENT					0x02000000
 #define	I2O_CLAIM_AUTHORIZED					0x03000000
 #define	I2O_CLAIM_SECONDARY					0x04000000
- 
+
 /* Message header defines for VersionOffset */
 #define I2OVER15	0x0001
 #define I2OVER20	0x0002
diff --git a/drivers/scsi/dpt/dpti_ioctl.h b/drivers/scsi/dpt/dpti_ioctl.h
index 82d2486..cc784e8 100644
--- a/drivers/scsi/dpt/dpti_ioctl.h
+++ b/drivers/scsi/dpt/dpti_ioctl.h
@@ -99,7 +99,7 @@
 	uCHAR    eataVersion;      /* EATA Version                    */
 	uLONG    cpLength;         /* EATA Command Packet Length      */
 	uLONG    spLength;         /* EATA Status Packet Length       */
-	uCHAR    drqNum;           /* DRQ Index (0,5,6,7)             */ 
+	uCHAR    drqNum;           /* DRQ Index (0,5,6,7)             */
 	uCHAR    flag1;            /* EATA Flags 1 (Byte 9)           */
 	uCHAR    flag2;            /* EATA Flags 2 (Byte 30)          */
 } CtrlInfo;
diff --git a/drivers/scsi/dpt/dptsig.h b/drivers/scsi/dpt/dptsig.h
index 4bf4477..94bc894 100644
--- a/drivers/scsi/dpt/dptsig.h
+++ b/drivers/scsi/dpt/dptsig.h
@@ -145,8 +145,8 @@
 #define FT_LOGGER       12      /* Event Logger */
 #define FT_INSTALL      13      /* An Install Program */
 #define FT_LIBRARY      14      /* Storage Manager Real-Mode Calls */
-#define FT_RESOURCE 	15 	/* Storage Manager Resource File */
-#define FT_MODEM_DB  	16  	/* Storage Manager Modem Database */
+#define FT_RESOURCE	15	/* Storage Manager Resource File */
+#define FT_MODEM_DB	16	/* Storage Manager Modem Database */
 
 /* Filetype flags - sigBYTE dsFiletypeFlags;    FLAG BITS */
 /* ------------------------------------------------------------------ */
diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c
index cd36e81..f7b9dbd 100644
--- a/drivers/scsi/dpt_i2o.c
+++ b/drivers/scsi/dpt_i2o.c
@@ -195,8 +195,6 @@
 			pci_dev_get(pDev);
 		}
 	}
-	if (pDev)
-		pci_dev_put(pDev);
 
 	/* In INIT state, Activate IOPs */
 	for (pHba = hba_chain; pHba; pHba = pHba->next) {
diff --git a/drivers/scsi/eata_generic.h b/drivers/scsi/eata_generic.h
index 635c148..5016af5c 100644
--- a/drivers/scsi/eata_generic.h
+++ b/drivers/scsi/eata_generic.h
@@ -18,13 +18,6 @@
  * Misc. definitions			     *
  *********************************************/
 
-#ifndef TRUE
-#define TRUE 1
-#endif
-#ifndef FALSE
-#define FALSE 0
-#endif
-
 #define R_LIMIT 0x20000
 
 #define MAXISA	   4
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c
index fbc1d5c..b10eefe 100644
--- a/drivers/scsi/ibmvscsi/ibmvscsi.c
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.c
@@ -85,7 +85,7 @@
 static int max_id = 64;
 static int max_channel = 3;
 static int init_timeout = 5;
-static int max_requests = 50;
+static int max_requests = IBMVSCSI_MAX_REQUESTS_DEFAULT;
 
 #define IBMVSCSI_VERSION "1.5.8"
 
@@ -538,7 +538,8 @@
 	int request_status;
 	int rc;
 
-	/* If we have exhausted our request limit, just fail this request.
+	/* If we have exhausted our request limit, just fail this request,
+	 * unless it is for a reset or abort.
 	 * Note that there are rare cases involving driver generated requests 
 	 * (such as task management requests) that the mid layer may think we
 	 * can handle more requests (can_queue) when we actually can't
@@ -551,9 +552,30 @@
 		 */
 		if (request_status < -1)
 			goto send_error;
-		/* Otherwise, if we have run out of requests */
-		else if (request_status < 0)
-			goto send_busy;
+		/* Otherwise, we may have run out of requests. */
+		/* Abort and reset calls should make it through.
+		 * Nothing except abort and reset should use the last two
+		 * slots unless we had two or less to begin with.
+		 */
+		else if (request_status < 2 &&
+		         evt_struct->iu.srp.cmd.opcode != SRP_TSK_MGMT) {
+			/* In the case that we have less than two requests
+			 * available, check the server limit as a combination
+			 * of the request limit and the number of requests
+			 * in-flight (the size of the send list).  If the
+			 * server limit is greater than 2, return busy so
+			 * that the last two are reserved for reset and abort.
+			 */
+			int server_limit = request_status;
+			struct srp_event_struct *tmp_evt;
+
+			list_for_each_entry(tmp_evt, &hostdata->sent, list) {
+				server_limit++;
+			}
+
+			if (server_limit > 2)
+				goto send_busy;
+		}
 	}
 
 	/* Copy the IU into the transfer area */
@@ -572,6 +594,7 @@
 
 		printk(KERN_ERR "ibmvscsi: send error %d\n",
 		       rc);
+		atomic_inc(&hostdata->request_limit);
 		goto send_error;
 	}
 
@@ -581,7 +604,8 @@
 	unmap_cmd_data(&evt_struct->iu.srp.cmd, evt_struct, hostdata->dev);
 
 	free_event_struct(&hostdata->pool, evt_struct);
- 	return SCSI_MLQUEUE_HOST_BUSY;
+	atomic_inc(&hostdata->request_limit);
+	return SCSI_MLQUEUE_HOST_BUSY;
 
  send_error:
 	unmap_cmd_data(&evt_struct->iu.srp.cmd, evt_struct, hostdata->dev);
@@ -831,23 +855,16 @@
 
 	printk(KERN_INFO "ibmvscsi: SRP_LOGIN succeeded\n");
 
-	if (evt_struct->xfer_iu->srp.login_rsp.req_lim_delta >
-	    (max_requests - 2))
-		evt_struct->xfer_iu->srp.login_rsp.req_lim_delta =
-		    max_requests - 2;
+	if (evt_struct->xfer_iu->srp.login_rsp.req_lim_delta < 0)
+		printk(KERN_ERR "ibmvscsi: Invalid request_limit.\n");
 
-	/* Now we know what the real request-limit is */
+	/* Now we know what the real request-limit is.
+	 * This value is set rather than added to request_limit because
+	 * request_limit could have been set to -1 by this client.
+	 */
 	atomic_set(&hostdata->request_limit,
 		   evt_struct->xfer_iu->srp.login_rsp.req_lim_delta);
 
-	hostdata->host->can_queue =
-	    evt_struct->xfer_iu->srp.login_rsp.req_lim_delta - 2;
-
-	if (hostdata->host->can_queue < 1) {
-		printk(KERN_ERR "ibmvscsi: Invalid request_limit_delta\n");
-		return;
-	}
-
 	/* If we had any pending I/Os, kick them */
 	scsi_unblock_requests(hostdata->host);
 
@@ -1337,6 +1354,27 @@
 	return rc;
 }
 
+/**
+ * ibmvscsi_slave_configure: Set the "allow_restart" flag for each disk.
+ * @sdev:	struct scsi_device device to configure
+ *
+ * Enable allow_restart for a device if it is a disk.  Adjust the
+ * queue_depth here also as is required by the documentation for
+ * struct scsi_host_template.
+ */
+static int ibmvscsi_slave_configure(struct scsi_device *sdev)
+{
+	struct Scsi_Host *shost = sdev->host;
+	unsigned long lock_flags = 0;
+
+	spin_lock_irqsave(shost->host_lock, lock_flags);
+	if (sdev->type == TYPE_DISK)
+		sdev->allow_restart = 1;
+	scsi_adjust_queue_depth(sdev, 0, shost->cmd_per_lun);
+	spin_unlock_irqrestore(shost->host_lock, lock_flags);
+	return 0;
+}
+
 /* ------------------------------------------------------------
  * sysfs attributes
  */
@@ -1482,8 +1520,9 @@
 	.queuecommand = ibmvscsi_queuecommand,
 	.eh_abort_handler = ibmvscsi_eh_abort_handler,
 	.eh_device_reset_handler = ibmvscsi_eh_device_reset_handler,
+	.slave_configure = ibmvscsi_slave_configure,
 	.cmd_per_lun = 16,
-	.can_queue = 1,		/* Updated after SRP_LOGIN */
+	.can_queue = IBMVSCSI_MAX_REQUESTS_DEFAULT,
 	.this_id = -1,
 	.sg_tablesize = SG_ALL,
 	.use_clustering = ENABLE_CLUSTERING,
@@ -1503,6 +1542,7 @@
 
 	vdev->dev.driver_data = NULL;
 
+	driver_template.can_queue = max_requests;
 	host = scsi_host_alloc(&driver_template, sizeof(*hostdata));
 	if (!host) {
 		printk(KERN_ERR "ibmvscsi: couldn't allocate host data\n");
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.h b/drivers/scsi/ibmvscsi/ibmvscsi.h
index 5c6d935..77cc1d4 100644
--- a/drivers/scsi/ibmvscsi/ibmvscsi.h
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.h
@@ -44,6 +44,8 @@
  */
 #define MAX_INDIRECT_BUFS 10
 
+#define IBMVSCSI_MAX_REQUESTS_DEFAULT 100
+
 /* ------------------------------------------------------------
  * Data Structures
  */
diff --git a/drivers/scsi/ibmvscsi/ibmvstgt.c b/drivers/scsi/ibmvscsi/ibmvstgt.c
index a39a478..6d223dd 100644
--- a/drivers/scsi/ibmvscsi/ibmvstgt.c
+++ b/drivers/scsi/ibmvscsi/ibmvstgt.c
@@ -35,7 +35,7 @@
 #include "ibmvscsi.h"
 
 #define	INITIAL_SRP_LIMIT	16
-#define	DEFAULT_MAX_SECTORS	512
+#define	DEFAULT_MAX_SECTORS	256
 
 #define	TGT_NAME	"ibmvstgt"
 
@@ -248,8 +248,8 @@
 						  md[i].va + mdone);
 
 			if (err != H_SUCCESS) {
-				eprintk("rdma error %d %d\n", dir, slen);
-				goto out;
+				eprintk("rdma error %d %d %ld\n", dir, slen, err);
+				return -EIO;
 			}
 
 			mlen -= slen;
@@ -265,45 +265,35 @@
 				if (sidx > nsg) {
 					eprintk("out of sg %p %d %d\n",
 						iue, sidx, nsg);
-					goto out;
+					return -EIO;
 				}
 			}
 		};
 
 		rest -= mlen;
 	}
-out:
-
 	return 0;
 }
 
-static int ibmvstgt_transfer_data(struct scsi_cmnd *sc,
-				  void (*done)(struct scsi_cmnd *))
-{
-	struct iu_entry	*iue = (struct iu_entry *) sc->SCp.ptr;
-	int err;
-
-	err = srp_transfer_data(sc, &vio_iu(iue)->srp.cmd, ibmvstgt_rdma, 1, 1);
-
-	done(sc);
-
-	return err;
-}
-
 static int ibmvstgt_cmd_done(struct scsi_cmnd *sc,
 			     void (*done)(struct scsi_cmnd *))
 {
 	unsigned long flags;
 	struct iu_entry *iue = (struct iu_entry *) sc->SCp.ptr;
 	struct srp_target *target = iue->target;
+	int err = 0;
 
-	dprintk("%p %p %x\n", iue, target, vio_iu(iue)->srp.cmd.cdb[0]);
+	dprintk("%p %p %x %u\n", iue, target, vio_iu(iue)->srp.cmd.cdb[0],
+		cmd->usg_sg);
+
+	if (sc->use_sg)
+		err = srp_transfer_data(sc, &vio_iu(iue)->srp.cmd, ibmvstgt_rdma, 1, 1);
 
 	spin_lock_irqsave(&target->lock, flags);
 	list_del(&iue->ilist);
 	spin_unlock_irqrestore(&target->lock, flags);
 
-	if (sc->result != SAM_STAT_GOOD) {
+	if (err|| sc->result != SAM_STAT_GOOD) {
 		eprintk("operation failed %p %d %x\n",
 			iue, sc->result, vio_iu(iue)->srp.cmd.cdb[0]);
 		send_rsp(iue, sc, HARDWARE_ERROR, 0x00);
@@ -503,7 +493,8 @@
 {
 	struct vio_port *vport = target_to_port(target);
 	struct iu_entry *iue;
-	long err, done;
+	long err;
+	int done = 1;
 
 	iue = srp_iu_get(target);
 	if (!iue) {
@@ -518,7 +509,6 @@
 
 	if (err != H_SUCCESS) {
 		eprintk("%ld transferring data error %p\n", err, iue);
-		done = 1;
 		goto out;
 	}
 
@@ -794,7 +784,6 @@
 	.use_clustering		= DISABLE_CLUSTERING,
 	.max_sectors		= DEFAULT_MAX_SECTORS,
 	.transfer_response	= ibmvstgt_cmd_done,
-	.transfer_data		= ibmvstgt_transfer_data,
 	.eh_abort_handler	= ibmvstgt_eh_abort_handler,
 	.tsk_mgmt_response	= ibmvstgt_tsk_mgmt_response,
 	.shost_attrs		= ibmvstgt_attrs,
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
index e9bd299..2c7b77e 100644
--- a/drivers/scsi/ipr.c
+++ b/drivers/scsi/ipr.c
@@ -89,10 +89,9 @@
 static unsigned int ipr_max_speed = 1;
 static int ipr_testmode = 0;
 static unsigned int ipr_fastfail = 0;
-static unsigned int ipr_transop_timeout = IPR_OPERATIONAL_TIMEOUT;
+static unsigned int ipr_transop_timeout = 0;
 static unsigned int ipr_enable_cache = 1;
 static unsigned int ipr_debug = 0;
-static int ipr_auto_create = 1;
 static DEFINE_SPINLOCK(ipr_driver_lock);
 
 /* This table describes the differences between DMA controller chips */
@@ -159,15 +158,13 @@
 MODULE_PARM_DESC(enable_cache, "Enable adapter's non-volatile write cache (default: 1)");
 module_param_named(debug, ipr_debug, int, 0);
 MODULE_PARM_DESC(debug, "Enable device driver debugging logging. Set to 1 to enable. (default: 0)");
-module_param_named(auto_create, ipr_auto_create, int, 0);
-MODULE_PARM_DESC(auto_create, "Auto-create single device RAID 0 arrays when initialized (default: 1)");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(IPR_DRIVER_VERSION);
 
 /*  A constant array of IOASCs/URCs/Error Messages */
 static const
 struct ipr_error_table_t ipr_error_table[] = {
-	{0x00000000, 1, 1,
+	{0x00000000, 1, IPR_DEFAULT_LOG_LEVEL,
 	"8155: An unknown error was received"},
 	{0x00330000, 0, 0,
 	"Soft underlength error"},
@@ -175,37 +172,37 @@
 	"Command to be cancelled not found"},
 	{0x00808000, 0, 0,
 	"Qualified success"},
-	{0x01080000, 1, 1,
+	{0x01080000, 1, IPR_DEFAULT_LOG_LEVEL,
 	"FFFE: Soft device bus error recovered by the IOA"},
-	{0x01088100, 0, 1,
+	{0x01088100, 0, IPR_DEFAULT_LOG_LEVEL,
 	"4101: Soft device bus fabric error"},
-	{0x01170600, 0, 1,
+	{0x01170600, 0, IPR_DEFAULT_LOG_LEVEL,
 	"FFF9: Device sector reassign successful"},
-	{0x01170900, 0, 1,
+	{0x01170900, 0, IPR_DEFAULT_LOG_LEVEL,
 	"FFF7: Media error recovered by device rewrite procedures"},
-	{0x01180200, 0, 1,
+	{0x01180200, 0, IPR_DEFAULT_LOG_LEVEL,
 	"7001: IOA sector reassignment successful"},
-	{0x01180500, 0, 1,
+	{0x01180500, 0, IPR_DEFAULT_LOG_LEVEL,
 	"FFF9: Soft media error. Sector reassignment recommended"},
-	{0x01180600, 0, 1,
+	{0x01180600, 0, IPR_DEFAULT_LOG_LEVEL,
 	"FFF7: Media error recovered by IOA rewrite procedures"},
-	{0x01418000, 0, 1,
+	{0x01418000, 0, IPR_DEFAULT_LOG_LEVEL,
 	"FF3D: Soft PCI bus error recovered by the IOA"},
-	{0x01440000, 1, 1,
+	{0x01440000, 1, IPR_DEFAULT_LOG_LEVEL,
 	"FFF6: Device hardware error recovered by the IOA"},
-	{0x01448100, 0, 1,
+	{0x01448100, 0, IPR_DEFAULT_LOG_LEVEL,
 	"FFF6: Device hardware error recovered by the device"},
-	{0x01448200, 1, 1,
+	{0x01448200, 1, IPR_DEFAULT_LOG_LEVEL,
 	"FF3D: Soft IOA error recovered by the IOA"},
-	{0x01448300, 0, 1,
+	{0x01448300, 0, IPR_DEFAULT_LOG_LEVEL,
 	"FFFA: Undefined device response recovered by the IOA"},
-	{0x014A0000, 1, 1,
+	{0x014A0000, 1, IPR_DEFAULT_LOG_LEVEL,
 	"FFF6: Device bus error, message or command phase"},
-	{0x014A8000, 0, 1,
+	{0x014A8000, 0, IPR_DEFAULT_LOG_LEVEL,
 	"FFFE: Task Management Function failed"},
-	{0x015D0000, 0, 1,
+	{0x015D0000, 0, IPR_DEFAULT_LOG_LEVEL,
 	"FFF6: Failure prediction threshold exceeded"},
-	{0x015D9200, 0, 1,
+	{0x015D9200, 0, IPR_DEFAULT_LOG_LEVEL,
 	"8009: Impending cache battery pack failure"},
 	{0x02040400, 0, 0,
 	"34FF: Disk device format in progress"},
@@ -215,85 +212,85 @@
 	"No ready, IOA shutdown"},
 	{0x025A0000, 0, 0,
 	"Not ready, IOA has been shutdown"},
-	{0x02670100, 0, 1,
+	{0x02670100, 0, IPR_DEFAULT_LOG_LEVEL,
 	"3020: Storage subsystem configuration error"},
 	{0x03110B00, 0, 0,
 	"FFF5: Medium error, data unreadable, recommend reassign"},
 	{0x03110C00, 0, 0,
 	"7000: Medium error, data unreadable, do not reassign"},
-	{0x03310000, 0, 1,
+	{0x03310000, 0, IPR_DEFAULT_LOG_LEVEL,
 	"FFF3: Disk media format bad"},
-	{0x04050000, 0, 1,
+	{0x04050000, 0, IPR_DEFAULT_LOG_LEVEL,
 	"3002: Addressed device failed to respond to selection"},
-	{0x04080000, 1, 1,
+	{0x04080000, 1, IPR_DEFAULT_LOG_LEVEL,
 	"3100: Device bus error"},
-	{0x04080100, 0, 1,
+	{0x04080100, 0, IPR_DEFAULT_LOG_LEVEL,
 	"3109: IOA timed out a device command"},
 	{0x04088000, 0, 0,
 	"3120: SCSI bus is not operational"},
-	{0x04088100, 0, 1,
+	{0x04088100, 0, IPR_DEFAULT_LOG_LEVEL,
 	"4100: Hard device bus fabric error"},
-	{0x04118000, 0, 1,
+	{0x04118000, 0, IPR_DEFAULT_LOG_LEVEL,
 	"9000: IOA reserved area data check"},
-	{0x04118100, 0, 1,
+	{0x04118100, 0, IPR_DEFAULT_LOG_LEVEL,
 	"9001: IOA reserved area invalid data pattern"},
-	{0x04118200, 0, 1,
+	{0x04118200, 0, IPR_DEFAULT_LOG_LEVEL,
 	"9002: IOA reserved area LRC error"},
-	{0x04320000, 0, 1,
+	{0x04320000, 0, IPR_DEFAULT_LOG_LEVEL,
 	"102E: Out of alternate sectors for disk storage"},
-	{0x04330000, 1, 1,
+	{0x04330000, 1, IPR_DEFAULT_LOG_LEVEL,
 	"FFF4: Data transfer underlength error"},
-	{0x04338000, 1, 1,
+	{0x04338000, 1, IPR_DEFAULT_LOG_LEVEL,
 	"FFF4: Data transfer overlength error"},
-	{0x043E0100, 0, 1,
+	{0x043E0100, 0, IPR_DEFAULT_LOG_LEVEL,
 	"3400: Logical unit failure"},
-	{0x04408500, 0, 1,
+	{0x04408500, 0, IPR_DEFAULT_LOG_LEVEL,
 	"FFF4: Device microcode is corrupt"},
-	{0x04418000, 1, 1,
+	{0x04418000, 1, IPR_DEFAULT_LOG_LEVEL,
 	"8150: PCI bus error"},
 	{0x04430000, 1, 0,
 	"Unsupported device bus message received"},
-	{0x04440000, 1, 1,
+	{0x04440000, 1, IPR_DEFAULT_LOG_LEVEL,
 	"FFF4: Disk device problem"},
-	{0x04448200, 1, 1,
+	{0x04448200, 1, IPR_DEFAULT_LOG_LEVEL,
 	"8150: Permanent IOA failure"},
-	{0x04448300, 0, 1,
+	{0x04448300, 0, IPR_DEFAULT_LOG_LEVEL,
 	"3010: Disk device returned wrong response to IOA"},
-	{0x04448400, 0, 1,
+	{0x04448400, 0, IPR_DEFAULT_LOG_LEVEL,
 	"8151: IOA microcode error"},
 	{0x04448500, 0, 0,
 	"Device bus status error"},
-	{0x04448600, 0, 1,
+	{0x04448600, 0, IPR_DEFAULT_LOG_LEVEL,
 	"8157: IOA error requiring IOA reset to recover"},
 	{0x04448700, 0, 0,
 	"ATA device status error"},
 	{0x04490000, 0, 0,
 	"Message reject received from the device"},
-	{0x04449200, 0, 1,
+	{0x04449200, 0, IPR_DEFAULT_LOG_LEVEL,
 	"8008: A permanent cache battery pack failure occurred"},
-	{0x0444A000, 0, 1,
+	{0x0444A000, 0, IPR_DEFAULT_LOG_LEVEL,
 	"9090: Disk unit has been modified after the last known status"},
-	{0x0444A200, 0, 1,
+	{0x0444A200, 0, IPR_DEFAULT_LOG_LEVEL,
 	"9081: IOA detected device error"},
-	{0x0444A300, 0, 1,
+	{0x0444A300, 0, IPR_DEFAULT_LOG_LEVEL,
 	"9082: IOA detected device error"},
-	{0x044A0000, 1, 1,
+	{0x044A0000, 1, IPR_DEFAULT_LOG_LEVEL,
 	"3110: Device bus error, message or command phase"},
-	{0x044A8000, 1, 1,
+	{0x044A8000, 1, IPR_DEFAULT_LOG_LEVEL,
 	"3110: SAS Command / Task Management Function failed"},
-	{0x04670400, 0, 1,
+	{0x04670400, 0, IPR_DEFAULT_LOG_LEVEL,
 	"9091: Incorrect hardware configuration change has been detected"},
-	{0x04678000, 0, 1,
+	{0x04678000, 0, IPR_DEFAULT_LOG_LEVEL,
 	"9073: Invalid multi-adapter configuration"},
-	{0x04678100, 0, 1,
+	{0x04678100, 0, IPR_DEFAULT_LOG_LEVEL,
 	"4010: Incorrect connection between cascaded expanders"},
-	{0x04678200, 0, 1,
+	{0x04678200, 0, IPR_DEFAULT_LOG_LEVEL,
 	"4020: Connections exceed IOA design limits"},
-	{0x04678300, 0, 1,
+	{0x04678300, 0, IPR_DEFAULT_LOG_LEVEL,
 	"4030: Incorrect multipath connection"},
-	{0x04679000, 0, 1,
+	{0x04679000, 0, IPR_DEFAULT_LOG_LEVEL,
 	"4110: Unsupported enclosure function"},
-	{0x046E0000, 0, 1,
+	{0x046E0000, 0, IPR_DEFAULT_LOG_LEVEL,
 	"FFF4: Command to logical unit failed"},
 	{0x05240000, 1, 0,
 	"Illegal request, invalid request type or request packet"},
@@ -313,101 +310,103 @@
 	"Illegal request, command sequence error"},
 	{0x052C8000, 1, 0,
 	"Illegal request, dual adapter support not enabled"},
-	{0x06040500, 0, 1,
+	{0x06040500, 0, IPR_DEFAULT_LOG_LEVEL,
 	"9031: Array protection temporarily suspended, protection resuming"},
-	{0x06040600, 0, 1,
+	{0x06040600, 0, IPR_DEFAULT_LOG_LEVEL,
 	"9040: Array protection temporarily suspended, protection resuming"},
-	{0x06288000, 0, 1,
+	{0x06288000, 0, IPR_DEFAULT_LOG_LEVEL,
 	"3140: Device bus not ready to ready transition"},
-	{0x06290000, 0, 1,
+	{0x06290000, 0, IPR_DEFAULT_LOG_LEVEL,
 	"FFFB: SCSI bus was reset"},
 	{0x06290500, 0, 0,
 	"FFFE: SCSI bus transition to single ended"},
 	{0x06290600, 0, 0,
 	"FFFE: SCSI bus transition to LVD"},
-	{0x06298000, 0, 1,
+	{0x06298000, 0, IPR_DEFAULT_LOG_LEVEL,
 	"FFFB: SCSI bus was reset by another initiator"},
-	{0x063F0300, 0, 1,
+	{0x063F0300, 0, IPR_DEFAULT_LOG_LEVEL,
 	"3029: A device replacement has occurred"},
-	{0x064C8000, 0, 1,
+	{0x064C8000, 0, IPR_DEFAULT_LOG_LEVEL,
 	"9051: IOA cache data exists for a missing or failed device"},
-	{0x064C8100, 0, 1,
+	{0x064C8100, 0, IPR_DEFAULT_LOG_LEVEL,
 	"9055: Auxiliary cache IOA contains cache data needed by the primary IOA"},
-	{0x06670100, 0, 1,
+	{0x06670100, 0, IPR_DEFAULT_LOG_LEVEL,
 	"9025: Disk unit is not supported at its physical location"},
-	{0x06670600, 0, 1,
+	{0x06670600, 0, IPR_DEFAULT_LOG_LEVEL,
 	"3020: IOA detected a SCSI bus configuration error"},
-	{0x06678000, 0, 1,
+	{0x06678000, 0, IPR_DEFAULT_LOG_LEVEL,
 	"3150: SCSI bus configuration error"},
-	{0x06678100, 0, 1,
+	{0x06678100, 0, IPR_DEFAULT_LOG_LEVEL,
 	"9074: Asymmetric advanced function disk configuration"},
-	{0x06678300, 0, 1,
+	{0x06678300, 0, IPR_DEFAULT_LOG_LEVEL,
 	"4040: Incomplete multipath connection between IOA and enclosure"},
-	{0x06678400, 0, 1,
+	{0x06678400, 0, IPR_DEFAULT_LOG_LEVEL,
 	"4041: Incomplete multipath connection between enclosure and device"},
-	{0x06678500, 0, 1,
+	{0x06678500, 0, IPR_DEFAULT_LOG_LEVEL,
 	"9075: Incomplete multipath connection between IOA and remote IOA"},
-	{0x06678600, 0, 1,
+	{0x06678600, 0, IPR_DEFAULT_LOG_LEVEL,
 	"9076: Configuration error, missing remote IOA"},
-	{0x06679100, 0, 1,
+	{0x06679100, 0, IPR_DEFAULT_LOG_LEVEL,
 	"4050: Enclosure does not support a required multipath function"},
-	{0x06690200, 0, 1,
+	{0x06690200, 0, IPR_DEFAULT_LOG_LEVEL,
 	"9041: Array protection temporarily suspended"},
-	{0x06698200, 0, 1,
+	{0x06698200, 0, IPR_DEFAULT_LOG_LEVEL,
 	"9042: Corrupt array parity detected on specified device"},
-	{0x066B0200, 0, 1,
+	{0x066B0200, 0, IPR_DEFAULT_LOG_LEVEL,
 	"9030: Array no longer protected due to missing or failed disk unit"},
-	{0x066B8000, 0, 1,
+	{0x066B8000, 0, IPR_DEFAULT_LOG_LEVEL,
 	"9071: Link operational transition"},
-	{0x066B8100, 0, 1,
+	{0x066B8100, 0, IPR_DEFAULT_LOG_LEVEL,
 	"9072: Link not operational transition"},
-	{0x066B8200, 0, 1,
+	{0x066B8200, 0, IPR_DEFAULT_LOG_LEVEL,
 	"9032: Array exposed but still protected"},
-	{0x066B9100, 0, 1,
+	{0x066B8300, 0, IPR_DEFAULT_LOG_LEVEL + 1,
+	"70DD: Device forced failed by disrupt device command"},
+	{0x066B9100, 0, IPR_DEFAULT_LOG_LEVEL,
 	"4061: Multipath redundancy level got better"},
-	{0x066B9200, 0, 1,
+	{0x066B9200, 0, IPR_DEFAULT_LOG_LEVEL,
 	"4060: Multipath redundancy level got worse"},
 	{0x07270000, 0, 0,
 	"Failure due to other device"},
-	{0x07278000, 0, 1,
+	{0x07278000, 0, IPR_DEFAULT_LOG_LEVEL,
 	"9008: IOA does not support functions expected by devices"},
-	{0x07278100, 0, 1,
+	{0x07278100, 0, IPR_DEFAULT_LOG_LEVEL,
 	"9010: Cache data associated with attached devices cannot be found"},
-	{0x07278200, 0, 1,
+	{0x07278200, 0, IPR_DEFAULT_LOG_LEVEL,
 	"9011: Cache data belongs to devices other than those attached"},
-	{0x07278400, 0, 1,
+	{0x07278400, 0, IPR_DEFAULT_LOG_LEVEL,
 	"9020: Array missing 2 or more devices with only 1 device present"},
-	{0x07278500, 0, 1,
+	{0x07278500, 0, IPR_DEFAULT_LOG_LEVEL,
 	"9021: Array missing 2 or more devices with 2 or more devices present"},
-	{0x07278600, 0, 1,
+	{0x07278600, 0, IPR_DEFAULT_LOG_LEVEL,
 	"9022: Exposed array is missing a required device"},
-	{0x07278700, 0, 1,
+	{0x07278700, 0, IPR_DEFAULT_LOG_LEVEL,
 	"9023: Array member(s) not at required physical locations"},
-	{0x07278800, 0, 1,
+	{0x07278800, 0, IPR_DEFAULT_LOG_LEVEL,
 	"9024: Array not functional due to present hardware configuration"},
-	{0x07278900, 0, 1,
+	{0x07278900, 0, IPR_DEFAULT_LOG_LEVEL,
 	"9026: Array not functional due to present hardware configuration"},
-	{0x07278A00, 0, 1,
+	{0x07278A00, 0, IPR_DEFAULT_LOG_LEVEL,
 	"9027: Array is missing a device and parity is out of sync"},
-	{0x07278B00, 0, 1,
+	{0x07278B00, 0, IPR_DEFAULT_LOG_LEVEL,
 	"9028: Maximum number of arrays already exist"},
-	{0x07278C00, 0, 1,
+	{0x07278C00, 0, IPR_DEFAULT_LOG_LEVEL,
 	"9050: Required cache data cannot be located for a disk unit"},
-	{0x07278D00, 0, 1,
+	{0x07278D00, 0, IPR_DEFAULT_LOG_LEVEL,
 	"9052: Cache data exists for a device that has been modified"},
-	{0x07278F00, 0, 1,
+	{0x07278F00, 0, IPR_DEFAULT_LOG_LEVEL,
 	"9054: IOA resources not available due to previous problems"},
-	{0x07279100, 0, 1,
+	{0x07279100, 0, IPR_DEFAULT_LOG_LEVEL,
 	"9092: Disk unit requires initialization before use"},
-	{0x07279200, 0, 1,
+	{0x07279200, 0, IPR_DEFAULT_LOG_LEVEL,
 	"9029: Incorrect hardware configuration change has been detected"},
-	{0x07279600, 0, 1,
+	{0x07279600, 0, IPR_DEFAULT_LOG_LEVEL,
 	"9060: One or more disk pairs are missing from an array"},
-	{0x07279700, 0, 1,
+	{0x07279700, 0, IPR_DEFAULT_LOG_LEVEL,
 	"9061: One or more disks are missing from an array"},
-	{0x07279800, 0, 1,
+	{0x07279800, 0, IPR_DEFAULT_LOG_LEVEL,
 	"9062: One or more disks are missing from an array"},
-	{0x07279900, 0, 1,
+	{0x07279900, 0, IPR_DEFAULT_LOG_LEVEL,
 	"9063: Maximum number of functional arrays has been exceeded"},
 	{0x0B260000, 0, 0,
 	"Aborted command, invalid descriptor"},
@@ -481,12 +480,16 @@
 {
 	struct ipr_ioarcb *ioarcb = &ipr_cmd->ioarcb;
 	struct ipr_ioasa *ioasa = &ipr_cmd->ioasa;
+	dma_addr_t dma_addr = be32_to_cpu(ioarcb->ioarcb_host_pci_addr);
 
 	memset(&ioarcb->cmd_pkt, 0, sizeof(struct ipr_cmd_pkt));
 	ioarcb->write_data_transfer_length = 0;
 	ioarcb->read_data_transfer_length = 0;
 	ioarcb->write_ioadl_len = 0;
 	ioarcb->read_ioadl_len = 0;
+	ioarcb->write_ioadl_addr =
+		cpu_to_be32(dma_addr + offsetof(struct ipr_cmnd, ioadl));
+	ioarcb->read_ioadl_addr = ioarcb->write_ioadl_addr;
 	ioasa->ioasc = 0;
 	ioasa->residual_data_len = 0;
 	ioasa->u.gata.status = 0;
@@ -1610,7 +1613,7 @@
 	/* Set indication we have logged an error */
 	ioa_cfg->errors_logged++;
 
-	if (ioa_cfg->log_level < IPR_DEFAULT_LOG_LEVEL)
+	if (ioa_cfg->log_level < ipr_error_table[error_index].log_hcam)
 		return;
 	if (be32_to_cpu(hostrcb->hcam.length) > sizeof(hostrcb->hcam.u.raw))
 		hostrcb->hcam.length = cpu_to_be32(sizeof(hostrcb->hcam.u.raw));
@@ -3850,6 +3853,8 @@
 		if (ipr_cmd->ioarcb.res_handle == res->cfgte.res_handle) {
 			if (ipr_cmd->scsi_cmd)
 				ipr_cmd->done = ipr_scsi_eh_done;
+			if (ipr_cmd->qc)
+				ipr_cmd->done = ipr_sata_eh_done;
 			if (ipr_cmd->qc && !(ipr_cmd->qc->flags & ATA_QCFLAG_FAILED)) {
 				ipr_cmd->qc->err_mask |= AC_ERR_TIMEOUT;
 				ipr_cmd->qc->flags |= ATA_QCFLAG_FAILED;
@@ -4230,6 +4235,14 @@
 
 		sglist = scsi_cmd->request_buffer;
 
+		if (ipr_cmd->dma_use_sg <= ARRAY_SIZE(ioarcb->add_data.u.ioadl)) {
+			ioadl = ioarcb->add_data.u.ioadl;
+			ioarcb->write_ioadl_addr =
+				cpu_to_be32(be32_to_cpu(ioarcb->ioarcb_host_pci_addr) +
+					    offsetof(struct ipr_ioarcb, add_data));
+			ioarcb->read_ioadl_addr = ioarcb->write_ioadl_addr;
+		}
+
 		for (i = 0; i < ipr_cmd->dma_use_sg; i++) {
 			ioadl[i].flags_and_data_len =
 				cpu_to_be32(ioadl_flags | sg_dma_len(&sglist[i]));
@@ -4260,6 +4273,11 @@
 						     scsi_cmd->sc_data_direction);
 
 		if (likely(!pci_dma_mapping_error(ipr_cmd->dma_handle))) {
+			ioadl = ioarcb->add_data.u.ioadl;
+			ioarcb->write_ioadl_addr =
+				cpu_to_be32(be32_to_cpu(ioarcb->ioarcb_host_pci_addr) +
+					    offsetof(struct ipr_ioarcb, add_data));
+			ioarcb->read_ioadl_addr = ioarcb->write_ioadl_addr;
 			ipr_cmd->dma_use_sg = 1;
 			ioadl[0].flags_and_data_len =
 				cpu_to_be32(ioadl_flags | length | IPR_IOADL_FLAGS_LAST);
@@ -4346,11 +4364,9 @@
  **/
 static void ipr_reinit_ipr_cmnd_for_erp(struct ipr_cmnd *ipr_cmd)
 {
-	struct ipr_ioarcb *ioarcb;
-	struct ipr_ioasa *ioasa;
-
-	ioarcb = &ipr_cmd->ioarcb;
-	ioasa = &ipr_cmd->ioasa;
+	struct ipr_ioarcb *ioarcb = &ipr_cmd->ioarcb;
+	struct ipr_ioasa *ioasa = &ipr_cmd->ioasa;
+	dma_addr_t dma_addr = be32_to_cpu(ioarcb->ioarcb_host_pci_addr);
 
 	memset(&ioarcb->cmd_pkt, 0, sizeof(struct ipr_cmd_pkt));
 	ioarcb->write_data_transfer_length = 0;
@@ -4359,6 +4375,9 @@
 	ioarcb->read_ioadl_len = 0;
 	ioasa->ioasc = 0;
 	ioasa->residual_data_len = 0;
+	ioarcb->write_ioadl_addr =
+		cpu_to_be32(dma_addr + offsetof(struct ipr_cmnd, ioadl));
+	ioarcb->read_ioadl_addr = ioarcb->write_ioadl_addr;
 }
 
 /**
@@ -4457,12 +4476,13 @@
 {
 	int i;
 	u16 data_len;
-	u32 ioasc;
+	u32 ioasc, fd_ioasc;
 	struct ipr_ioasa *ioasa = &ipr_cmd->ioasa;
 	__be32 *ioasa_data = (__be32 *)ioasa;
 	int error_index;
 
 	ioasc = be32_to_cpu(ioasa->ioasc) & IPR_IOASC_IOASC_MASK;
+	fd_ioasc = be32_to_cpu(ioasa->fd_ioasc) & IPR_IOASC_IOASC_MASK;
 
 	if (0 == ioasc)
 		return;
@@ -4470,13 +4490,19 @@
 	if (ioa_cfg->log_level < IPR_DEFAULT_LOG_LEVEL)
 		return;
 
-	error_index = ipr_get_error(ioasc);
+	if (ioasc == IPR_IOASC_BUS_WAS_RESET && fd_ioasc)
+		error_index = ipr_get_error(fd_ioasc);
+	else
+		error_index = ipr_get_error(ioasc);
 
 	if (ioa_cfg->log_level < IPR_MAX_LOG_LEVEL) {
 		/* Don't log an error if the IOA already logged one */
 		if (ioasa->ilid != 0)
 			return;
 
+		if (!ipr_is_gscsi(res))
+			return;
+
 		if (ipr_error_table[error_index].log_ioasa == 0)
 			return;
 	}
@@ -4636,11 +4662,11 @@
 		return;
 	}
 
-	if (ipr_is_gscsi(res))
-		ipr_dump_ioasa(ioa_cfg, ipr_cmd, res);
-	else
+	if (!ipr_is_gscsi(res))
 		ipr_gen_sense(ipr_cmd);
 
+	ipr_dump_ioasa(ioa_cfg, ipr_cmd, res);
+
 	switch (ioasc & IPR_IOASC_IOASC_MASK) {
 	case IPR_IOASC_ABORTED_CMD_TERM_BY_HOST:
 		if (ipr_is_naca_model(res))
@@ -5121,7 +5147,7 @@
 	struct ipr_ioarcb_ata_regs *regs;
 
 	if (unlikely(!ioa_cfg->allow_cmds || ioa_cfg->ioa_is_dead))
-		return -EIO;
+		return AC_ERR_SYSTEM;
 
 	ipr_cmd = ipr_get_free_ipr_cmnd(ioa_cfg);
 	ioarcb = &ipr_cmd->ioarcb;
@@ -5166,7 +5192,7 @@
 
 	default:
 		WARN_ON(1);
-		return -1;
+		return AC_ERR_INVALID;
 	}
 
 	mb();
@@ -6188,7 +6214,7 @@
 	dev_info(&ioa_cfg->pdev->dev, "Initializing IOA.\n");
 
 	ipr_cmd->timer.data = (unsigned long) ipr_cmd;
-	ipr_cmd->timer.expires = jiffies + (ipr_transop_timeout * HZ);
+	ipr_cmd->timer.expires = jiffies + (ioa_cfg->transop_timeout * HZ);
 	ipr_cmd->timer.function = (void (*)(unsigned long))ipr_oper_timeout;
 	ipr_cmd->done = ipr_reset_ioa_job;
 	add_timer(&ipr_cmd->timer);
@@ -6385,6 +6411,7 @@
 	rc = pci_write_config_byte(ioa_cfg->pdev, PCI_BIST, PCI_BIST_START);
 
 	if (rc != PCIBIOS_SUCCESSFUL) {
+		pci_unblock_user_cfg_access(ipr_cmd->ioa_cfg->pdev);
 		ipr_cmd->ioasa.ioasc = cpu_to_be32(IPR_IOASC_PCI_ACCESS_ERROR);
 		rc = IPR_RC_JOB_CONTINUE;
 	} else {
@@ -7117,8 +7144,6 @@
 	ioa_cfg->pdev = pdev;
 	ioa_cfg->log_level = ipr_log_level;
 	ioa_cfg->doorbell = IPR_DOORBELL;
-	if (!ipr_auto_create)
-		ioa_cfg->doorbell |= IPR_RUNTIME_RESET;
 	sprintf(ioa_cfg->eye_catcher, IPR_EYECATCHER);
 	sprintf(ioa_cfg->trace_start, IPR_TRACE_START_LABEL);
 	sprintf(ioa_cfg->ipr_free_label, IPR_FREEQ_LABEL);
@@ -7233,6 +7258,13 @@
 		goto out_scsi_host_put;
 	}
 
+	if (ipr_transop_timeout)
+		ioa_cfg->transop_timeout = ipr_transop_timeout;
+	else if (dev_id->driver_data & IPR_USE_LONG_TRANSOP_TIMEOUT)
+		ioa_cfg->transop_timeout = IPR_LONG_OPERATIONAL_TIMEOUT;
+	else
+		ioa_cfg->transop_timeout = IPR_OPERATIONAL_TIMEOUT;
+
 	ipr_regs_pci = pci_resource_start(pdev, 0);
 
 	rc = pci_request_regions(pdev, IPR_NAME);
@@ -7540,29 +7572,45 @@
 	{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CITRINE,
 		PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_571A, 0, 0, 0 },
 	{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CITRINE,
-		PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575B, 0, 0, 0 },
+		PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575B, 0, 0,
+		IPR_USE_LONG_TRANSOP_TIMEOUT },
 	{ PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_OBSIDIAN,
 	      PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572A, 0, 0, 0 },
 	{ PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_OBSIDIAN,
 	      PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572B, 0, 0, 0 },
 	{ PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_OBSIDIAN,
-	      PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575C, 0, 0, 0 },
+	      PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575C, 0, 0,
+	      IPR_USE_LONG_TRANSOP_TIMEOUT },
 	{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN,
 	      PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572A, 0, 0, 0 },
 	{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN,
 	      PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572B, 0, 0, 0 },
 	{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN,
-	      PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575C, 0, 0, 0 },
+	      PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575C, 0, 0,
+	      IPR_USE_LONG_TRANSOP_TIMEOUT },
 	{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN_E,
-	      PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57B7, 0, 0, 0 },
+	      PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_574E, 0, 0, 0 },
+	{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN_E,
+	      PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575D, 0, 0,
+	      IPR_USE_LONG_TRANSOP_TIMEOUT },
+	{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN_E,
+	      PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57B3, 0, 0, 0 },
+	{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN_E,
+	      PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57B7, 0, 0,
+	      IPR_USE_LONG_TRANSOP_TIMEOUT },
 	{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_SNIPE,
 		PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_2780, 0, 0, 0 },
 	{ PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_SCAMP,
 		PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_571E, 0, 0, 0 },
 	{ PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_SCAMP,
-		PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_571F, 0, 0, 0 },
+		PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_571F, 0, 0,
+		IPR_USE_LONG_TRANSOP_TIMEOUT },
 	{ PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_SCAMP,
-		PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572F, 0, 0, 0 },
+		PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572F, 0, 0,
+		IPR_USE_LONG_TRANSOP_TIMEOUT },
+	{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_SCAMP_E,
+		PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_574D, 0, 0,
+		IPR_USE_LONG_TRANSOP_TIMEOUT },
 	{ }
 };
 MODULE_DEVICE_TABLE(pci, ipr_pci_table);
diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h
index 88f285d..bc53d7c 100644
--- a/drivers/scsi/ipr.h
+++ b/drivers/scsi/ipr.h
@@ -37,8 +37,8 @@
 /*
  * Literals
  */
-#define IPR_DRIVER_VERSION "2.3.1"
-#define IPR_DRIVER_DATE "(January 23, 2007)"
+#define IPR_DRIVER_VERSION "2.3.2"
+#define IPR_DRIVER_DATE "(March 23, 2007)"
 
 /*
  * IPR_MAX_CMD_PER_LUN: This defines the maximum number of outstanding
@@ -55,6 +55,7 @@
 #define IPR_NUM_BASE_CMD_BLKS				100
 
 #define PCI_DEVICE_ID_IBM_OBSIDIAN_E	0x0339
+#define PCI_DEVICE_ID_IBM_SCAMP_E		0x034A
 
 #define IPR_SUBS_DEV_ID_2780	0x0264
 #define IPR_SUBS_DEV_ID_5702	0x0266
@@ -69,8 +70,12 @@
 #define IPR_SUBS_DEV_ID_572A	0x02C1
 #define IPR_SUBS_DEV_ID_572B	0x02C2
 #define IPR_SUBS_DEV_ID_572F	0x02C3
+#define IPR_SUBS_DEV_ID_574D	0x030B
+#define IPR_SUBS_DEV_ID_574E	0x030A
 #define IPR_SUBS_DEV_ID_575B	0x030D
 #define IPR_SUBS_DEV_ID_575C	0x0338
+#define IPR_SUBS_DEV_ID_575D	0x033E
+#define IPR_SUBS_DEV_ID_57B3	0x033A
 #define IPR_SUBS_DEV_ID_57B7	0x0360
 #define IPR_SUBS_DEV_ID_57B8	0x02C2
 
@@ -104,6 +109,9 @@
 #define IPR_IOASC_IOA_WAS_RESET			0x10000001
 #define IPR_IOASC_PCI_ACCESS_ERROR			0x10000002
 
+/* Driver data flags */
+#define IPR_USE_LONG_TRANSOP_TIMEOUT		0x00000001
+
 #define IPR_DEFAULT_MAX_ERROR_DUMP			984
 #define IPR_NUM_LOG_HCAMS				2
 #define IPR_NUM_CFG_CHG_HCAMS				2
@@ -179,6 +187,7 @@
 #define IPR_SET_SUP_DEVICE_TIMEOUT		(2 * 60 * HZ)
 #define IPR_REQUEST_SENSE_TIMEOUT		(10 * HZ)
 #define IPR_OPERATIONAL_TIMEOUT		(5 * 60)
+#define IPR_LONG_OPERATIONAL_TIMEOUT	(12 * 60)
 #define IPR_WAIT_FOR_RESET_TIMEOUT		(2 * HZ)
 #define IPR_CHECK_FOR_RESET_TIMEOUT		(HZ / 10)
 #define IPR_WAIT_FOR_BIST_TIMEOUT		(2 * HZ)
@@ -413,9 +422,25 @@
 	u8 ctl;
 }__attribute__ ((packed, aligned(4)));
 
+struct ipr_ioadl_desc {
+	__be32 flags_and_data_len;
+#define IPR_IOADL_FLAGS_MASK		0xff000000
+#define IPR_IOADL_GET_FLAGS(x) (be32_to_cpu(x) & IPR_IOADL_FLAGS_MASK)
+#define IPR_IOADL_DATA_LEN_MASK		0x00ffffff
+#define IPR_IOADL_GET_DATA_LEN(x) (be32_to_cpu(x) & IPR_IOADL_DATA_LEN_MASK)
+#define IPR_IOADL_FLAGS_READ		0x48000000
+#define IPR_IOADL_FLAGS_READ_LAST	0x49000000
+#define IPR_IOADL_FLAGS_WRITE		0x68000000
+#define IPR_IOADL_FLAGS_WRITE_LAST	0x69000000
+#define IPR_IOADL_FLAGS_LAST		0x01000000
+
+	__be32 address;
+}__attribute__((packed, aligned (8)));
+
 struct ipr_ioarcb_add_data {
 	union {
 		struct ipr_ioarcb_ata_regs regs;
+		struct ipr_ioadl_desc ioadl[5];
 		__be32 add_cmd_parms[10];
 	}u;
 }__attribute__ ((packed, aligned(4)));
@@ -447,21 +472,6 @@
 	struct ipr_ioarcb_add_data add_data;
 }__attribute__((packed, aligned (4)));
 
-struct ipr_ioadl_desc {
-	__be32 flags_and_data_len;
-#define IPR_IOADL_FLAGS_MASK		0xff000000
-#define IPR_IOADL_GET_FLAGS(x) (be32_to_cpu(x) & IPR_IOADL_FLAGS_MASK)
-#define IPR_IOADL_DATA_LEN_MASK		0x00ffffff
-#define IPR_IOADL_GET_DATA_LEN(x) (be32_to_cpu(x) & IPR_IOADL_DATA_LEN_MASK)
-#define IPR_IOADL_FLAGS_READ		0x48000000
-#define IPR_IOADL_FLAGS_READ_LAST	0x49000000
-#define IPR_IOADL_FLAGS_WRITE		0x68000000
-#define IPR_IOADL_FLAGS_WRITE_LAST	0x69000000
-#define IPR_IOADL_FLAGS_LAST		0x01000000
-
-	__be32 address;
-}__attribute__((packed, aligned (8)));
-
 struct ipr_ioasa_vset {
 	__be32 failing_lba_hi;
 	__be32 failing_lba_lo;
@@ -1119,6 +1129,7 @@
 
 	struct ipr_bus_attributes bus_attr[IPR_MAX_NUM_BUSES];
 
+	unsigned int transop_timeout;
 	const struct ipr_chip_cfg_t *chip_cfg;
 
 	void __iomem *hdw_dma_regs;	/* iomapped PCI memory space */
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index 8f55e14..c9a3abf 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -527,12 +527,12 @@
 		 * than 8K, but there are no targets that currently do this.
 		 * For now we fail until we find a vendor that needs it
 		 */
-		if (DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH <
+		if (ISCSI_DEF_MAX_RECV_SEG_LEN <
 		    tcp_conn->in.datalen) {
 			printk(KERN_ERR "iscsi_tcp: received buffer of len %u "
 			      "but conn buffer is only %u (opcode %0x)\n",
 			      tcp_conn->in.datalen,
-			      DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH, opcode);
+			      ISCSI_DEF_MAX_RECV_SEG_LEN, opcode);
 			rc = ISCSI_ERR_PROTO;
 			break;
 		}
@@ -1762,7 +1762,7 @@
 	 * due to strange issues with iser these are not set
 	 * in iscsi_conn_setup
 	 */
-	conn->max_recv_dlength = DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH;
+	conn->max_recv_dlength = ISCSI_DEF_MAX_RECV_SEG_LEN;
 
 	tcp_conn = kzalloc(sizeof(*tcp_conn), GFP_KERNEL);
 	if (!tcp_conn)
@@ -1777,14 +1777,24 @@
 	tcp_conn->tx_hash.tfm = crypto_alloc_hash("crc32c", 0,
 						  CRYPTO_ALG_ASYNC);
 	tcp_conn->tx_hash.flags = 0;
-	if (IS_ERR(tcp_conn->tx_hash.tfm))
+	if (IS_ERR(tcp_conn->tx_hash.tfm)) {
+		printk(KERN_ERR "Could not create connection due to crc32c "
+		       "loading error %ld. Make sure the crc32c module is "
+		       "built as a module or into the kernel\n",
+			PTR_ERR(tcp_conn->tx_hash.tfm));
 		goto free_tcp_conn;
+	}
 
 	tcp_conn->rx_hash.tfm = crypto_alloc_hash("crc32c", 0,
 						  CRYPTO_ALG_ASYNC);
 	tcp_conn->rx_hash.flags = 0;
-	if (IS_ERR(tcp_conn->rx_hash.tfm))
+	if (IS_ERR(tcp_conn->rx_hash.tfm)) {
+		printk(KERN_ERR "Could not create connection due to crc32c "
+		       "loading error %ld. Make sure the crc32c module is "
+		       "built as a module or into the kernel\n",
+			PTR_ERR(tcp_conn->rx_hash.tfm));
 		goto free_tx_tfm;
+	}
 
 	return cls_conn;
 
@@ -2138,6 +2148,7 @@
 	.change_queue_depth	= iscsi_change_queue_depth,
 	.can_queue		= ISCSI_XMIT_CMDS_MAX - 1,
 	.sg_tablesize		= ISCSI_SG_TABLESIZE,
+	.max_sectors		= 0xFFFF,
 	.cmd_per_lun		= ISCSI_DEF_CMD_PER_LUN,
 	.eh_abort_handler       = iscsi_eh_abort,
 	.eh_host_reset_handler	= iscsi_eh_host_reset,
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index 7c75771..3f5b9b4 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -25,6 +25,7 @@
 #include <linux/mutex.h>
 #include <linux/kfifo.h>
 #include <linux/delay.h>
+#include <asm/unaligned.h>
 #include <net/tcp.h>
 #include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_device.h>
@@ -269,14 +270,14 @@
 			goto out;
 		}
 
-		senselen = be16_to_cpu(*(__be16 *)data);
+		senselen = be16_to_cpu(get_unaligned((__be16 *) data));
 		if (datalen < senselen)
 			goto invalid_datalen;
 
 		memcpy(sc->sense_buffer, data + 2,
 		       min_t(uint16_t, senselen, SCSI_SENSE_BUFFERSIZE));
 		debug_scsi("copied %d bytes of sense\n",
-			   min(senselen, SCSI_SENSE_BUFFERSIZE));
+			   min_t(uint16_t, senselen, SCSI_SENSE_BUFFERSIZE));
 	}
 
 	if (sc->sc_data_direction == DMA_TO_DEVICE)
@@ -577,7 +578,7 @@
 }
 EXPORT_SYMBOL_GPL(iscsi_conn_failure);
 
-static int iscsi_xmit_imm_task(struct iscsi_conn *conn)
+static int iscsi_xmit_mtask(struct iscsi_conn *conn)
 {
 	struct iscsi_hdr *hdr = conn->mtask->hdr;
 	int rc, was_logout = 0;
@@ -591,6 +592,9 @@
 	if (rc)
 		return rc;
 
+	/* done with this in-progress mtask */
+	conn->mtask = NULL;
+
 	if (was_logout) {
 		set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
 		return -ENODATA;
@@ -643,11 +647,9 @@
 		conn->ctask = NULL;
 	}
 	if (conn->mtask) {
-		rc = iscsi_xmit_imm_task(conn);
+		rc = iscsi_xmit_mtask(conn);
 	        if (rc)
 		        goto again;
-		/* done with this in-progress mtask */
-		conn->mtask = NULL;
 	}
 
 	/* process immediate first */
@@ -658,12 +660,10 @@
 			list_add_tail(&conn->mtask->running,
 				      &conn->mgmt_run_list);
 			spin_unlock_bh(&conn->session->lock);
-			rc = iscsi_xmit_imm_task(conn);
+			rc = iscsi_xmit_mtask(conn);
 		        if (rc)
 			        goto again;
 	        }
-		/* done with this mtask */
-		conn->mtask = NULL;
 	}
 
 	/* process command queue */
@@ -701,12 +701,10 @@
 			list_add_tail(&conn->mtask->running,
 				      &conn->mgmt_run_list);
 			spin_unlock_bh(&conn->session->lock);
-		        rc = tt->xmit_mgmt_task(conn, conn->mtask);
-			if (rc)
+			rc = iscsi_xmit_mtask(conn);
+		        if (rc)
 			        goto again;
 	        }
-		/* done with this mtask */
-		conn->mtask = NULL;
 	}
 
 	return -ENODATA;
@@ -1523,7 +1521,7 @@
 	}
 	spin_unlock_bh(&session->lock);
 
-	data = kmalloc(DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH, GFP_KERNEL);
+	data = kmalloc(ISCSI_DEF_MAX_RECV_SEG_LEN, GFP_KERNEL);
 	if (!data)
 		goto login_mtask_data_alloc_fail;
 	conn->login_mtask->data = conn->data = data;
@@ -1597,6 +1595,9 @@
 		wake_up(&conn->ehwait);
 	}
 
+	/* flush queued up work because we free the connection below */
+	scsi_flush_work(session->host);
+
 	spin_lock_bh(&session->lock);
 	kfree(conn->data);
 	kfree(conn->persistent_address);
diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c
index dc70c18..e34442e 100644
--- a/drivers/scsi/libsas/sas_expander.c
+++ b/drivers/scsi/libsas/sas_expander.c
@@ -22,7 +22,6 @@
  *
  */
 
-#include <linux/pci.h>
 #include <linux/scatterlist.h>
 
 #include "sas_internal.h"
diff --git a/drivers/scsi/libsrp.c b/drivers/scsi/libsrp.c
index 89403b0..5631c19 100644
--- a/drivers/scsi/libsrp.c
+++ b/drivers/scsi/libsrp.c
@@ -22,7 +22,6 @@
 #include <linux/kfifo.h>
 #include <linux/scatterlist.h>
 #include <linux/dma-mapping.h>
-#include <linux/pci.h>
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_tcq.h>
@@ -225,8 +224,7 @@
 	struct srp_direct_buf *md = NULL;
 	struct scatterlist dummy, *sg = NULL;
 	dma_addr_t token = 0;
-	long err;
-	unsigned int done = 0;
+	int err = 0;
 	int nmd, nsg = 0, len;
 
 	if (dma_map || ext_desc) {
@@ -258,8 +256,8 @@
 		sg_dma_address(&dummy) = token;
 		err = rdma_io(sc, &dummy, 1, &id->table_desc, 1, DMA_TO_DEVICE,
 			      id->table_desc.len);
-		if (err < 0) {
-			eprintk("Error copying indirect table %ld\n", err);
+		if (err) {
+			eprintk("Error copying indirect table %d\n", err);
 			goto free_mem;
 		}
 	} else {
@@ -272,6 +270,7 @@
 		nsg = dma_map_sg(iue->target->dev, sg, sc->use_sg, DMA_BIDIRECTIONAL);
 		if (!nsg) {
 			eprintk("fail to map %p %d\n", iue, sc->use_sg);
+			err = -EIO;
 			goto free_mem;
 		}
 		len = min(sc->request_bufflen, id->len);
@@ -287,7 +286,7 @@
 	if (token && dma_map)
 		dma_free_coherent(iue->target->dev, id->table_desc.len, md, token);
 
-	return done;
+	return err;
 }
 
 static int data_out_desc_size(struct srp_cmd *cmd)
@@ -352,7 +351,7 @@
 		break;
 	default:
 		eprintk("Unknown format %d %x\n", dir, format);
-		break;
+		err = -EINVAL;
 	}
 
 	return err;
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 057fd7e0..dcf6106 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -671,7 +671,7 @@
 lpfc_parse_vpd(struct lpfc_hba * phba, uint8_t * vpd, int len)
 {
 	uint8_t lenlo, lenhi;
-	uint32_t Length;
+	int Length;
 	int i, j;
 	int finished = 0;
 	int index = 0;
diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c
index 0aa3304..7fc6e06 100644
--- a/drivers/scsi/megaraid.c
+++ b/drivers/scsi/megaraid.c
@@ -2088,7 +2088,7 @@
 static inline int
 make_local_pdev(adapter_t *adapter, struct pci_dev **pdev)
 {
-	*pdev = kmalloc(sizeof(struct pci_dev), GFP_KERNEL);
+	*pdev = alloc_pci_dev();
 
 	if( *pdev == NULL ) return -1;
 
diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c
index a967fad..08060fb 100644
--- a/drivers/scsi/osst.c
+++ b/drivers/scsi/osst.c
@@ -87,6 +87,7 @@
 MODULE_DESCRIPTION("OnStream {DI-|FW-|SC-|USB}{30|50} Tape Driver");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS_CHARDEV_MAJOR(OSST_MAJOR);
+MODULE_ALIAS_SCSI_DEVICE(TYPE_TAPE);
 
 module_param(max_dev, int, 0444);
 MODULE_PARM_DESC(max_dev, "Maximum number of OnStream Tape Drives to attach (4)");
diff --git a/drivers/scsi/pci2000.h b/drivers/scsi/pci2000.h
deleted file mode 100644
index 0ebd8ce..0000000
--- a/drivers/scsi/pci2000.h
+++ /dev/null
@@ -1,197 +0,0 @@
-/****************************************************************************
- * Perceptive Solutions, Inc. PCI-2000 device driver for Linux.
- *
- * pci2000.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 _PCI2000_H
-#define _PCI2000_H
-
-#include <linux/types.h>
-
-#ifndef	PSI_EIDE_SCSIOP
-#define	PSI_EIDE_SCSIOP	1
-
-#define	LINUXVERSION(v,p,s)    (((v)<<16) + ((p)<<8) + (s))
-
-/************************************************/
-/*		definition of standard data types		*/
-/************************************************/
-#define	CHAR	char
-#define	UCHAR	unsigned char
-#define	SHORT	short
-#define	USHORT	unsigned short
-#define	BOOL	long
-#define	LONG	long
-#define	ULONG	unsigned long
-#define	VOID	void
-
-typedef	CHAR	*PCHAR;
-typedef	UCHAR	*PUCHAR;
-typedef	SHORT	*PSHORT;
-typedef	USHORT	*PUSHORT;
-typedef	BOOL	*PBOOL;
-typedef	LONG	*PLONG;
-typedef	ULONG	*PULONG;
-typedef	VOID	*PVOID;
-
-
-/************************************************/
-/*		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])) )
-
-/************************************************/
-/*		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
-
-// 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;
-
-#endif
-
-// function prototypes
-int Pci2000_Detect			(struct scsi_host_template *tpnt);
-int Pci2000_Command			(Scsi_Cmnd *SCpnt);
-int Pci2000_QueueCommand	(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *));
-int Pci2000_Abort			(Scsi_Cmnd *SCpnt);
-int Pci2000_Reset			(Scsi_Cmnd *SCpnt, unsigned int flags);
-int Pci2000_Release			(struct Scsi_Host *pshost);
-int Pci2000_BiosParam		(struct scsi_device *sdev,
-					struct block_device *bdev,
-					sector_t capacity, int geom[]);
-
-#endif
diff --git a/drivers/scsi/pcmcia/Kconfig b/drivers/scsi/pcmcia/Kconfig
index eac8e17..7dd787f 100644
--- a/drivers/scsi/pcmcia/Kconfig
+++ b/drivers/scsi/pcmcia/Kconfig
@@ -3,11 +3,11 @@
 #
 
 menu "PCMCIA SCSI adapter support"
-	depends on SCSI!=n && PCMCIA!=n && MODULES
+	depends on SCSI!=n && PCMCIA!=n
 
 config PCMCIA_AHA152X
 	tristate "Adaptec AHA152X PCMCIA support"
-	depends on m && !64BIT
+	depends on !64BIT
 	select SCSI_SPI_ATTRS
 	help
 	  Say Y here if you intend to attach this type of PCMCIA SCSI host
@@ -18,7 +18,6 @@
 
 config PCMCIA_FDOMAIN
 	tristate "Future Domain PCMCIA support"
-	depends on m
 	help
 	  Say Y here if you intend to attach this type of PCMCIA SCSI host
 	  adapter to your computer.
@@ -28,7 +27,7 @@
 
 config PCMCIA_NINJA_SCSI
 	tristate "NinjaSCSI-3 / NinjaSCSI-32Bi (16bit) PCMCIA support"
-	depends on m && !64BIT
+	depends on !64BIT
 	help
 	  If you intend to attach this type of PCMCIA SCSI host adapter to
 	  your computer, say Y here and read
@@ -62,7 +61,6 @@
 
 config PCMCIA_QLOGIC
 	tristate "Qlogic PCMCIA support"
-	depends on m
 	help
 	  Say Y here if you intend to attach this type of PCMCIA SCSI host
 	  adapter to your computer.
@@ -72,7 +70,6 @@
 
 config PCMCIA_SYM53C500
 	tristate "Symbios 53c500 PCMCIA support"
-	depends on m
 	help
 	  Say Y here if you have a New Media Bus Toaster or other PCMCIA
 	  SCSI adapter based on the Symbios 53c500 controller.
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 05f4f2a..e8948b6 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -1478,14 +1478,17 @@
 	uint32_t b24 : 24;
 
 	struct {
-		uint8_t d_id[3];
-		uint8_t rsvd_1;
-	} r;
-
-	struct {
+#ifdef __BIG_ENDIAN
+		uint8_t domain;
+		uint8_t area;
+		uint8_t al_pa;
+#elif __LITTLE_ENDIAN
 		uint8_t al_pa;
 		uint8_t area;
 		uint8_t domain;
+#else
+#error "__BIG_ENDIAN or __LITTLE_ENDIAN must be defined!"
+#endif
 		uint8_t rsvd_1;
 	} b;
 } port_id_t;
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 98c01cd..3e296ab 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -11,6 +11,11 @@
 
 #include "qla_devtbl.h"
 
+#ifdef CONFIG_SPARC
+#include <asm/prom.h>
+#include <asm/pbm.h>
+#endif
+
 /* XXX(hch): this is ugly, but we don't want to pull in exioctl.h */
 #ifndef EXT_IS_LUN_BIT_SET
 #define EXT_IS_LUN_BIT_SET(P,L) \
@@ -88,12 +93,7 @@
 
 	qla_printk(KERN_INFO, ha, "Configure NVRAM parameters...\n");
 
-	rval = ha->isp_ops.nvram_config(ha);
-	if (rval) {
-		DEBUG2(printk("scsi(%ld): Unable to verify NVRAM data.\n",
-		    ha->host_no));
-		return rval;
-	}
+	ha->isp_ops.nvram_config(ha);
 
 	if (ha->flags.disable_serdes) {
 		/* Mask HBA via NVRAM settings? */
@@ -1393,6 +1393,28 @@
 	}
 }
 
+/* On sparc systems, obtain port and node WWN from firmware
+ * properties.
+ */
+static void qla2xxx_nvram_wwn_from_ofw(scsi_qla_host_t *ha, nvram_t *nv)
+{
+#ifdef CONFIG_SPARC
+	struct pci_dev *pdev = ha->pdev;
+	struct pcidev_cookie *pcp = pdev->sysdata;
+	struct device_node *dp = pcp->prom_node;
+	u8 *val;
+	int len;
+
+	val = of_get_property(dp, "port-wwn", &len);
+	if (val && len >= WWN_SIZE)
+		memcpy(nv->port_name, val, WWN_SIZE);
+
+	val = of_get_property(dp, "node-wwn", &len);
+	if (val && len >= WWN_SIZE)
+		memcpy(nv->node_name, val, WWN_SIZE);
+#endif
+}
+
 /*
 * NVRAM configuration for ISP 2xxx
 *
@@ -1409,6 +1431,7 @@
 int
 qla2x00_nvram_config(scsi_qla_host_t *ha)
 {
+	int             rval;
 	uint8_t         chksum = 0;
 	uint16_t        cnt;
 	uint8_t         *dptr1, *dptr2;
@@ -1417,6 +1440,8 @@
 	uint8_t         *ptr = (uint8_t *)ha->request_ring;
 	struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
 
+	rval = QLA_SUCCESS;
+
 	/* Determine NVRAM starting address. */
 	ha->nvram_size = sizeof(nvram_t);
 	ha->nvram_base = 0;
@@ -1440,7 +1465,57 @@
 		qla_printk(KERN_WARNING, ha, "Inconsistent NVRAM detected: "
 		    "checksum=0x%x id=%c version=0x%x.\n", chksum, nv->id[0],
 		    nv->nvram_version);
-		return QLA_FUNCTION_FAILED;
+		qla_printk(KERN_WARNING, ha, "Falling back to functioning (yet "
+		    "invalid -- WWPN) defaults.\n");
+
+		/*
+		 * Set default initialization control block.
+		 */
+		memset(nv, 0, ha->nvram_size);
+		nv->parameter_block_version = ICB_VERSION;
+
+		if (IS_QLA23XX(ha)) {
+			nv->firmware_options[0] = BIT_2 | BIT_1;
+			nv->firmware_options[1] = BIT_7 | BIT_5;
+			nv->add_firmware_options[0] = BIT_5;
+			nv->add_firmware_options[1] = BIT_5 | BIT_4;
+			nv->frame_payload_size = __constant_cpu_to_le16(2048);
+			nv->special_options[1] = BIT_7;
+		} else if (IS_QLA2200(ha)) {
+			nv->firmware_options[0] = BIT_2 | BIT_1;
+			nv->firmware_options[1] = BIT_7 | BIT_5;
+			nv->add_firmware_options[0] = BIT_5;
+			nv->add_firmware_options[1] = BIT_5 | BIT_4;
+			nv->frame_payload_size = __constant_cpu_to_le16(1024);
+		} else if (IS_QLA2100(ha)) {
+			nv->firmware_options[0] = BIT_3 | BIT_1;
+			nv->firmware_options[1] = BIT_5;
+			nv->frame_payload_size = __constant_cpu_to_le16(1024);
+		}
+
+		nv->max_iocb_allocation = __constant_cpu_to_le16(256);
+		nv->execution_throttle = __constant_cpu_to_le16(16);
+		nv->retry_count = 8;
+		nv->retry_delay = 1;
+
+		nv->port_name[0] = 33;
+		nv->port_name[3] = 224;
+		nv->port_name[4] = 139;
+
+		qla2xxx_nvram_wwn_from_ofw(ha, nv);
+
+		nv->login_timeout = 4;
+
+		/*
+		 * Set default host adapter parameters
+		 */
+		nv->host_p[1] = BIT_2;
+		nv->reset_delay = 5;
+		nv->port_down_retry_count = 8;
+		nv->max_luns_per_target = __constant_cpu_to_le16(8);
+		nv->link_down_timeout = 60;
+
+		rval = 1;
 	}
 
 #if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_SGI_SN2)
@@ -1653,7 +1728,11 @@
 		}
 	}
 
-	return QLA_SUCCESS;
+	if (rval) {
+		DEBUG2_3(printk(KERN_WARNING
+		    "scsi(%ld): NVRAM configuration failed!\n", ha->host_no));
+	}
+	return (rval);
 }
 
 static void
@@ -3071,9 +3150,7 @@
 
 		ha->isp_ops.get_flash_version(ha, ha->request_ring);
 
-		rval = ha->isp_ops.nvram_config(ha);
-		if (rval)
-			goto isp_abort_retry;
+		ha->isp_ops.nvram_config(ha);
 
 		if (!qla2x00_restart_isp(ha)) {
 			clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags);
@@ -3103,7 +3180,6 @@
 				}
 			}
 		} else {	/* failed the ISP abort */
-isp_abort_retry:
 			ha->flags.online = 1;
 			if (test_bit(ISP_ABORT_RETRY, &ha->dpc_flags)) {
 				if (ha->isp_abort_cnt == 0) {
@@ -3290,9 +3366,32 @@
 	spin_unlock_irqrestore(&ha->hardware_lock, flags);
 }
 
+/* On sparc systems, obtain port and node WWN from firmware
+ * properties.
+ */
+static void qla24xx_nvram_wwn_from_ofw(scsi_qla_host_t *ha, struct nvram_24xx *nv)
+{
+#ifdef CONFIG_SPARC
+	struct pci_dev *pdev = ha->pdev;
+	struct pcidev_cookie *pcp = pdev->sysdata;
+	struct device_node *dp = pcp->prom_node;
+	u8 *val;
+	int len;
+
+	val = of_get_property(dp, "port-wwn", &len);
+	if (val && len >= WWN_SIZE)
+		memcpy(nv->port_name, val, WWN_SIZE);
+
+	val = of_get_property(dp, "node-wwn", &len);
+	if (val && len >= WWN_SIZE)
+		memcpy(nv->node_name, val, WWN_SIZE);
+#endif
+}
+
 int
 qla24xx_nvram_config(scsi_qla_host_t *ha)
 {
+	int   rval;
 	struct init_cb_24xx *icb;
 	struct nvram_24xx *nv;
 	uint32_t *dptr;
@@ -3300,6 +3399,7 @@
 	uint32_t chksum;
 	uint16_t cnt;
 
+	rval = QLA_SUCCESS;
 	icb = (struct init_cb_24xx *)ha->init_cb;
 	nv = (struct nvram_24xx *)ha->request_ring;
 
@@ -3332,7 +3432,52 @@
 		qla_printk(KERN_WARNING, ha, "Inconsistent NVRAM detected: "
 		    "checksum=0x%x id=%c version=0x%x.\n", chksum, nv->id[0],
 		    le16_to_cpu(nv->nvram_version));
-		return QLA_FUNCTION_FAILED;
+		qla_printk(KERN_WARNING, ha, "Falling back to functioning (yet "
+		    "invalid -- WWPN) defaults.\n");
+
+		/*
+		 * Set default initialization control block.
+		 */
+		memset(nv, 0, ha->nvram_size);
+		nv->nvram_version = __constant_cpu_to_le16(ICB_VERSION);
+		nv->version = __constant_cpu_to_le16(ICB_VERSION);
+		nv->frame_payload_size = __constant_cpu_to_le16(2048);
+		nv->execution_throttle = __constant_cpu_to_le16(0xFFFF);
+		nv->exchange_count = __constant_cpu_to_le16(0);
+		nv->hard_address = __constant_cpu_to_le16(124);
+		nv->port_name[0] = 0x21;
+		nv->port_name[1] = 0x00 + PCI_FUNC(ha->pdev->devfn);
+		nv->port_name[2] = 0x00;
+		nv->port_name[3] = 0xe0;
+		nv->port_name[4] = 0x8b;
+		nv->port_name[5] = 0x1c;
+		nv->port_name[6] = 0x55;
+		nv->port_name[7] = 0x86;
+		nv->node_name[0] = 0x20;
+		nv->node_name[1] = 0x00;
+		nv->node_name[2] = 0x00;
+		nv->node_name[3] = 0xe0;
+		nv->node_name[4] = 0x8b;
+		nv->node_name[5] = 0x1c;
+		nv->node_name[6] = 0x55;
+		nv->node_name[7] = 0x86;
+		qla24xx_nvram_wwn_from_ofw(ha, nv);
+		nv->login_retry_count = __constant_cpu_to_le16(8);
+		nv->interrupt_delay_timer = __constant_cpu_to_le16(0);
+		nv->login_timeout = __constant_cpu_to_le16(0);
+		nv->firmware_options_1 =
+		    __constant_cpu_to_le32(BIT_14|BIT_13|BIT_2|BIT_1);
+		nv->firmware_options_2 = __constant_cpu_to_le32(2 << 4);
+		nv->firmware_options_2 |= __constant_cpu_to_le32(BIT_12);
+		nv->firmware_options_3 = __constant_cpu_to_le32(2 << 13);
+		nv->host_p = __constant_cpu_to_le32(BIT_11|BIT_10);
+		nv->efi_parameters = __constant_cpu_to_le32(0);
+		nv->reset_delay = 5;
+		nv->max_luns_per_target = __constant_cpu_to_le16(128);
+		nv->port_down_retry_count = __constant_cpu_to_le16(30);
+		nv->link_down_timeout = __constant_cpu_to_le16(30);
+
+		rval = 1;
 	}
 
 	/* Reset Initialization control block */
@@ -3479,7 +3624,11 @@
 		ha->flags.process_response_queue = 1;
 	}
 
-	return QLA_SUCCESS;
+	if (rval) {
+		DEBUG2_3(printk(KERN_WARNING
+		    "scsi(%ld): NVRAM configuration failed!\n", ha->host_no));
+	}
+	return (rval);
 }
 
 static int
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index 83376f6..71e32a24 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -1280,14 +1280,14 @@
 	} else {
 		if (name != NULL) {
 			/* This function returns name in big endian. */
-			name[0] = LSB(mcp->mb[2]);
-			name[1] = MSB(mcp->mb[2]);
-			name[2] = LSB(mcp->mb[3]);
-			name[3] = MSB(mcp->mb[3]);
-			name[4] = LSB(mcp->mb[6]);
-			name[5] = MSB(mcp->mb[6]);
-			name[6] = LSB(mcp->mb[7]);
-			name[7] = MSB(mcp->mb[7]);
+			name[0] = MSB(mcp->mb[2]);
+			name[1] = LSB(mcp->mb[2]);
+			name[2] = MSB(mcp->mb[3]);
+			name[3] = LSB(mcp->mb[3]);
+			name[4] = MSB(mcp->mb[6]);
+			name[5] = LSB(mcp->mb[6]);
+			name[6] = MSB(mcp->mb[7]);
+			name[7] = LSB(mcp->mb[7]);
 		}
 
 		DEBUG11(printk("qla2x00_get_port_name(%ld): done.\n",
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 68f5d24..b78919a 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -62,7 +62,7 @@
 		"vary by ISP type.  Default is 1 - allocate memory.");
 
 int ql2xextended_error_logging;
-module_param(ql2xextended_error_logging, int, S_IRUGO|S_IRUSR);
+module_param(ql2xextended_error_logging, int, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(ql2xextended_error_logging,
 		"Option to enable extended error logging, "
 		"Default is 0 - no logging. 1 - log errors.");
@@ -157,6 +157,8 @@
 
 	.slave_alloc		= qla2xxx_slave_alloc,
 	.slave_destroy		= qla2xxx_slave_destroy,
+	.scan_finished		= qla2xxx_scan_finished,
+	.scan_start		= qla2xxx_scan_start,
 	.change_queue_depth	= qla2x00_change_queue_depth,
 	.change_queue_type	= qla2x00_change_queue_type,
 	.this_id		= -1,
@@ -1705,6 +1707,7 @@
 
 	scsi_host_put(ha->host);
 
+	pci_disable_device(pdev);
 	pci_set_drvdata(pdev, NULL);
 }
 
@@ -1747,8 +1750,6 @@
 	if (ha->iobase)
 		iounmap(ha->iobase);
 	pci_release_regions(ha->pdev);
-
-	pci_disable_device(ha->pdev);
 }
 
 static inline void
diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c
index ff1dd41..206bda0 100644
--- a/drivers/scsi/qla2xxx/qla_sup.c
+++ b/drivers/scsi/qla2xxx/qla_sup.c
@@ -466,6 +466,7 @@
 			udelay(10);
 		else
 			rval = QLA_FUNCTION_TIMEOUT;
+		cond_resched();
 	}
 
 	/* TODO: What happens if we time out? */
@@ -508,6 +509,7 @@
 			udelay(10);
 		else
 			rval = QLA_FUNCTION_TIMEOUT;
+		cond_resched();
 	}
 	return rval;
 }
@@ -1255,6 +1257,7 @@
 		}
 		udelay(10);
 		barrier();
+		cond_resched();
 	}
 	return status;
 }
@@ -1403,6 +1406,7 @@
 		if (saddr % 100)
 			udelay(10);
 		*tmp_buf = data;
+		cond_resched();
 	}
 }
 
@@ -1449,7 +1453,6 @@
 qla2x00_read_optrom_data(struct scsi_qla_host *ha, uint8_t *buf,
     uint32_t offset, uint32_t length)
 {
-	unsigned long flags;
 	uint32_t addr, midpoint;
 	uint8_t *data;
 	struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
@@ -1458,7 +1461,6 @@
 	qla2x00_suspend_hba(ha);
 
 	/* Go with read. */
-	spin_lock_irqsave(&ha->hardware_lock, flags);
 	midpoint = ha->optrom_size / 2;
 
 	qla2x00_flash_enable(ha);
@@ -1473,7 +1475,6 @@
 		*data = qla2x00_read_flash_byte(ha, addr);
 	}
 	qla2x00_flash_disable(ha);
-	spin_unlock_irqrestore(&ha->hardware_lock, flags);
 
 	/* Resume HBA. */
 	qla2x00_resume_hba(ha);
@@ -1487,7 +1488,6 @@
 {
 
 	int rval;
-	unsigned long flags;
 	uint8_t man_id, flash_id, sec_number, data;
 	uint16_t wd;
 	uint32_t addr, liter, sec_mask, rest_addr;
@@ -1500,7 +1500,6 @@
 	sec_number = 0;
 
 	/* Reset ISP chip. */
-	spin_lock_irqsave(&ha->hardware_lock, flags);
 	WRT_REG_WORD(&reg->ctrl_status, CSR_ISP_SOFT_RESET);
 	pci_read_config_word(ha->pdev, PCI_COMMAND, &wd);
 
@@ -1689,10 +1688,10 @@
 				rval = QLA_FUNCTION_FAILED;
 				break;
 			}
+			cond_resched();
 		}
 	} while (0);
 	qla2x00_flash_disable(ha);
-	spin_unlock_irqrestore(&ha->hardware_lock, flags);
 
 	/* Resume HBA. */
 	qla2x00_resume_hba(ha);
diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h
index 61347ae..dc85495 100644
--- a/drivers/scsi/qla2xxx/qla_version.h
+++ b/drivers/scsi/qla2xxx/qla_version.h
@@ -7,7 +7,7 @@
 /*
  * Driver version
  */
-#define QLA2XXX_VERSION      "8.01.07-k5"
+#define QLA2XXX_VERSION      "8.01.07-k6"
 
 #define QLA_DRIVER_MAJOR_VER	8
 #define QLA_DRIVER_MINOR_VER	1
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index 1c89ee3..4c1e313 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -344,7 +344,6 @@
 void scsi_log_send(struct scsi_cmnd *cmd)
 {
 	unsigned int level;
-	struct scsi_device *sdev;
 
 	/*
 	 * If ML QUEUE log level is greater than or equal to:
@@ -361,22 +360,17 @@
 		level = SCSI_LOG_LEVEL(SCSI_LOG_MLQUEUE_SHIFT,
 				       SCSI_LOG_MLQUEUE_BITS);
 		if (level > 1) {
-			sdev = cmd->device;
-			sdev_printk(KERN_INFO, sdev, "send ");
+			scmd_printk(KERN_INFO, cmd, "Send: ");
 			if (level > 2)
 				printk("0x%p ", cmd);
-			/*
-			 * spaces to match disposition and cmd->result
-			 * output in scsi_log_completion.
-			 */
-			printk("                 ");
+			printk("\n");
 			scsi_print_command(cmd);
 			if (level > 3) {
 				printk(KERN_INFO "buffer = 0x%p, bufflen = %d,"
 				       " done = 0x%p, queuecommand 0x%p\n",
 					cmd->request_buffer, cmd->request_bufflen,
 					cmd->done,
-					sdev->host->hostt->queuecommand);
+					cmd->device->host->hostt->queuecommand);
 
 			}
 		}
@@ -386,7 +380,6 @@
 void scsi_log_completion(struct scsi_cmnd *cmd, int disposition)
 {
 	unsigned int level;
-	struct scsi_device *sdev;
 
 	/*
 	 * If ML COMPLETE log level is greater than or equal to:
@@ -405,8 +398,7 @@
 				       SCSI_LOG_MLCOMPLETE_BITS);
 		if (((level > 0) && (cmd->result || disposition != SUCCESS)) ||
 		    (level > 1)) {
-			sdev = cmd->device;
-			sdev_printk(KERN_INFO, sdev, "done ");
+			scmd_printk(KERN_INFO, cmd, "Done: ");
 			if (level > 2)
 				printk("0x%p ", cmd);
 			/*
@@ -415,40 +407,35 @@
 			 */
 			switch (disposition) {
 			case SUCCESS:
-				printk("SUCCESS");
+				printk("SUCCESS\n");
 				break;
 			case NEEDS_RETRY:
-				printk("RETRY  ");
+				printk("RETRY\n");
 				break;
 			case ADD_TO_MLQUEUE:
-				printk("MLQUEUE");
+				printk("MLQUEUE\n");
 				break;
 			case FAILED:
-				printk("FAILED ");
+				printk("FAILED\n");
 				break;
 			case TIMEOUT_ERROR:
 				/* 
 				 * If called via scsi_times_out.
 				 */
-				printk("TIMEOUT");
+				printk("TIMEOUT\n");
 				break;
 			default:
-				printk("UNKNOWN");
+				printk("UNKNOWN\n");
 			}
-			printk(" %8x ", cmd->result);
+			scsi_print_result(cmd);
 			scsi_print_command(cmd);
-			if (status_byte(cmd->result) & CHECK_CONDITION) {
-				/*
-				 * XXX The scsi_print_sense formatting/prefix
-				 * doesn't match this function.
-				 */
+			if (status_byte(cmd->result) & CHECK_CONDITION)
 				scsi_print_sense("", cmd);
-			}
-			if (level > 3) {
-				printk(KERN_INFO "scsi host busy %d failed %d\n",
-				       sdev->host->host_busy,
-				       sdev->host->host_failed);
-			}
+			if (level > 3)
+				scmd_printk(KERN_INFO, cmd,
+					    "scsi host busy %d failed %d\n",
+					    cmd->device->host->host_busy,
+					    cmd->device->host->host_failed);
 		}
 	}
 }
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index 918bb60..3963e70 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -184,10 +184,19 @@
  **/
 void scsi_times_out(struct scsi_cmnd *scmd)
 {
+	enum scsi_eh_timer_return (* eh_timed_out)(struct scsi_cmnd *);
+
 	scsi_log_completion(scmd, TIMEOUT_ERROR);
 
 	if (scmd->device->host->transportt->eh_timed_out)
-		switch (scmd->device->host->transportt->eh_timed_out(scmd)) {
+		eh_timed_out = scmd->device->host->transportt->eh_timed_out;
+	else if (scmd->device->host->hostt->eh_timed_out)
+		eh_timed_out = scmd->device->host->hostt->eh_timed_out;
+	else
+		eh_timed_out = NULL;
+
+	if (eh_timed_out)
+		switch (eh_timed_out(scmd)) {
 		case EH_HANDLED:
 			__scsi_done(scmd);
 			return;
@@ -923,10 +932,12 @@
 	static unsigned char stu_command[6] = {START_STOP, 0, 0, 0, 1, 0};
 
 	if (scmd->device->allow_restart) {
-		int rtn;
+		int i, rtn = NEEDS_RETRY;
 
-		rtn = scsi_send_eh_cmnd(scmd, stu_command, 6,
-					START_UNIT_TIMEOUT, 0);
+		for (i = 0; rtn == NEEDS_RETRY && i < 2; i++)
+			rtn = scsi_send_eh_cmnd(scmd, stu_command, 6,
+						START_UNIT_TIMEOUT, 0);
+
 		if (rtn == SUCCESS)
 			return 0;
 	}
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 05d79af..61fbcdc 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -848,8 +848,8 @@
 				memcpy(req->sense, cmd->sense_buffer,  len);
 				req->sense_len = len;
 			}
-		} else
-			req->data_len = cmd->resid;
+		}
+		req->data_len = cmd->resid;
 	}
 
 	/*
@@ -968,9 +968,7 @@
 	}
 	if (result) {
 		if (!(req->cmd_flags & REQ_QUIET)) {
-			scmd_printk(KERN_INFO, cmd,
-				    "SCSI error: return code = 0x%08x\n",
-				    result);
+			scsi_print_result(cmd);
 			if (driver_byte(result) & DRIVER_SENSE)
 				scsi_print_sense("", cmd);
 		}
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index 0949145..a67f315 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -181,10 +181,8 @@
 	return 0;
 }
 
-#ifdef MODULE
 /* Only exported for the benefit of scsi_wait_scan */
 EXPORT_SYMBOL_GPL(scsi_complete_async_scans);
-#endif
 
 /**
  * scsi_unlock_floptical - unlock device via a special MODE SENSE command
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index 939de0d..67a38a1 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -276,8 +276,22 @@
 	return (sdp->inq_periph_qual == SCSI_INQ_PQ_CON)? 1: 0;
 }
 
+static int scsi_bus_uevent(struct device *dev, char **envp, int num_envp,
+		           char *buffer, int buffer_size)
+{
+	struct scsi_device *sdev = to_scsi_device(dev);
+	int i = 0;
+	int length = 0;
+
+	add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length,
+		       "MODALIAS=" SCSI_DEVICE_MODALIAS_FMT, sdev->type);
+	envp[i] = NULL;
+	return 0;
+}
+
 static int scsi_bus_suspend(struct device * dev, pm_message_t state)
 {
+	struct device_driver *drv = dev->driver;
 	struct scsi_device *sdev = to_scsi_device(dev);
 	struct scsi_host_template *sht = sdev->host->hostt;
 	int err;
@@ -286,28 +300,51 @@
 	if (err)
 		return err;
 
-	if (sht->suspend)
-		err = sht->suspend(sdev, state);
+	/* call HLD suspend first */
+	if (drv && drv->suspend) {
+		err = drv->suspend(dev, state);
+		if (err)
+			return err;
+	}
 
-	return err;
+	/* then, call host suspend */
+	if (sht->suspend) {
+		err = sht->suspend(sdev, state);
+		if (err) {
+			if (drv && drv->resume)
+				drv->resume(dev);
+			return err;
+		}
+	}
+
+	return 0;
 }
 
 static int scsi_bus_resume(struct device * dev)
 {
+	struct device_driver *drv = dev->driver;
 	struct scsi_device *sdev = to_scsi_device(dev);
 	struct scsi_host_template *sht = sdev->host->hostt;
-	int err = 0;
+	int err = 0, err2 = 0;
 
+	/* call host resume first */
 	if (sht->resume)
 		err = sht->resume(sdev);
 
+	/* then, call HLD resume */
+	if (drv && drv->resume)
+		err2 = drv->resume(dev);
+
 	scsi_device_resume(sdev);
-	return err;
+
+	/* favor LLD failure */
+	return err ? err : err2;;
 }
 
 struct bus_type scsi_bus_type = {
         .name		= "scsi",
         .match		= scsi_bus_match,
+	.uevent		= scsi_bus_uevent,
 	.suspend	= scsi_bus_suspend,
 	.resume		= scsi_bus_resume,
 };
@@ -547,6 +584,14 @@
 show_sdev_iostat(iodone_cnt);
 show_sdev_iostat(ioerr_cnt);
 
+static ssize_t
+sdev_show_modalias(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct scsi_device *sdev;
+	sdev = to_scsi_device(dev);
+	return snprintf (buf, 20, SCSI_DEVICE_MODALIAS_FMT "\n", sdev->type);
+}
+static DEVICE_ATTR(modalias, S_IRUGO, sdev_show_modalias, NULL);
 
 /* Default template for device attributes.  May NOT be modified */
 static struct device_attribute *scsi_sysfs_sdev_attrs[] = {
@@ -566,6 +611,7 @@
 	&dev_attr_iorequest_cnt,
 	&dev_attr_iodone_cnt,
 	&dev_attr_ioerr_cnt,
+	&dev_attr_modalias,
 	NULL
 };
 
diff --git a/drivers/scsi/scsi_tgt_if.c b/drivers/scsi/scsi_tgt_if.c
index 0e08817..ca22ddf 100644
--- a/drivers/scsi/scsi_tgt_if.c
+++ b/drivers/scsi/scsi_tgt_if.c
@@ -179,10 +179,12 @@
 	switch (ev->hdr.type) {
 	case TGT_UEVENT_CMD_RSP:
 		err = scsi_tgt_kspace_exec(ev->p.cmd_rsp.host_no,
-					   ev->p.cmd_rsp.tag,
 					   ev->p.cmd_rsp.result,
-					   ev->p.cmd_rsp.len,
+					   ev->p.cmd_rsp.tag,
 					   ev->p.cmd_rsp.uaddr,
+					   ev->p.cmd_rsp.len,
+					   ev->p.cmd_rsp.sense_uaddr,
+					   ev->p.cmd_rsp.sense_len,
 					   ev->p.cmd_rsp.rw);
 		break;
 	case TGT_UEVENT_TSK_MGMT_RSP:
diff --git a/drivers/scsi/scsi_tgt_lib.c b/drivers/scsi/scsi_tgt_lib.c
index d402aff..2570f48 100644
--- a/drivers/scsi/scsi_tgt_lib.c
+++ b/drivers/scsi/scsi_tgt_lib.c
@@ -28,7 +28,6 @@
 #include <scsi/scsi_device.h>
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_tgt.h>
-#include <../drivers/md/dm-bio-list.h>
 
 #include "scsi_tgt_priv.h"
 
@@ -42,16 +41,12 @@
 struct scsi_tgt_cmd {
 	/* TODO replace work with James b's code */
 	struct work_struct work;
-	/* TODO replace the lists with a large bio */
-	struct bio_list xfer_done_list;
-	struct bio_list xfer_list;
+	/* TODO fix limits of some drivers */
+	struct bio *bio;
 
 	struct list_head hash_list;
 	struct request *rq;
 	u64 tag;
-
-	void *buffer;
-	unsigned bufflen;
 };
 
 #define TGT_HASH_ORDER	4
@@ -93,7 +88,12 @@
 	if (!tcmd)
 		goto put_dev;
 
-	rq = blk_get_request(shost->uspace_req_q, write, gfp_mask);
+	/*
+	 * The blk helpers are used to the READ/WRITE requests
+	 * transfering data from a initiator point of view. Since
+	 * we are in target mode we want the opposite.
+	 */
+	rq = blk_get_request(shost->uspace_req_q, !write, gfp_mask);
 	if (!rq)
 		goto free_tcmd;
 
@@ -111,8 +111,6 @@
 	rq->cmd_flags |= REQ_TYPE_BLOCK_PC;
 	rq->end_io_data = tcmd;
 
-	bio_list_init(&tcmd->xfer_list);
-	bio_list_init(&tcmd->xfer_done_list);
 	tcmd->rq = rq;
 
 	return cmd;
@@ -157,22 +155,6 @@
 }
 EXPORT_SYMBOL_GPL(scsi_host_put_command);
 
-static void scsi_unmap_user_pages(struct scsi_tgt_cmd *tcmd)
-{
-	struct bio *bio;
-
-	/* must call bio_endio in case bio was bounced */
-	while ((bio = bio_list_pop(&tcmd->xfer_done_list))) {
-		bio_endio(bio, bio->bi_size, 0);
-		bio_unmap_user(bio);
-	}
-
-	while ((bio = bio_list_pop(&tcmd->xfer_list))) {
-		bio_endio(bio, bio->bi_size, 0);
-		bio_unmap_user(bio);
-	}
-}
-
 static void cmd_hashlist_del(struct scsi_cmnd *cmd)
 {
 	struct request_queue *q = cmd->request->q;
@@ -185,6 +167,11 @@
 	spin_unlock_irqrestore(&qdata->cmd_hash_lock, flags);
 }
 
+static void scsi_unmap_user_pages(struct scsi_tgt_cmd *tcmd)
+{
+	blk_rq_unmap_user(tcmd->bio);
+}
+
 static void scsi_tgt_cmd_destroy(struct work_struct *work)
 {
 	struct scsi_tgt_cmd *tcmd =
@@ -193,16 +180,6 @@
 
 	dprintk("cmd %p %d %lu\n", cmd, cmd->sc_data_direction,
 		rq_data_dir(cmd->request));
-	/*
-	 * We fix rq->cmd_flags here since when we told bio_map_user
-	 * to write vm for WRITE commands, blk_rq_bio_prep set
-	 * rq_data_dir the flags to READ.
-	 */
-	if (cmd->sc_data_direction == DMA_TO_DEVICE)
-		cmd->request->cmd_flags |= REQ_RW;
-	else
-		cmd->request->cmd_flags &= ~REQ_RW;
-
 	scsi_unmap_user_pages(tcmd);
 	scsi_host_put_command(scsi_tgt_cmd_to_host(cmd), cmd);
 }
@@ -215,6 +192,7 @@
 	struct list_head *head;
 
 	tcmd->tag = tag;
+	tcmd->bio = NULL;
 	INIT_WORK(&tcmd->work, scsi_tgt_cmd_destroy);
 	spin_lock_irqsave(&qdata->cmd_hash_lock, flags);
 	head = &qdata->cmd_hash[cmd_hashfn(tag)];
@@ -349,10 +327,14 @@
 	dprintk("cmd %p %lu\n", cmd, rq_data_dir(cmd->request));
 
 	scsi_tgt_uspace_send_status(cmd, tcmd->tag);
+
+	if (cmd->request_buffer)
+		scsi_free_sgtable(cmd->request_buffer, cmd->sglist_len);
+
 	queue_work(scsi_tgtd, &tcmd->work);
 }
 
-static int __scsi_tgt_transfer_response(struct scsi_cmnd *cmd)
+static int scsi_tgt_transfer_response(struct scsi_cmnd *cmd)
 {
 	struct Scsi_Host *shost = scsi_tgt_cmd_to_host(cmd);
 	int err;
@@ -365,30 +347,12 @@
 	case SCSI_MLQUEUE_DEVICE_BUSY:
 		return -EAGAIN;
 	}
-
 	return 0;
 }
 
-static void scsi_tgt_transfer_response(struct scsi_cmnd *cmd)
-{
-	struct scsi_tgt_cmd *tcmd = cmd->request->end_io_data;
-	int err;
-
-	err = __scsi_tgt_transfer_response(cmd);
-	if (!err)
-		return;
-
-	cmd->result = DID_BUS_BUSY << 16;
-	err = scsi_tgt_uspace_send_status(cmd, tcmd->tag);
-	if (err <= 0)
-		/* the eh will have to pick this up */
-		printk(KERN_ERR "Could not send cmd %p status\n", cmd);
-}
-
 static int scsi_tgt_init_cmd(struct scsi_cmnd *cmd, gfp_t gfp_mask)
 {
 	struct request *rq = cmd->request;
-	struct scsi_tgt_cmd *tcmd = rq->end_io_data;
 	int count;
 
 	cmd->use_sg = rq->nr_phys_segments;
@@ -398,143 +362,54 @@
 
 	cmd->request_bufflen = rq->data_len;
 
-	dprintk("cmd %p addr %p cnt %d %lu\n", cmd, tcmd->buffer, cmd->use_sg,
-		rq_data_dir(rq));
+	dprintk("cmd %p cnt %d %lu\n", cmd, cmd->use_sg, rq_data_dir(rq));
 	count = blk_rq_map_sg(rq->q, rq, cmd->request_buffer);
 	if (likely(count <= cmd->use_sg)) {
 		cmd->use_sg = count;
 		return 0;
 	}
 
-	eprintk("cmd %p addr %p cnt %d\n", cmd, tcmd->buffer, cmd->use_sg);
+	eprintk("cmd %p cnt %d\n", cmd, cmd->use_sg);
 	scsi_free_sgtable(cmd->request_buffer, cmd->sglist_len);
 	return -EINVAL;
 }
 
 /* TODO: test this crap and replace bio_map_user with new interface maybe */
 static int scsi_map_user_pages(struct scsi_tgt_cmd *tcmd, struct scsi_cmnd *cmd,
-			       int rw)
+			       unsigned long uaddr, unsigned int len, int rw)
 {
 	struct request_queue *q = cmd->request->q;
 	struct request *rq = cmd->request;
-	void *uaddr = tcmd->buffer;
-	unsigned int len = tcmd->bufflen;
-	struct bio *bio;
 	int err;
 
-	while (len > 0) {
-		dprintk("%lx %u\n", (unsigned long) uaddr, len);
-		bio = bio_map_user(q, NULL, (unsigned long) uaddr, len, rw);
-		if (IS_ERR(bio)) {
-			err = PTR_ERR(bio);
-			dprintk("fail to map %lx %u %d %x\n",
-				(unsigned long) uaddr, len, err, cmd->cmnd[0]);
-			goto unmap_bios;
-		}
-
-		uaddr += bio->bi_size;
-		len -= bio->bi_size;
-
+	dprintk("%lx %u\n", uaddr, len);
+	err = blk_rq_map_user(q, rq, (void *)uaddr, len);
+	if (err) {
 		/*
-		 * The first bio is added and merged. We could probably
-		 * try to add others using scsi_merge_bio() but for now
-		 * we keep it simple. The first bio should be pretty large
-		 * (either hitting the 1 MB bio pages limit or a queue limit)
-		 * already but for really large IO we may want to try and
-		 * merge these.
+		 * TODO: need to fixup sg_tablesize, max_segment_size,
+		 * max_sectors, etc for modern HW and software drivers
+		 * where this value is bogus.
+		 *
+		 * TODO2: we can alloc a reserve buffer of max size
+		 * we can handle and do the slow copy path for really large
+		 * IO.
 		 */
-		if (!rq->bio) {
-			blk_rq_bio_prep(q, rq, bio);
-			rq->data_len = bio->bi_size;
-		} else
-			/* put list of bios to transfer in next go around */
-			bio_list_add(&tcmd->xfer_list, bio);
+		eprintk("Could not handle request of size %u.\n", len);
+		return err;
 	}
 
-	cmd->offset = 0;
+	tcmd->bio = rq->bio;
 	err = scsi_tgt_init_cmd(cmd, GFP_KERNEL);
 	if (err)
-		goto unmap_bios;
+		goto unmap_rq;
 
 	return 0;
 
-unmap_bios:
-	if (rq->bio) {
-		bio_unmap_user(rq->bio);
-		while ((bio = bio_list_pop(&tcmd->xfer_list)))
-			bio_unmap_user(bio);
-	}
-
+unmap_rq:
+	scsi_unmap_user_pages(tcmd);
 	return err;
 }
 
-static int scsi_tgt_transfer_data(struct scsi_cmnd *);
-
-static void scsi_tgt_data_transfer_done(struct scsi_cmnd *cmd)
-{
-	struct scsi_tgt_cmd *tcmd = cmd->request->end_io_data;
-	struct bio *bio;
-	int err;
-
-	/* should we free resources here on error ? */
-	if (cmd->result) {
-send_uspace_err:
-		err = scsi_tgt_uspace_send_status(cmd, tcmd->tag);
-		if (err <= 0)
-			/* the tgt uspace eh will have to pick this up */
-			printk(KERN_ERR "Could not send cmd %p status\n", cmd);
-		return;
-	}
-
-	dprintk("cmd %p request_bufflen %u bufflen %u\n",
-		cmd, cmd->request_bufflen, tcmd->bufflen);
-
-	scsi_free_sgtable(cmd->request_buffer, cmd->sglist_len);
-	bio_list_add(&tcmd->xfer_done_list, cmd->request->bio);
-
-	tcmd->buffer += cmd->request_bufflen;
-	cmd->offset += cmd->request_bufflen;
-
-	if (!tcmd->xfer_list.head) {
-		scsi_tgt_transfer_response(cmd);
-		return;
-	}
-
-	dprintk("cmd2 %p request_bufflen %u bufflen %u\n",
-		cmd, cmd->request_bufflen, tcmd->bufflen);
-
-	bio = bio_list_pop(&tcmd->xfer_list);
-	BUG_ON(!bio);
-
-	blk_rq_bio_prep(cmd->request->q, cmd->request, bio);
-	cmd->request->data_len = bio->bi_size;
-	err = scsi_tgt_init_cmd(cmd, GFP_ATOMIC);
-	if (err) {
-		cmd->result = DID_ERROR << 16;
-		goto send_uspace_err;
-	}
-
-	if (scsi_tgt_transfer_data(cmd)) {
-		cmd->result = DID_NO_CONNECT << 16;
-		goto send_uspace_err;
-	}
-}
-
-static int scsi_tgt_transfer_data(struct scsi_cmnd *cmd)
-{
-	int err;
-	struct Scsi_Host *host = scsi_tgt_cmd_to_host(cmd);
-
-	err = host->hostt->transfer_data(cmd, scsi_tgt_data_transfer_done);
-	switch (err) {
-		case SCSI_MLQUEUE_HOST_BUSY:
-		case SCSI_MLQUEUE_DEVICE_BUSY:
-			return -EAGAIN;
-	default:
-		return 0;
-	}
-}
-
 static int scsi_tgt_copy_sense(struct scsi_cmnd *cmd, unsigned long uaddr,
 				unsigned len)
 {
@@ -584,8 +459,9 @@
 	return rq;
 }
 
-int scsi_tgt_kspace_exec(int host_no, u64 tag, int result, u32 len,
-			 unsigned long uaddr, u8 rw)
+int scsi_tgt_kspace_exec(int host_no, int result, u64 tag,
+			 unsigned long uaddr, u32 len, unsigned long sense_uaddr,
+			 u32 sense_len, u8 rw)
 {
 	struct Scsi_Host *shost;
 	struct scsi_cmnd *cmd;
@@ -617,8 +493,9 @@
 	}
 	cmd = rq->special;
 
-	dprintk("cmd %p result %d len %d bufflen %u %lu %x\n", cmd,
-		result, len, cmd->request_bufflen, rq_data_dir(rq), cmd->cmnd[0]);
+	dprintk("cmd %p scb %x result %d len %d bufflen %u %lu %x\n",
+		cmd, cmd->cmnd[0], result, len, cmd->request_bufflen,
+		rq_data_dir(rq), cmd->cmnd[0]);
 
 	if (result == TASK_ABORTED) {
 		scsi_tgt_abort_cmd(shost, cmd);
@@ -629,36 +506,36 @@
 	 * in the request_* values
 	 */
 	tcmd = cmd->request->end_io_data;
-	tcmd->buffer = (void *)uaddr;
-	tcmd->bufflen = len;
 	cmd->result = result;
 
-	if (!tcmd->bufflen || cmd->request_buffer) {
-		err = __scsi_tgt_transfer_response(cmd);
-		goto done;
-	}
+	if (cmd->result == SAM_STAT_CHECK_CONDITION)
+		scsi_tgt_copy_sense(cmd, sense_uaddr, sense_len);
 
-	/*
-	 * TODO: Do we need to handle case where request does not
-	 * align with LLD.
-	 */
-	err = scsi_map_user_pages(rq->end_io_data, cmd, rw);
-	if (err) {
-		eprintk("%p %d\n", cmd, err);
-		err = -EAGAIN;
-		goto done;
-	}
+	if (len) {
+		err = scsi_map_user_pages(rq->end_io_data, cmd, uaddr, len, rw);
+		if (err) {
+			/*
+			 * user-space daemon bugs or OOM
+			 * TODO: we can do better for OOM.
+			 */
+			struct scsi_tgt_queuedata *qdata;
+			struct list_head *head;
+			unsigned long flags;
 
-	/* userspace failure */
-	if (cmd->result) {
-		if (status_byte(cmd->result) == CHECK_CONDITION)
-			scsi_tgt_copy_sense(cmd, uaddr, len);
-		err = __scsi_tgt_transfer_response(cmd);
-		goto done;
-	}
-	/* ask the target LLD to transfer the data to the buffer */
-	err = scsi_tgt_transfer_data(cmd);
+			eprintk("cmd %p ret %d uaddr %lx len %d rw %d\n",
+				cmd, err, uaddr, len, rw);
 
+			qdata = shost->uspace_req_q->queuedata;
+			head = &qdata->cmd_hash[cmd_hashfn(tcmd->tag)];
+
+			spin_lock_irqsave(&qdata->cmd_hash_lock, flags);
+			list_add(&tcmd->hash_list, head);
+			spin_unlock_irqrestore(&qdata->cmd_hash_lock, flags);
+
+			goto done;
+		}
+	}
+	err = scsi_tgt_transfer_response(cmd);
 done:
 	scsi_host_put(shost);
 	return err;
diff --git a/drivers/scsi/scsi_tgt_priv.h b/drivers/scsi/scsi_tgt_priv.h
index 84488c5..e9e6db1 100644
--- a/drivers/scsi/scsi_tgt_priv.h
+++ b/drivers/scsi/scsi_tgt_priv.h
@@ -18,8 +18,9 @@
 extern int scsi_tgt_uspace_send_cmd(struct scsi_cmnd *cmd, struct scsi_lun *lun,
 				    u64 tag);
 extern int scsi_tgt_uspace_send_status(struct scsi_cmnd *cmd, u64 tag);
-extern int scsi_tgt_kspace_exec(int host_no, u64 tag, int result, u32 len,
-				unsigned long uaddr, u8 rw);
+extern int scsi_tgt_kspace_exec(int host_no, int result, u64 tag,
+				unsigned long uaddr, u32 len, unsigned long sense_uaddr,
+				u32 sense_len, u8 rw);
 extern int scsi_tgt_uspace_send_tsk_mgmt(int host_no, int function, u64 tag,
 					 struct scsi_lun *scsilun, void *data);
 extern int scsi_tgt_kspace_tsk_mgmt(int host_no, u64 mid, int result);
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
index 58afdb4..14c4f06 100644
--- a/drivers/scsi/scsi_transport_fc.c
+++ b/drivers/scsi/scsi_transport_fc.c
@@ -200,6 +200,8 @@
 	{ FC_PORTSPEED_2GBIT,		"2 Gbit" },
 	{ FC_PORTSPEED_4GBIT,		"4 Gbit" },
 	{ FC_PORTSPEED_10GBIT,		"10 Gbit" },
+	{ FC_PORTSPEED_8GBIT,		"8 Gbit" },
+	{ FC_PORTSPEED_16GBIT,		"16 Gbit" },
 	{ FC_PORTSPEED_NOT_NEGOTIATED,	"Not Negotiated" },
 };
 fc_bitfield_name_search(port_speed, fc_port_speed_names)
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
index aabaa05..caf1836 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -49,7 +49,7 @@
 	struct class_device_attribute *session_attrs[ISCSI_SESSION_ATTRS + 1];
 };
 
-static int iscsi_session_nr;	/* sysfs session id for next new session */
+static atomic_t iscsi_session_nr; /* sysfs session id for next new session */
 
 /*
  * list of registered transports and lock that must
@@ -300,7 +300,7 @@
 	int err;
 
 	ihost = shost->shost_data;
-	session->sid = iscsi_session_nr++;
+	session->sid = atomic_add_return(1, &iscsi_session_nr);
 	session->target_id = target_id;
 
 	snprintf(session->dev.bus_id, BUS_ID_SIZE, "session%u",
@@ -1419,6 +1419,8 @@
 	printk(KERN_INFO "Loading iSCSI transport class v%s.\n",
 		ISCSI_TRANSPORT_VERSION);
 
+	atomic_set(&iscsi_session_nr, 0);
+
 	err = class_register(&iscsi_transport_class);
 	if (err)
 		return err;
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 5a8f55f..00e4666 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -58,16 +58,10 @@
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_ioctl.h>
 #include <scsi/scsicam.h>
+#include <scsi/sd.h>
 
 #include "scsi_logging.h"
 
-/*
- * More than enough for everybody ;)  The huge number of majors
- * is a leftover from 16bit dev_t days, we don't really need that
- * much numberspace.
- */
-#define SD_MAJORS	16
-
 MODULE_AUTHOR("Eric Youngdale");
 MODULE_DESCRIPTION("SCSI disk (sd) driver");
 MODULE_LICENSE("GPL");
@@ -88,45 +82,9 @@
 MODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK13_MAJOR);
 MODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK14_MAJOR);
 MODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK15_MAJOR);
-
-/*
- * This is limited by the naming scheme enforced in sd_probe,
- * add another character to it if you really need more disks.
- */
-#define SD_MAX_DISKS	(((26 * 26) + 26 + 1) * 26)
-
-/*
- * Time out in seconds for disks and Magneto-opticals (which are slower).
- */
-#define SD_TIMEOUT		(30 * HZ)
-#define SD_MOD_TIMEOUT		(75 * HZ)
-
-/*
- * Number of allowed retries
- */
-#define SD_MAX_RETRIES		5
-#define SD_PASSTHROUGH_RETRIES	1
-
-/*
- * Size of the initial data buffer for mode and read capacity data
- */
-#define SD_BUF_SIZE		512
-
-struct scsi_disk {
-	struct scsi_driver *driver;	/* always &sd_template */
-	struct scsi_device *device;
-	struct class_device cdev;
-	struct gendisk	*disk;
-	unsigned int	openers;	/* protected by BKL for now, yuck */
-	sector_t	capacity;	/* size in 512-byte sectors */
-	u32		index;
-	u8		media_present;
-	u8		write_prot;
-	unsigned	WCE : 1;	/* state of disk WCE bit */
-	unsigned	RCD : 1;	/* state of disk RCD bit, unused */
-	unsigned	DPOFUA : 1;	/* state of disk DPOFUA bit */
-};
-#define to_scsi_disk(obj) container_of(obj,struct scsi_disk,cdev)
+MODULE_ALIAS_SCSI_DEVICE(TYPE_DISK);
+MODULE_ALIAS_SCSI_DEVICE(TYPE_MOD);
+MODULE_ALIAS_SCSI_DEVICE(TYPE_RBC);
 
 static DEFINE_IDR(sd_index_idr);
 static DEFINE_SPINLOCK(sd_index_lock);
@@ -136,20 +94,6 @@
  * object after last put) */
 static DEFINE_MUTEX(sd_ref_mutex);
 
-static int sd_revalidate_disk(struct gendisk *disk);
-static void sd_rw_intr(struct scsi_cmnd * SCpnt);
-
-static int sd_probe(struct device *);
-static int sd_remove(struct device *);
-static void sd_shutdown(struct device *dev);
-static void sd_rescan(struct device *);
-static int sd_init_command(struct scsi_cmnd *);
-static int sd_issue_flush(struct device *, sector_t *);
-static void sd_prepare_flush(request_queue_t *, struct request *);
-static void sd_read_capacity(struct scsi_disk *sdkp, char *diskname,
-			     unsigned char *buffer);
-static void scsi_disk_release(struct class_device *cdev);
-
 static const char *sd_cache_types[] = {
 	"write through", "none", "write back",
 	"write back, no read (daft)"
@@ -199,13 +143,27 @@
 	if (scsi_mode_select(sdp, 1, sp, 8, buffer_data, len, SD_TIMEOUT,
 			     SD_MAX_RETRIES, &data, &sshdr)) {
 		if (scsi_sense_valid(&sshdr))
-			scsi_print_sense_hdr(sdkp->disk->disk_name, &sshdr);
+			sd_print_sense_hdr(sdkp, &sshdr);
 		return -EINVAL;
 	}
 	sd_revalidate_disk(sdkp->disk);
 	return count;
 }
 
+static ssize_t sd_store_manage_start_stop(struct class_device *cdev,
+					  const char *buf, size_t count)
+{
+	struct scsi_disk *sdkp = to_scsi_disk(cdev);
+	struct scsi_device *sdp = sdkp->device;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EACCES;
+
+	sdp->manage_start_stop = simple_strtoul(buf, NULL, 10);
+
+	return count;
+}
+
 static ssize_t sd_store_allow_restart(struct class_device *cdev, const char *buf,
 				      size_t count)
 {
@@ -238,6 +196,14 @@
 	return snprintf(buf, 20, "%u\n", sdkp->DPOFUA);
 }
 
+static ssize_t sd_show_manage_start_stop(struct class_device *cdev, char *buf)
+{
+	struct scsi_disk *sdkp = to_scsi_disk(cdev);
+	struct scsi_device *sdp = sdkp->device;
+
+	return snprintf(buf, 20, "%u\n", sdp->manage_start_stop);
+}
+
 static ssize_t sd_show_allow_restart(struct class_device *cdev, char *buf)
 {
 	struct scsi_disk *sdkp = to_scsi_disk(cdev);
@@ -251,6 +217,8 @@
 	__ATTR(FUA, S_IRUGO, sd_show_fua, NULL),
 	__ATTR(allow_restart, S_IRUGO|S_IWUSR, sd_show_allow_restart,
 	       sd_store_allow_restart),
+	__ATTR(manage_start_stop, S_IRUGO|S_IWUSR, sd_show_manage_start_stop,
+	       sd_store_manage_start_stop),
 	__ATTR_NULL,
 };
 
@@ -267,6 +235,8 @@
 		.name		= "sd",
 		.probe		= sd_probe,
 		.remove		= sd_remove,
+		.suspend	= sd_suspend,
+		.resume		= sd_resume,
 		.shutdown	= sd_shutdown,
 	},
 	.rescan			= sd_rescan,
@@ -371,15 +341,19 @@
 	unsigned int this_count = SCpnt->request_bufflen >> 9;
 	unsigned int timeout = sdp->timeout;
 
-	SCSI_LOG_HLQUEUE(1, printk("sd_init_command: disk=%s, block=%llu, "
-			    "count=%d\n", disk->disk_name,
-			 (unsigned long long)block, this_count));
+	SCSI_LOG_HLQUEUE(1, scmd_printk(KERN_INFO, SCpnt,
+					"sd_init_command: block=%llu, "
+					"count=%d\n",
+					(unsigned long long)block,
+					this_count));
 
 	if (!sdp || !scsi_device_online(sdp) ||
  	    block + rq->nr_sectors > get_capacity(disk)) {
-		SCSI_LOG_HLQUEUE(2, printk("Finishing %ld sectors\n", 
-				 rq->nr_sectors));
-		SCSI_LOG_HLQUEUE(2, printk("Retry with 0x%p\n", SCpnt));
+		SCSI_LOG_HLQUEUE(2, scmd_printk(KERN_INFO, SCpnt,
+						"Finishing %ld sectors\n",
+						rq->nr_sectors));
+		SCSI_LOG_HLQUEUE(2, scmd_printk(KERN_INFO, SCpnt,
+						"Retry with 0x%p\n", SCpnt));
 		return 0;
 	}
 
@@ -391,8 +365,8 @@
 		/* printk("SCSI disk has been changed. Prohibiting further I/O.\n"); */
 		return 0;
 	}
-	SCSI_LOG_HLQUEUE(2, printk("%s : block=%llu\n",
-				   disk->disk_name, (unsigned long long)block));
+	SCSI_LOG_HLQUEUE(2, scmd_printk(KERN_INFO, SCpnt, "block=%llu\n",
+					(unsigned long long)block));
 
 	/*
 	 * If we have a 1K hardware sectorsize, prevent access to single
@@ -407,7 +381,8 @@
 	 */
 	if (sdp->sector_size == 1024) {
 		if ((block & 1) || (rq->nr_sectors & 1)) {
-			printk(KERN_ERR "sd: Bad block number requested");
+			scmd_printk(KERN_ERR, SCpnt,
+				    "Bad block number requested\n");
 			return 0;
 		} else {
 			block = block >> 1;
@@ -416,7 +391,8 @@
 	}
 	if (sdp->sector_size == 2048) {
 		if ((block & 3) || (rq->nr_sectors & 3)) {
-			printk(KERN_ERR "sd: Bad block number requested");
+			scmd_printk(KERN_ERR, SCpnt,
+				    "Bad block number requested\n");
 			return 0;
 		} else {
 			block = block >> 2;
@@ -425,7 +401,8 @@
 	}
 	if (sdp->sector_size == 4096) {
 		if ((block & 7) || (rq->nr_sectors & 7)) {
-			printk(KERN_ERR "sd: Bad block number requested");
+			scmd_printk(KERN_ERR, SCpnt,
+				    "Bad block number requested\n");
 			return 0;
 		} else {
 			block = block >> 3;
@@ -442,13 +419,15 @@
 		SCpnt->cmnd[0] = READ_6;
 		SCpnt->sc_data_direction = DMA_FROM_DEVICE;
 	} else {
-		printk(KERN_ERR "sd: Unknown command %x\n", rq->cmd_flags);
+		scmd_printk(KERN_ERR, SCpnt, "Unknown command %x\n", rq->cmd_flags);
 		return 0;
 	}
 
-	SCSI_LOG_HLQUEUE(2, printk("%s : %s %d/%ld 512 byte blocks.\n", 
-		disk->disk_name, (rq_data_dir(rq) == WRITE) ? 
-		"writing" : "reading", this_count, rq->nr_sectors));
+	SCSI_LOG_HLQUEUE(2, scmd_printk(KERN_INFO, SCpnt,
+					"%s %d/%ld 512 byte blocks.\n",
+					(rq_data_dir(rq) == WRITE) ?
+					"writing" : "reading", this_count,
+					rq->nr_sectors));
 
 	SCpnt->cmnd[1] = 0;
 	
@@ -490,7 +469,8 @@
 			 * during operation and thus turned off
 			 * use_10_for_rw.
 			 */
-			printk(KERN_ERR "sd: FUA write on READ/WRITE(6) drive\n");
+			scmd_printk(KERN_ERR, SCpnt,
+				    "FUA write on READ/WRITE(6) drive\n");
 			return 0;
 		}
 
@@ -549,7 +529,7 @@
 		return -ENXIO;
 
 
-	SCSI_LOG_HLQUEUE(3, printk("sd_open: disk=%s\n", disk->disk_name));
+	SCSI_LOG_HLQUEUE(3, sd_printk(KERN_INFO, sdkp, "sd_open\n"));
 
 	sdev = sdkp->device;
 
@@ -619,7 +599,7 @@
 	struct scsi_disk *sdkp = scsi_disk(disk);
 	struct scsi_device *sdev = sdkp->device;
 
-	SCSI_LOG_HLQUEUE(3, printk("sd_release: disk=%s\n", disk->disk_name));
+	SCSI_LOG_HLQUEUE(3, sd_printk(KERN_INFO, sdkp, "sd_release\n"));
 
 	if (!--sdkp->openers && sdev->removable) {
 		if (scsi_block_when_processing_errors(sdev))
@@ -732,8 +712,7 @@
 	struct scsi_device *sdp = sdkp->device;
 	int retval;
 
-	SCSI_LOG_HLQUEUE(3, printk("sd_media_changed: disk=%s\n",
-						disk->disk_name));
+	SCSI_LOG_HLQUEUE(3, sd_printk(KERN_INFO, sdkp, "sd_media_changed\n"));
 
 	if (!sdp->removable)
 		return 0;
@@ -786,9 +765,10 @@
 	return 1;
 }
 
-static int sd_sync_cache(struct scsi_device *sdp)
+static int sd_sync_cache(struct scsi_disk *sdkp)
 {
 	int retries, res;
+	struct scsi_device *sdp = sdkp->device;
 	struct scsi_sense_hdr sshdr;
 
 	if (!scsi_device_online(sdp))
@@ -809,28 +789,27 @@
 			break;
 	}
 
-	if (res) {		printk(KERN_WARNING "FAILED\n  status = %x, message = %02x, "
-				    "host = %d, driver = %02x\n  ",
-				    status_byte(res), msg_byte(res),
-				    host_byte(res), driver_byte(res));
-			if (driver_byte(res) & DRIVER_SENSE)
-				scsi_print_sense_hdr("sd", &sshdr);
+	if (res) {
+		sd_print_result(sdkp, res);
+		if (driver_byte(res) & DRIVER_SENSE)
+			sd_print_sense_hdr(sdkp, &sshdr);
 	}
 
-	return res;
+	if (res)
+		return -EIO;
+	return 0;
 }
 
 static int sd_issue_flush(struct device *dev, sector_t *error_sector)
 {
 	int ret = 0;
-	struct scsi_device *sdp = to_scsi_device(dev);
 	struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev);
 
 	if (!sdkp)
                return -ENODEV;
 
 	if (sdkp->WCE)
-		ret = sd_sync_cache(sdp);
+		ret = sd_sync_cache(sdkp);
 	scsi_disk_put(sdkp);
 	return ret;
 }
@@ -928,12 +907,14 @@
 			sense_deferred = scsi_sense_is_deferred(&sshdr);
 	}
 #ifdef CONFIG_SCSI_LOGGING
-	SCSI_LOG_HLCOMPLETE(1, printk("sd_rw_intr: %s: res=0x%x\n", 
-				SCpnt->request->rq_disk->disk_name, result));
+	SCSI_LOG_HLCOMPLETE(1, scsi_print_result(SCpnt));
 	if (sense_valid) {
-		SCSI_LOG_HLCOMPLETE(1, printk("sd_rw_intr: sb[respc,sk,asc,"
-				"ascq]=%x,%x,%x,%x\n", sshdr.response_code,
-				sshdr.sense_key, sshdr.asc, sshdr.ascq));
+		SCSI_LOG_HLCOMPLETE(1, scmd_printk(KERN_INFO, SCpnt,
+						   "sd_rw_intr: sb[respc,sk,asc,"
+						   "ascq]=%x,%x,%x,%x\n",
+						   sshdr.response_code,
+						   sshdr.sense_key, sshdr.asc,
+						   sshdr.ascq));
 	}
 #endif
 	if (driver_byte(result) != DRIVER_SENSE &&
@@ -1025,7 +1006,7 @@
  * spinup disk - called only in sd_revalidate_disk()
  */
 static void
-sd_spinup_disk(struct scsi_disk *sdkp, char *diskname)
+sd_spinup_disk(struct scsi_disk *sdkp)
 {
 	unsigned char cmd[10];
 	unsigned long spintime_expire = 0;
@@ -1069,9 +1050,10 @@
 		if ((driver_byte(the_result) & DRIVER_SENSE) == 0) {
 			/* no sense, TUR either succeeded or failed
 			 * with a status error */
-			if(!spintime && !scsi_status_is_good(the_result))
-				printk(KERN_NOTICE "%s: Unit Not Ready, "
-				       "error = 0x%x\n", diskname, the_result);
+			if(!spintime && !scsi_status_is_good(the_result)) {
+				sd_printk(KERN_NOTICE, sdkp, "Unit Not Ready\n");
+				sd_print_result(sdkp, the_result);
+			}
 			break;
 		}
 					
@@ -1096,8 +1078,7 @@
 		 */
 		} else if (sense_valid && sshdr.sense_key == NOT_READY) {
 			if (!spintime) {
-				printk(KERN_NOTICE "%s: Spinning up disk...",
-				       diskname);
+				sd_printk(KERN_NOTICE, sdkp, "Spinning up disk...");
 				cmd[0] = START_STOP;
 				cmd[1] = 1;	/* Return immediately */
 				memset((void *) &cmd[2], 0, 8);
@@ -1130,9 +1111,8 @@
 			/* we don't understand the sense code, so it's
 			 * probably pointless to loop */
 			if(!spintime) {
-				printk(KERN_NOTICE "%s: Unit Not Ready, "
-					"sense:\n", diskname);
-				scsi_print_sense_hdr("", &sshdr);
+				sd_printk(KERN_NOTICE, sdkp, "Unit Not Ready\n");
+				sd_print_sense_hdr(sdkp, &sshdr);
 			}
 			break;
 		}
@@ -1151,8 +1131,7 @@
  * read disk capacity
  */
 static void
-sd_read_capacity(struct scsi_disk *sdkp, char *diskname,
-		 unsigned char *buffer)
+sd_read_capacity(struct scsi_disk *sdkp, unsigned char *buffer)
 {
 	unsigned char cmd[16];
 	int the_result, retries;
@@ -1191,18 +1170,12 @@
 	} while (the_result && retries);
 
 	if (the_result && !longrc) {
-		printk(KERN_NOTICE "%s : READ CAPACITY failed.\n"
-		       "%s : status=%x, message=%02x, host=%d, driver=%02x \n",
-		       diskname, diskname,
-		       status_byte(the_result),
-		       msg_byte(the_result),
-		       host_byte(the_result),
-		       driver_byte(the_result));
-
+		sd_printk(KERN_NOTICE, sdkp, "READ CAPACITY failed\n");
+		sd_print_result(sdkp, the_result);
 		if (driver_byte(the_result) & DRIVER_SENSE)
-			scsi_print_sense_hdr("sd", &sshdr);
+			sd_print_sense_hdr(sdkp, &sshdr);
 		else
-			printk("%s : sense not available. \n", diskname);
+			sd_printk(KERN_NOTICE, sdkp, "Sense not available.\n");
 
 		/* Set dirty bit for removable devices if not ready -
 		 * sometimes drives will not report this properly. */
@@ -1218,16 +1191,10 @@
 		return;
 	} else if (the_result && longrc) {
 		/* READ CAPACITY(16) has been failed */
-		printk(KERN_NOTICE "%s : READ CAPACITY(16) failed.\n"
-		       "%s : status=%x, message=%02x, host=%d, driver=%02x \n",
-		       diskname, diskname,
-		       status_byte(the_result),
-		       msg_byte(the_result),
-		       host_byte(the_result),
-		       driver_byte(the_result));
-		printk(KERN_NOTICE "%s : use 0xffffffff as device size\n",
-		       diskname);
-		
+		sd_printk(KERN_NOTICE, sdkp, "READ CAPACITY(16) failed\n");
+		sd_print_result(sdkp, the_result);
+		sd_printk(KERN_NOTICE, sdkp, "Use 0xffffffff as device size\n");
+
 		sdkp->capacity = 1 + (sector_t) 0xffffffff;		
 		goto got_data;
 	}	
@@ -1238,14 +1205,14 @@
 		if (buffer[0] == 0xff && buffer[1] == 0xff &&
 		    buffer[2] == 0xff && buffer[3] == 0xff) {
 			if(sizeof(sdkp->capacity) > 4) {
-				printk(KERN_NOTICE "%s : very big device. try to use"
-				       " READ CAPACITY(16).\n", diskname);
+				sd_printk(KERN_NOTICE, sdkp, "Very big device. "
+					  "Trying to use READ CAPACITY(16).\n");
 				longrc = 1;
 				goto repeat;
 			}
-			printk(KERN_ERR "%s: too big for this kernel.  Use a "
-			       "kernel compiled with support for large block "
-			       "devices.\n", diskname);
+			sd_printk(KERN_ERR, sdkp, "Too big for this kernel. Use "
+				  "a kernel compiled with support for large "
+				  "block devices.\n");
 			sdkp->capacity = 0;
 			goto got_data;
 		}
@@ -1284,8 +1251,8 @@
 got_data:
 	if (sector_size == 0) {
 		sector_size = 512;
-		printk(KERN_NOTICE "%s : sector size 0 reported, "
-		       "assuming 512.\n", diskname);
+		sd_printk(KERN_NOTICE, sdkp, "Sector size 0 reported, "
+			  "assuming 512.\n");
 	}
 
 	if (sector_size != 512 &&
@@ -1293,8 +1260,8 @@
 	    sector_size != 2048 &&
 	    sector_size != 4096 &&
 	    sector_size != 256) {
-		printk(KERN_NOTICE "%s : unsupported sector size "
-		       "%d.\n", diskname, sector_size);
+		sd_printk(KERN_NOTICE, sdkp, "Unsupported sector size %d.\n",
+			  sector_size);
 		/*
 		 * The user might want to re-format the drive with
 		 * a supported sectorsize.  Once this happens, it
@@ -1327,10 +1294,10 @@
 		mb -= sz - 974;
 		sector_div(mb, 1950);
 
-		printk(KERN_NOTICE "SCSI device %s: "
-		       "%llu %d-byte hdwr sectors (%llu MB)\n",
-		       diskname, (unsigned long long)sdkp->capacity,
-		       hard_sector, (unsigned long long)mb);
+		sd_printk(KERN_NOTICE, sdkp,
+			  "%llu %d-byte hardware sectors (%llu MB)\n",
+			  (unsigned long long)sdkp->capacity,
+			  hard_sector, (unsigned long long)mb);
 	}
 
 	/* Rescale capacity to 512-byte units */
@@ -1362,8 +1329,7 @@
  * called with buffer of length SD_BUF_SIZE
  */
 static void
-sd_read_write_protect_flag(struct scsi_disk *sdkp, char *diskname,
-			   unsigned char *buffer)
+sd_read_write_protect_flag(struct scsi_disk *sdkp, unsigned char *buffer)
 {
 	int res;
 	struct scsi_device *sdp = sdkp->device;
@@ -1371,7 +1337,7 @@
 
 	set_disk_ro(sdkp->disk, 0);
 	if (sdp->skip_ms_page_3f) {
-		printk(KERN_NOTICE "%s: assuming Write Enabled\n", diskname);
+		sd_printk(KERN_NOTICE, sdkp, "Assuming Write Enabled\n");
 		return;
 	}
 
@@ -1403,15 +1369,16 @@
 	}
 
 	if (!scsi_status_is_good(res)) {
-		printk(KERN_WARNING
-		       "%s: test WP failed, assume Write Enabled\n", diskname);
+		sd_printk(KERN_WARNING, sdkp,
+			  "Test WP failed, assume Write Enabled\n");
 	} else {
 		sdkp->write_prot = ((data.device_specific & 0x80) != 0);
 		set_disk_ro(sdkp->disk, sdkp->write_prot);
-		printk(KERN_NOTICE "%s: Write Protect is %s\n", diskname,
-		       sdkp->write_prot ? "on" : "off");
-		printk(KERN_DEBUG "%s: Mode Sense: %02x %02x %02x %02x\n",
-		       diskname, buffer[0], buffer[1], buffer[2], buffer[3]);
+		sd_printk(KERN_NOTICE, sdkp, "Write Protect is %s\n",
+			  sdkp->write_prot ? "on" : "off");
+		sd_printk(KERN_DEBUG, sdkp,
+			  "Mode Sense: %02x %02x %02x %02x\n",
+			  buffer[0], buffer[1], buffer[2], buffer[3]);
 	}
 }
 
@@ -1420,8 +1387,7 @@
  * called with buffer of length SD_BUF_SIZE
  */
 static void
-sd_read_cache_type(struct scsi_disk *sdkp, char *diskname,
-		   unsigned char *buffer)
+sd_read_cache_type(struct scsi_disk *sdkp, unsigned char *buffer)
 {
 	int len = 0, res;
 	struct scsi_device *sdp = sdkp->device;
@@ -1450,8 +1416,7 @@
 
 	if (!data.header_length) {
 		modepage = 6;
-		printk(KERN_ERR "%s: missing header in MODE_SENSE response\n",
-		       diskname);
+		sd_printk(KERN_ERR, sdkp, "Missing header in MODE_SENSE response\n");
 	}
 
 	/* that went OK, now ask for the proper length */
@@ -1478,13 +1443,12 @@
 		int offset = data.header_length + data.block_descriptor_length;
 
 		if (offset >= SD_BUF_SIZE - 2) {
-			printk(KERN_ERR "%s: malformed MODE SENSE response",
-				diskname);
+			sd_printk(KERN_ERR, sdkp, "Malformed MODE SENSE response\n");
 			goto defaults;
 		}
 
 		if ((buffer[offset] & 0x3f) != modepage) {
-			printk(KERN_ERR "%s: got wrong page\n", diskname);
+			sd_printk(KERN_ERR, sdkp, "Got wrong page\n");
 			goto defaults;
 		}
 
@@ -1498,14 +1462,13 @@
 
 		sdkp->DPOFUA = (data.device_specific & 0x10) != 0;
 		if (sdkp->DPOFUA && !sdkp->device->use_10_for_rw) {
-			printk(KERN_NOTICE "SCSI device %s: uses "
-			       "READ/WRITE(6), disabling FUA\n", diskname);
+			sd_printk(KERN_NOTICE, sdkp,
+				  "Uses READ/WRITE(6), disabling FUA\n");
 			sdkp->DPOFUA = 0;
 		}
 
-		printk(KERN_NOTICE "SCSI device %s: "
-		       "write cache: %s, read cache: %s, %s\n",
-		       diskname,
+		sd_printk(KERN_NOTICE, sdkp,
+		       "Write cache: %s, read cache: %s, %s\n",
 		       sdkp->WCE ? "enabled" : "disabled",
 		       sdkp->RCD ? "disabled" : "enabled",
 		       sdkp->DPOFUA ? "supports DPO and FUA"
@@ -1518,15 +1481,13 @@
 	if (scsi_sense_valid(&sshdr) &&
 	    sshdr.sense_key == ILLEGAL_REQUEST &&
 	    sshdr.asc == 0x24 && sshdr.ascq == 0x0)
-		printk(KERN_NOTICE "%s: cache data unavailable\n",
-		       diskname);	/* Invalid field in CDB */
+		/* Invalid field in CDB */
+		sd_printk(KERN_NOTICE, sdkp, "Cache data unavailable\n");
 	else
-		printk(KERN_ERR "%s: asking for cache data failed\n",
-		       diskname);
+		sd_printk(KERN_ERR, sdkp, "Asking for cache data failed\n");
 
 defaults:
-	printk(KERN_ERR "%s: assuming drive cache: write through\n",
-	       diskname);
+	sd_printk(KERN_ERR, sdkp, "Assuming drive cache: write through\n");
 	sdkp->WCE = 0;
 	sdkp->RCD = 0;
 	sdkp->DPOFUA = 0;
@@ -1544,7 +1505,8 @@
 	unsigned char *buffer;
 	unsigned ordered;
 
-	SCSI_LOG_HLQUEUE(3, printk("sd_revalidate_disk: disk=%s\n", disk->disk_name));
+	SCSI_LOG_HLQUEUE(3, sd_printk(KERN_INFO, sdkp,
+				      "sd_revalidate_disk\n"));
 
 	/*
 	 * If the device is offline, don't try and read capacity or any
@@ -1555,8 +1517,8 @@
 
 	buffer = kmalloc(SD_BUF_SIZE, GFP_KERNEL | __GFP_DMA);
 	if (!buffer) {
-		printk(KERN_WARNING "(sd_revalidate_disk:) Memory allocation "
-		       "failure.\n");
+		sd_printk(KERN_WARNING, sdkp, "sd_revalidate_disk: Memory "
+			  "allocation failure.\n");
 		goto out;
 	}
 
@@ -1568,16 +1530,16 @@
 	sdkp->WCE = 0;
 	sdkp->RCD = 0;
 
-	sd_spinup_disk(sdkp, disk->disk_name);
+	sd_spinup_disk(sdkp);
 
 	/*
 	 * Without media there is no reason to ask; moreover, some devices
 	 * react badly if we do.
 	 */
 	if (sdkp->media_present) {
-		sd_read_capacity(sdkp, disk->disk_name, buffer);
-		sd_read_write_protect_flag(sdkp, disk->disk_name, buffer);
-		sd_read_cache_type(sdkp, disk->disk_name, buffer);
+		sd_read_capacity(sdkp, buffer);
+		sd_read_write_protect_flag(sdkp, buffer);
+		sd_read_cache_type(sdkp, buffer);
 	}
 
 	/*
@@ -1709,8 +1671,8 @@
 	dev_set_drvdata(dev, sdkp);
 	add_disk(gd);
 
-	sdev_printk(KERN_NOTICE, sdp, "Attached scsi %sdisk %s\n",
-		    sdp->removable ? "removable " : "", gd->disk_name);
+	sd_printk(KERN_NOTICE, sdkp, "Attached SCSI %sdisk\n",
+		  sdp->removable ? "removable " : "");
 
 	return 0;
 
@@ -1774,6 +1736,31 @@
 	kfree(sdkp);
 }
 
+static int sd_start_stop_device(struct scsi_disk *sdkp, int start)
+{
+	unsigned char cmd[6] = { START_STOP };	/* START_VALID */
+	struct scsi_sense_hdr sshdr;
+	struct scsi_device *sdp = sdkp->device;
+	int res;
+
+	if (start)
+		cmd[4] |= 1;	/* START */
+
+	if (!scsi_device_online(sdp))
+		return -ENODEV;
+
+	res = scsi_execute_req(sdp, cmd, DMA_NONE, NULL, 0, &sshdr,
+			       SD_TIMEOUT, SD_MAX_RETRIES);
+	if (res) {
+		sd_printk(KERN_WARNING, sdkp, "START_STOP FAILED\n");
+		sd_print_result(sdkp, res);
+		if (driver_byte(res) & DRIVER_SENSE)
+			sd_print_sense_hdr(sdkp, &sshdr);
+	}
+
+	return res;
+}
+
 /*
  * Send a SYNCHRONIZE CACHE instruction down to the device through
  * the normal SCSI command structure.  Wait for the command to
@@ -1781,20 +1768,62 @@
  */
 static void sd_shutdown(struct device *dev)
 {
-	struct scsi_device *sdp = to_scsi_device(dev);
 	struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev);
 
 	if (!sdkp)
 		return;         /* this can happen */
 
 	if (sdkp->WCE) {
-		printk(KERN_NOTICE "Synchronizing SCSI cache for disk %s: \n",
-				sdkp->disk->disk_name);
-		sd_sync_cache(sdp);
+		sd_printk(KERN_NOTICE, sdkp, "Synchronizing SCSI cache\n");
+		sd_sync_cache(sdkp);
 	}
+
+	if (system_state != SYSTEM_RESTART && sdkp->device->manage_start_stop) {
+		sd_printk(KERN_NOTICE, sdkp, "Stopping disk\n");
+		sd_start_stop_device(sdkp, 0);
+	}
+
 	scsi_disk_put(sdkp);
 }
 
+static int sd_suspend(struct device *dev, pm_message_t mesg)
+{
+	struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev);
+	int ret;
+
+	if (!sdkp)
+		return 0;	/* this can happen */
+
+	if (sdkp->WCE) {
+		sd_printk(KERN_NOTICE, sdkp, "Synchronizing SCSI cache\n");
+		ret = sd_sync_cache(sdkp);
+		if (ret)
+			return ret;
+	}
+
+	if (mesg.event == PM_EVENT_SUSPEND &&
+	    sdkp->device->manage_start_stop) {
+		sd_printk(KERN_NOTICE, sdkp, "Stopping disk\n");
+		ret = sd_start_stop_device(sdkp, 0);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int sd_resume(struct device *dev)
+{
+	struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev);
+
+	if (!sdkp->device->manage_start_stop)
+		return 0;
+
+	sd_printk(KERN_NOTICE, sdkp, "Starting disk\n");
+
+	return sd_start_stop_device(sdkp, 1);
+}
+
 /**
  *	init_sd - entry point for this driver (both when built in or when
  *	a module).
@@ -1852,3 +1881,19 @@
 
 module_init(init_sd);
 module_exit(exit_sd);
+
+static void sd_print_sense_hdr(struct scsi_disk *sdkp,
+			       struct scsi_sense_hdr *sshdr)
+{
+	sd_printk(KERN_INFO, sdkp, "");
+	scsi_show_sense_hdr(sshdr);
+	sd_printk(KERN_INFO, sdkp, "");
+	scsi_show_extd_sense(sshdr->asc, sshdr->ascq);
+}
+
+static void sd_print_result(struct scsi_disk *sdkp, int result)
+{
+	sd_printk(KERN_INFO, sdkp, "");
+	scsi_show_result(result);
+}
+
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 81e3bc7..570977c 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -917,6 +917,8 @@
 			return result;
                 if (val < 0)
                         return -EINVAL;
+		val = min_t(int, val,
+				sdp->device->request_queue->max_sectors * 512);
 		if (val != sfp->reserve.bufflen) {
 			if (sg_res_in_use(sfp) || sfp->mmap_called)
 				return -EBUSY;
@@ -925,7 +927,8 @@
 		}
 		return 0;
 	case SG_GET_RESERVED_SIZE:
-		val = (int) sfp->reserve.bufflen;
+		val = min_t(int, sfp->reserve.bufflen,
+				sdp->device->request_queue->max_sectors * 512);
 		return put_user(val, ip);
 	case SG_SET_COMMAND_Q:
 		result = get_user(val, ip);
@@ -1061,6 +1064,9 @@
 		if (sdp->detached)
 			return -ENODEV;
 		return scsi_ioctl(sdp->device, cmd_in, p);
+	case BLKSECTGET:
+		return put_user(sdp->device->request_queue->max_sectors * 512,
+				ip);
 	default:
 		if (read_only)
 			return -EPERM;	/* don't know so take safe approach */
@@ -2339,6 +2345,7 @@
 {
 	Sg_fd *sfp;
 	unsigned long iflags;
+	int bufflen;
 
 	sfp = kzalloc(sizeof(*sfp), GFP_ATOMIC | __GFP_NOWARN);
 	if (!sfp)
@@ -2369,7 +2376,9 @@
 	if (unlikely(sg_big_buff != def_reserved_size))
 		sg_big_buff = def_reserved_size;
 
-	sg_build_reserve(sfp, sg_big_buff);
+	bufflen = min_t(int, sg_big_buff,
+			sdp->device->request_queue->max_sectors * 512);
+	sg_build_reserve(sfp, bufflen);
 	SCSI_LOG_TIMEOUT(3, printk("sg_add_sfp:   bufflen=%d, k_use_sg=%d\n",
 			   sfp->reserve.bufflen, sfp->reserve.k_use_sg));
 	return sfp;
diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
index 1857d68..f9a52af 100644
--- a/drivers/scsi/sr.c
+++ b/drivers/scsi/sr.c
@@ -62,6 +62,8 @@
 MODULE_DESCRIPTION("SCSI cdrom (sr) driver");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_CDROM_MAJOR);
+MODULE_ALIAS_SCSI_DEVICE(TYPE_ROM);
+MODULE_ALIAS_SCSI_DEVICE(TYPE_WORM);
 
 #define SR_DISKS	256
 
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index 98d8411..55bfecc 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -89,6 +89,7 @@
 MODULE_DESCRIPTION("SCSI tape (st) driver");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS_CHARDEV_MAJOR(SCSI_TAPE_MAJOR);
+MODULE_ALIAS_SCSI_DEVICE(TYPE_TAPE);
 
 /* Set 'perm' (4th argument) to 0 to disable module_param's definition
  * of sysfs parameters (which module_param doesn't yet support).
diff --git a/drivers/scsi/tmscsim.c b/drivers/scsi/tmscsim.c
index a583e89..3158949 100644
--- a/drivers/scsi/tmscsim.c
+++ b/drivers/scsi/tmscsim.c
@@ -2680,7 +2680,7 @@
 		printk (KERN_INFO "DC390: Using safe settings.\n");
 	}
 
-	return pci_module_init(&dc390_driver);
+	return pci_register_driver(&dc390_driver);
 }
 
 static void __exit dc390_module_exit(void)
diff --git a/drivers/usb/input/Makefile b/drivers/usb/input/Makefile
index 9bf420e..284a073 100644
--- a/drivers/usb/input/Makefile
+++ b/drivers/usb/input/Makefile
@@ -10,9 +10,6 @@
 obj-$(CONFIG_USB_ATI_REMOTE2)	+= ati_remote2.o
 obj-$(CONFIG_USB_KBTAB)		+= kbtab.o
 obj-$(CONFIG_USB_KEYSPAN_REMOTE)	+= keyspan_remote.o
-obj-$(CONFIG_USB_MTOUCH)	+= mtouchusb.o
-obj-$(CONFIG_USB_ITMTOUCH)	+= itmtouch.o
-obj-$(CONFIG_USB_EGALAX)	+= touchkitusb.o
 obj-$(CONFIG_USB_TOUCHSCREEN)	+= usbtouchscreen.o
 obj-$(CONFIG_USB_POWERMATE)	+= powermate.o
 obj-$(CONFIG_USB_WACOM)		+= wacom.o
@@ -20,7 +17,7 @@
 obj-$(CONFIG_USB_YEALINK)	+= yealink.o
 obj-$(CONFIG_USB_XPAD)		+= xpad.o
 obj-$(CONFIG_USB_APPLETOUCH)	+= appletouch.o
-obj-$(CONFIG_USB_GTCO)         += gtco.o
+obj-$(CONFIG_USB_GTCO)		+= gtco.o
 
 ifeq ($(CONFIG_USB_DEBUG),y)
 EXTRA_CFLAGS += -DDEBUG
diff --git a/drivers/usb/input/acecad.c b/drivers/usb/input/acecad.c
index 909138e..be8e924 100644
--- a/drivers/usb/input/acecad.c
+++ b/drivers/usb/input/acecad.c
@@ -111,7 +111,7 @@
 
 static int usb_acecad_open(struct input_dev *dev)
 {
-	struct usb_acecad *acecad = dev->private;
+	struct usb_acecad *acecad = input_get_drvdata(dev);
 
 	acecad->irq->dev = acecad->usbdev;
 	if (usb_submit_urb(acecad->irq, GFP_KERNEL))
@@ -122,7 +122,7 @@
 
 static void usb_acecad_close(struct input_dev *dev)
 {
-	struct usb_acecad *acecad = dev->private;
+	struct usb_acecad *acecad = input_get_drvdata(dev);
 
 	usb_kill_urb(acecad->irq);
 }
@@ -135,6 +135,7 @@
 	struct usb_acecad *acecad;
 	struct input_dev *input_dev;
 	int pipe, maxp;
+	int err = -ENOMEM;
 
 	if (interface->desc.bNumEndpoints != 1)
 		return -ENODEV;
@@ -149,16 +150,22 @@
 
 	acecad = kzalloc(sizeof(struct usb_acecad), GFP_KERNEL);
 	input_dev = input_allocate_device();
-	if (!acecad || !input_dev)
+	if (!acecad || !input_dev) {
+		err = -ENOMEM;
 		goto fail1;
+	}
 
 	acecad->data = usb_buffer_alloc(dev, 8, GFP_KERNEL, &acecad->data_dma);
-	if (!acecad->data)
+	if (!acecad->data) {
+		err= -ENOMEM;
 		goto fail1;
+	}
 
 	acecad->irq = usb_alloc_urb(0, GFP_KERNEL);
-	if (!acecad->irq)
+	if (!acecad->irq) {
+		err = -ENOMEM;
 		goto fail2;
+	}
 
 	acecad->usbdev = dev;
 	acecad->input = input_dev;
@@ -178,8 +185,9 @@
 	input_dev->name = acecad->name;
 	input_dev->phys = acecad->phys;
 	usb_to_input_id(dev, &input_dev->id);
-	input_dev->cdev.dev = &intf->dev;
-	input_dev->private = acecad;
+	input_dev->dev.parent = &intf->dev;
+
+	input_set_drvdata(input_dev, acecad);
 
 	input_dev->open = usb_acecad_open;
 	input_dev->close = usb_acecad_close;
@@ -221,7 +229,9 @@
 	acecad->irq->transfer_dma = acecad->data_dma;
 	acecad->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 
-	input_register_device(acecad->input);
+	err = input_register_device(acecad->input);
+	if (err)
+		goto fail2;
 
 	usb_set_intfdata(intf, acecad);
 
@@ -230,7 +240,7 @@
  fail2:	usb_buffer_free(dev, 8, acecad->data, acecad->data_dma);
  fail1: input_free_device(input_dev);
 	kfree(acecad);
-	return -ENOMEM;
+	return err;
 }
 
 static void usb_acecad_disconnect(struct usb_interface *intf)
diff --git a/drivers/usb/input/aiptek.c b/drivers/usb/input/aiptek.c
index f857935..cc0a498 100644
--- a/drivers/usb/input/aiptek.c
+++ b/drivers/usb/input/aiptek.c
@@ -798,7 +798,7 @@
  */
 static int aiptek_open(struct input_dev *inputdev)
 {
-	struct aiptek *aiptek = inputdev->private;
+	struct aiptek *aiptek = input_get_drvdata(inputdev);
 
 	aiptek->urb->dev = aiptek->usbdev;
 	if (usb_submit_urb(aiptek->urb, GFP_KERNEL) != 0)
@@ -812,7 +812,7 @@
  */
 static void aiptek_close(struct input_dev *inputdev)
 {
-	struct aiptek *aiptek = inputdev->private;
+	struct aiptek *aiptek = input_get_drvdata(inputdev);
 
 	usb_kill_urb(aiptek->urb);
 }
@@ -1972,6 +1972,7 @@
 		AIPTEK_PROGRAMMABLE_DELAY_200,
 		AIPTEK_PROGRAMMABLE_DELAY_300
 	};
+	int err = -ENOMEM;
 
 	/* programmableDelay is where the command-line specified
 	 * delay is kept. We make it the first element of speeds[],
@@ -2043,8 +2044,10 @@
 	inputdev->name = "Aiptek";
 	inputdev->phys = aiptek->features.usbPath;
 	usb_to_input_id(usbdev, &inputdev->id);
-	inputdev->cdev.dev = &intf->dev;
-	inputdev->private = aiptek;
+	inputdev->dev.parent = &intf->dev;
+
+	input_set_drvdata(inputdev, aiptek);
+
 	inputdev->open = aiptek_open;
 	inputdev->close = aiptek_close;
 
@@ -2133,7 +2136,9 @@
 
 	/* Register the tablet as an Input Device
 	 */
-	input_register_device(aiptek->inputdev);
+	err = input_register_device(aiptek->inputdev);
+	if (err)
+		goto fail2;
 
 	/* We now will look for the evdev device which is mapped to
 	 * the tablet. The partial name is kept in the link list of
@@ -2165,23 +2170,13 @@
 
 	return 0;
 
-fail2:	usb_buffer_free(usbdev, AIPTEK_PACKET_LENGTH, aiptek->data,
+ fail2:	usb_buffer_free(usbdev, AIPTEK_PACKET_LENGTH, aiptek->data,
 			aiptek->data_dma);
-fail1:	input_free_device(inputdev);
+ fail1:	input_free_device(inputdev);
 	kfree(aiptek);
-	return -ENOMEM;
+	return err;
 }
 
-/* Forward declaration */
-static void aiptek_disconnect(struct usb_interface *intf);
-
-static struct usb_driver aiptek_driver = {
-	.name = "aiptek",
-	.probe = aiptek_probe,
-	.disconnect = aiptek_disconnect,
-	.id_table = aiptek_ids,
-};
-
 /***********************************************************************
  * Deal with tablet disconnecting from the system.
  */
@@ -2206,6 +2201,13 @@
 	}
 }
 
+static struct usb_driver aiptek_driver = {
+	.name = "aiptek",
+	.probe = aiptek_probe,
+	.disconnect = aiptek_disconnect,
+	.id_table = aiptek_ids,
+};
+
 static int __init aiptek_init(void)
 {
 	int result = usb_register(&aiptek_driver);
diff --git a/drivers/usb/input/appletouch.c b/drivers/usb/input/appletouch.c
index c77291d..e321526 100644
--- a/drivers/usb/input/appletouch.c
+++ b/drivers/usb/input/appletouch.c
@@ -466,7 +466,7 @@
 
 static int atp_open(struct input_dev *input)
 {
-	struct atp *dev = input->private;
+	struct atp *dev = input_get_drvdata(input);
 
 	if (usb_submit_urb(dev->urb, GFP_ATOMIC))
 		return -EIO;
@@ -477,7 +477,7 @@
 
 static void atp_close(struct input_dev *input)
 {
-	struct atp *dev = input->private;
+	struct atp *dev = input_get_drvdata(input);
 
 	usb_kill_urb(dev->urb);
 	dev->open = 0;
@@ -491,8 +491,7 @@
 	struct usb_host_interface *iface_desc;
 	struct usb_endpoint_descriptor *endpoint;
 	int int_in_endpointAddr = 0;
-	int i, retval = -ENOMEM;
-
+	int i, error = -ENOMEM;
 
 	/* set up the endpoint information */
 	/* use only the first interrupt-in endpoint */
@@ -567,17 +566,13 @@
 	}
 
 	dev->urb = usb_alloc_urb(0, GFP_KERNEL);
-	if (!dev->urb) {
-		retval = -ENOMEM;
+	if (!dev->urb)
 		goto err_free_devs;
-	}
 
 	dev->data = usb_buffer_alloc(dev->udev, dev->datalen, GFP_KERNEL,
 				     &dev->urb->transfer_dma);
-	if (!dev->data) {
-		retval = -ENOMEM;
+	if (!dev->data)
 		goto err_free_urb;
-	}
 
 	usb_fill_int_urb(dev->urb, udev,
 			 usb_rcvintpipe(udev, int_in_endpointAddr),
@@ -589,9 +584,10 @@
 	input_dev->name = "appletouch";
 	input_dev->phys = dev->phys;
 	usb_to_input_id(dev->udev, &input_dev->id);
-	input_dev->cdev.dev = &iface->dev;
+	input_dev->dev.parent = &iface->dev;
 
-	input_dev->private = dev;
+	input_set_drvdata(input_dev, dev);
+
 	input_dev->open = atp_open;
 	input_dev->close = atp_close;
 
@@ -633,20 +629,25 @@
 	set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit);
 	set_bit(BTN_LEFT, input_dev->keybit);
 
-	input_register_device(dev->input);
+	error = input_register_device(dev->input);
+	if (error)
+		goto err_free_buffer;
 
 	/* save our data pointer in this interface device */
 	usb_set_intfdata(iface, dev);
 
 	return 0;
 
+ err_free_buffer:
+	usb_buffer_free(dev->udev, dev->datalen,
+			dev->data, dev->urb->transfer_dma);
  err_free_urb:
 	usb_free_urb(dev->urb);
  err_free_devs:
 	usb_set_intfdata(iface, NULL);
 	kfree(dev);
 	input_free_device(input_dev);
-	return retval;
+	return error;
 }
 
 static void atp_disconnect(struct usb_interface *iface)
diff --git a/drivers/usb/input/ati_remote.c b/drivers/usb/input/ati_remote.c
index b724e36..471aab2 100644
--- a/drivers/usb/input/ati_remote.c
+++ b/drivers/usb/input/ati_remote.c
@@ -120,6 +120,7 @@
  * behaviour.
  */
 #define FILTER_TIME	60 /* msec */
+#define REPEAT_DELAY	500 /* msec */
 
 static unsigned long channel_mask;
 module_param(channel_mask, ulong, 0644);
@@ -133,6 +134,10 @@
 module_param(repeat_filter, int, 0644);
 MODULE_PARM_DESC(repeat_filter, "Repeat filter time, default = 60 msec");
 
+static int repeat_delay = REPEAT_DELAY;
+module_param(repeat_delay, int, 0644);
+MODULE_PARM_DESC(repeat_delay, "Delay before sending repeats, default = 500 msec");
+
 #define dbginfo(dev, format, arg...) do { if (debug) dev_info(dev , format , ## arg); } while (0)
 #undef err
 #define err(format, arg...) printk(KERN_ERR format , ## arg)
@@ -174,6 +179,8 @@
 	unsigned char old_data[2];  /* Detect duplicate events */
 	unsigned long old_jiffies;
 	unsigned long acc_jiffies;  /* handle acceleration */
+	unsigned long first_jiffies;
+
 	unsigned int repeat_count;
 
 	char name[NAME_BUFSIZE];
@@ -318,7 +325,7 @@
  */
 static int ati_remote_open(struct input_dev *inputdev)
 {
-	struct ati_remote *ati_remote = inputdev->private;
+	struct ati_remote *ati_remote = input_get_drvdata(inputdev);
 
 	/* On first open, submit the read urb which was set up previously. */
 	ati_remote->irq_urb->dev = ati_remote->udev;
@@ -336,7 +343,7 @@
  */
 static void ati_remote_close(struct input_dev *inputdev)
 {
-	struct ati_remote *ati_remote = inputdev->private;
+	struct ati_remote *ati_remote = input_get_drvdata(inputdev);
 
 	usb_kill_urb(ati_remote->irq_urb);
 }
@@ -501,21 +508,31 @@
 	}
 
 	if (ati_remote_tbl[index].kind == KIND_FILTERED) {
+		unsigned long now = jiffies;
+
 		/* Filter duplicate events which happen "too close" together. */
 		if (ati_remote->old_data[0] == data[1] &&
 		    ati_remote->old_data[1] == data[2] &&
-		    time_before(jiffies, ati_remote->old_jiffies + msecs_to_jiffies(repeat_filter))) {
+		    time_before(now, ati_remote->old_jiffies +
+				     msecs_to_jiffies(repeat_filter))) {
 			ati_remote->repeat_count++;
 		} else {
 			ati_remote->repeat_count = 0;
+			ati_remote->first_jiffies = now;
 		}
 
 		ati_remote->old_data[0] = data[1];
 		ati_remote->old_data[1] = data[2];
-		ati_remote->old_jiffies = jiffies;
+		ati_remote->old_jiffies = now;
 
+		/* Ensure we skip at least the 4 first duplicate events (generated
+		 * by a single keypress), and continue skipping until repeat_delay
+		 * msecs have passed
+		 */
 		if (ati_remote->repeat_count > 0 &&
-		    ati_remote->repeat_count < 5)
+		    (ati_remote->repeat_count < 5 ||
+		     time_before(now, ati_remote->first_jiffies +
+				      msecs_to_jiffies(repeat_delay))))
 			return;
 
 
@@ -653,7 +670,8 @@
 		if (ati_remote_tbl[i].type == EV_KEY)
 			set_bit(ati_remote_tbl[i].code, idev->keybit);
 
-	idev->private = ati_remote;
+	input_set_drvdata(idev, ati_remote);
+
 	idev->open = ati_remote_open;
 	idev->close = ati_remote_close;
 
@@ -661,7 +679,7 @@
 	idev->phys = ati_remote->phys;
 
 	usb_to_input_id(ati_remote->udev, &idev->id);
-	idev->cdev.dev = &ati_remote->udev->dev;
+	idev->dev.parent = &ati_remote->udev->dev;
 }
 
 static int ati_remote_initialize(struct ati_remote *ati_remote)
@@ -772,15 +790,17 @@
 		goto fail3;
 
 	/* Set up and register input device */
-	input_register_device(ati_remote->idev);
+	err = input_register_device(ati_remote->idev);
+	if (err)
+		goto fail3;
 
 	usb_set_intfdata(interface, ati_remote);
 	return 0;
 
-fail3:	usb_kill_urb(ati_remote->irq_urb);
+ fail3:	usb_kill_urb(ati_remote->irq_urb);
 	usb_kill_urb(ati_remote->out_urb);
-fail2:	ati_remote_free_buffers(ati_remote);
-fail1:	input_free_device(input_dev);
+ fail2:	ati_remote_free_buffers(ati_remote);
+ fail1:	input_free_device(input_dev);
 	kfree(ati_remote);
 	return err;
 }
diff --git a/drivers/usb/input/ati_remote2.c b/drivers/usb/input/ati_remote2.c
index 6459be9..a9032aa 100644
--- a/drivers/usb/input/ati_remote2.c
+++ b/drivers/usb/input/ati_remote2.c
@@ -131,7 +131,7 @@
 
 static int ati_remote2_open(struct input_dev *idev)
 {
-	struct ati_remote2 *ar2 = idev->private;
+	struct ati_remote2 *ar2 = input_get_drvdata(idev);
 	int r;
 
 	r = usb_submit_urb(ar2->urb[0], GFP_KERNEL);
@@ -153,7 +153,7 @@
 
 static void ati_remote2_close(struct input_dev *idev)
 {
-	struct ati_remote2 *ar2 = idev->private;
+	struct ati_remote2 *ar2 = input_get_drvdata(idev);
 
 	usb_kill_urb(ar2->urb[0]);
 	usb_kill_urb(ar2->urb[1]);
@@ -337,14 +337,14 @@
 static int ati_remote2_input_init(struct ati_remote2 *ar2)
 {
 	struct input_dev *idev;
-	int i;
+	int i, retval;
 
 	idev = input_allocate_device();
 	if (!idev)
 		return -ENOMEM;
 
 	ar2->idev = idev;
-	idev->private = ar2;
+	input_set_drvdata(idev, ar2);
 
 	idev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_REL);
 	idev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT);
@@ -362,13 +362,13 @@
 	idev->phys = ar2->phys;
 
 	usb_to_input_id(ar2->udev, &idev->id);
-	idev->cdev.dev = &ar2->udev->dev;
+	idev->dev.parent = &ar2->udev->dev;
 
-	i = input_register_device(idev);
-	if (i)
+	retval = input_register_device(idev);
+	if (retval)
 		input_free_device(idev);
 
-	return i;
+	return retval;
 }
 
 static int ati_remote2_urb_init(struct ati_remote2 *ar2)
diff --git a/drivers/usb/input/gtco.c b/drivers/usb/input/gtco.c
index ae756e0..b2ca10f2f 100644
--- a/drivers/usb/input/gtco.c
+++ b/drivers/usb/input/gtco.c
@@ -187,7 +187,6 @@
 
 
 /*
- *
  *   This is an abbreviated parser for the HID Report Descriptor.  We
  *   know what devices we are talking to, so this is by no means meant
  *   to be generic.  We can make some safe assumptions:
@@ -204,7 +203,7 @@
 static void parse_hid_report_descriptor(struct gtco *device, char * report,
 					int length)
 {
-	int   x,i=0;
+	int   x, i = 0;
 
 	/* Tag primitive vars */
 	__u8   prefix;
@@ -215,7 +214,6 @@
 	__u16  data16 = 0;
 	__u32  data32 = 0;
 
-
 	/* For parsing logic */
 	int   inputnum = 0;
 	__u32 usage = 0;
@@ -225,46 +223,46 @@
 	__u32 oldval[TAG_GLOB_MAX];
 
 	/* Debug stuff */
-	char  maintype='x';
+	char  maintype = 'x';
 	char  globtype[12];
-	int   indent=0;
-	char  indentstr[10]="";
-
+	int   indent = 0;
+	char  indentstr[10] = "";
 
 
 	dbg("======>>>>>>PARSE<<<<<<======");
 
 	/* Walk  this report and pull out the info we need */
-	while (i<length){
-		prefix=report[i];
+	while (i < length) {
+		prefix = report[i];
 
 		/* Skip over prefix */
 		i++;
 
 		/* Determine data size and save the data in the proper variable */
 		size = PREF_SIZE(prefix);
-		switch(size){
+		switch (size) {
 		case 1:
 			data = report[i];
 			break;
 		case 2:
-			data16 = le16_to_cpu(get_unaligned((__le16*)(&(report[i]))));
+			data16 = le16_to_cpu(get_unaligned((__le16 *)&report[i]));
 			break;
 		case 3:
 			size = 4;
-			data32 = le32_to_cpu(get_unaligned((__le32*)(&(report[i]))));
+			data32 = le32_to_cpu(get_unaligned((__le32 *)&report[i]));
+			break;
 		}
 
 		/* Skip size of data */
-		i+=size;
+		i += size;
 
 		/* What we do depends on the tag type */
 		tag  = PREF_TAG(prefix);
 		type = PREF_TYPE(prefix);
-		switch(type){
+		switch (type) {
 		case TYPE_MAIN:
-			strcpy(globtype,"");
-			switch(tag){
+			strcpy(globtype, "");
+			switch (tag) {
 
 			case TAG_MAIN_INPUT:
 				/*
@@ -274,19 +272,17 @@
 				 * min/max values
 				 */
 
-				maintype='I';
-				if (data==2){
-					strcpy(globtype,"Variable");
-				}
-				if (data==3){
-					strcpy(globtype,"Var|Const");
-				}
+				maintype = 'I';
+				if (data == 2)
+					strcpy(globtype, "Variable");
+				else if (data == 3)
+					strcpy(globtype, "Var|Const");
 
 				dbg("::::: Saving Report: %d input #%d Max: 0x%X(%d) Min:0x%X(%d) of %d bits",
-				    globalval[TAG_GLOB_REPORT_ID],inputnum,
-				    globalval[TAG_GLOB_LOG_MAX],globalval[TAG_GLOB_LOG_MAX],
-				    globalval[TAG_GLOB_LOG_MIN],globalval[TAG_GLOB_LOG_MIN],
-				    (globalval[TAG_GLOB_REPORT_SZ] * globalval[TAG_GLOB_REPORT_CNT]));
+				    globalval[TAG_GLOB_REPORT_ID], inputnum,
+				    globalval[TAG_GLOB_LOG_MAX], globalval[TAG_GLOB_LOG_MAX],
+				    globalval[TAG_GLOB_LOG_MIN], globalval[TAG_GLOB_LOG_MIN],
+				    globalval[TAG_GLOB_REPORT_SZ] * globalval[TAG_GLOB_REPORT_CNT]);
 
 
 				/*
@@ -295,43 +291,43 @@
 				  that, we look for everything else by
 				  local usage value
 				 */
-				switch (inputnum){
+				switch (inputnum) {
 				case 0:  /* X coord */
-					dbg("GER: X Usage: 0x%x",usage);
-					if (device->max_X == 0){
+					dbg("GER: X Usage: 0x%x", usage);
+					if (device->max_X == 0) {
 						device->max_X = globalval[TAG_GLOB_LOG_MAX];
 						device->min_X = globalval[TAG_GLOB_LOG_MIN];
 					}
-
 					break;
+
 				case 1:  /* Y coord */
-					dbg("GER: Y Usage: 0x%x",usage);
-					if (device->max_Y == 0){
+					dbg("GER: Y Usage: 0x%x", usage);
+					if (device->max_Y == 0) {
 						device->max_Y = globalval[TAG_GLOB_LOG_MAX];
 						device->min_Y = globalval[TAG_GLOB_LOG_MIN];
 					}
 					break;
+
 				default:
 					/* Tilt X */
-					if (usage == DIGITIZER_USAGE_TILT_X){
-						if (device->maxtilt_X == 0){
+					if (usage == DIGITIZER_USAGE_TILT_X) {
+						if (device->maxtilt_X == 0) {
 							device->maxtilt_X = globalval[TAG_GLOB_LOG_MAX];
 							device->mintilt_X = globalval[TAG_GLOB_LOG_MIN];
 						}
 					}
 
 					/* Tilt Y */
-					if (usage == DIGITIZER_USAGE_TILT_Y){
-						if (device->maxtilt_Y == 0){
+					if (usage == DIGITIZER_USAGE_TILT_Y) {
+						if (device->maxtilt_Y == 0) {
 							device->maxtilt_Y = globalval[TAG_GLOB_LOG_MAX];
 							device->mintilt_Y = globalval[TAG_GLOB_LOG_MIN];
 						}
 					}
 
-
 					/* Pressure */
-					if (usage == DIGITIZER_USAGE_TIP_PRESSURE){
-						if (device->maxpressure == 0){
+					if (usage == DIGITIZER_USAGE_TIP_PRESSURE) {
+						if (device->maxpressure == 0) {
 							device->maxpressure = globalval[TAG_GLOB_LOG_MAX];
 							device->minpressure = globalval[TAG_GLOB_LOG_MIN];
 						}
@@ -341,214 +337,226 @@
 				}
 
 				inputnum++;
-
-
 				break;
+
 			case TAG_MAIN_OUTPUT:
-				maintype='O';
+				maintype = 'O';
 				break;
-			case TAG_MAIN_FEATURE:
-				maintype='F';
-				break;
-			case TAG_MAIN_COL_START:
-				maintype='S';
 
-				if (data==0){
+			case TAG_MAIN_FEATURE:
+				maintype = 'F';
+				break;
+
+			case TAG_MAIN_COL_START:
+				maintype = 'S';
+
+				if (data == 0) {
 					dbg("======>>>>>> Physical");
-					strcpy(globtype,"Physical");
-				}else{
+					strcpy(globtype, "Physical");
+				} else
 					dbg("======>>>>>>");
-				}
 
 				/* Indent the debug output */
 				indent++;
-				for (x=0;x<indent;x++){
-					indentstr[x]='-';
-				}
-				indentstr[x]=0;
+				for (x = 0; x < indent; x++)
+					indentstr[x] = '-';
+				indentstr[x] = 0;
 
 				/* Save global tags */
-				for (x=0;x<TAG_GLOB_MAX;x++){
+				for (x = 0; x < TAG_GLOB_MAX; x++)
 					oldval[x] = globalval[x];
-				}
 
 				break;
+
 			case TAG_MAIN_COL_END:
 				dbg("<<<<<<======");
-				maintype='E';
+				maintype = 'E';
 				indent--;
-				for (x=0;x<indent;x++){
-					indentstr[x]='-';
-				}
-				indentstr[x]=0;
+				for (x = 0; x < indent; x++)
+					indentstr[x] = '-';
+				indentstr[x] = 0;
 
 				/* Copy global tags back */
-				for (x=0;x<TAG_GLOB_MAX;x++){
+				for (x = 0; x < TAG_GLOB_MAX; x++)
 					globalval[x] = oldval[x];
-				}
 
 				break;
 			}
 
-			switch (size){
+			switch (size) {
 			case 1:
 				dbg("%sMAINTAG:(%d) %c SIZE: %d Data: %s 0x%x",
-				    indentstr,tag,maintype,size,globtype,data);
+				    indentstr, tag, maintype, size, globtype, data);
 				break;
+
 			case 2:
 				dbg("%sMAINTAG:(%d) %c SIZE: %d Data: %s 0x%x",
-				    indentstr,tag,maintype,size,globtype, data16);
+				    indentstr, tag, maintype, size, globtype, data16);
 				break;
+
 			case 4:
 				dbg("%sMAINTAG:(%d) %c SIZE: %d Data: %s 0x%x",
-				    indentstr,tag,maintype,size,globtype,data32);
+				    indentstr, tag, maintype, size, globtype, data32);
 				break;
 			}
 			break;
+
 		case TYPE_GLOBAL:
-			switch(tag){
+			switch (tag) {
 			case TAG_GLOB_USAGE:
 				/*
 				 * First time we hit the global usage tag,
 				 * it should tell us the type of device
 				 */
-				if (device->usage == 0){
+				if (device->usage == 0)
 					device->usage = data;
-				}
-				strcpy(globtype,"USAGE");
+
+				strcpy(globtype, "USAGE");
 				break;
-			case TAG_GLOB_LOG_MIN   :
-				strcpy(globtype,"LOG_MIN");
+
+			case TAG_GLOB_LOG_MIN:
+				strcpy(globtype, "LOG_MIN");
 				break;
-			case TAG_GLOB_LOG_MAX   :
-				strcpy(globtype,"LOG_MAX");
+
+			case TAG_GLOB_LOG_MAX:
+				strcpy(globtype, "LOG_MAX");
 				break;
-			case TAG_GLOB_PHYS_MIN  :
-				strcpy(globtype,"PHYS_MIN");
+
+			case TAG_GLOB_PHYS_MIN:
+				strcpy(globtype, "PHYS_MIN");
 				break;
-			case TAG_GLOB_PHYS_MAX  :
-				strcpy(globtype,"PHYS_MAX");
+
+			case TAG_GLOB_PHYS_MAX:
+				strcpy(globtype, "PHYS_MAX");
 				break;
-			case TAG_GLOB_UNIT_EXP  :
-				strcpy(globtype,"EXP");
+
+			case TAG_GLOB_UNIT_EXP:
+				strcpy(globtype, "EXP");
 				break;
-			case TAG_GLOB_UNIT      :
-				strcpy(globtype,"UNIT");
+
+			case TAG_GLOB_UNIT:
+				strcpy(globtype, "UNIT");
 				break;
-			case TAG_GLOB_REPORT_SZ :
-				strcpy(globtype,"REPORT_SZ");
+
+			case TAG_GLOB_REPORT_SZ:
+				strcpy(globtype, "REPORT_SZ");
 				break;
-			case TAG_GLOB_REPORT_ID :
-				strcpy(globtype,"REPORT_ID");
+
+			case TAG_GLOB_REPORT_ID:
+				strcpy(globtype, "REPORT_ID");
 				/* New report, restart numbering */
-				inputnum=0;
+				inputnum = 0;
 				break;
+
 			case TAG_GLOB_REPORT_CNT:
-				strcpy(globtype,"REPORT_CNT");
+				strcpy(globtype, "REPORT_CNT");
 				break;
-			case TAG_GLOB_PUSH :
-				strcpy(globtype,"PUSH");
+
+			case TAG_GLOB_PUSH:
+				strcpy(globtype, "PUSH");
 				break;
+
 			case TAG_GLOB_POP:
-				strcpy(globtype,"POP");
+				strcpy(globtype, "POP");
 				break;
 			}
 
-
 			/* Check to make sure we have a good tag number
 			   so we don't overflow array */
-			if (tag < TAG_GLOB_MAX){
-				switch (size){
+			if (tag < TAG_GLOB_MAX) {
+				switch (size) {
 				case 1:
-					dbg("%sGLOBALTAG:%s(%d) SIZE: %d Data: 0x%x",indentstr,globtype,tag,size,data);
-					globalval[tag]=data;
+					dbg("%sGLOBALTAG:%s(%d) SIZE: %d Data: 0x%x",
+					    indentstr, globtype, tag, size, data);
+					globalval[tag] = data;
 					break;
+
 				case 2:
-					dbg("%sGLOBALTAG:%s(%d) SIZE: %d Data: 0x%x",indentstr,globtype,tag,size,data16);
-					globalval[tag]=data16;
+					dbg("%sGLOBALTAG:%s(%d) SIZE: %d Data: 0x%x",
+					    indentstr, globtype, tag, size, data16);
+					globalval[tag] = data16;
 					break;
+
 				case 4:
-					dbg("%sGLOBALTAG:%s(%d) SIZE: %d Data: 0x%x",indentstr,globtype,tag,size,data32);
-					globalval[tag]=data32;
+					dbg("%sGLOBALTAG:%s(%d) SIZE: %d Data: 0x%x",
+					    indentstr, globtype, tag, size, data32);
+					globalval[tag] = data32;
 					break;
 				}
-			}else{
+			} else {
 				dbg("%sGLOBALTAG: ILLEGAL TAG:%d SIZE: %d ",
-				    indentstr,tag,size);
+				    indentstr, tag, size);
 			}
-
-
 			break;
 
 		case TYPE_LOCAL:
-			switch(tag){
+			switch (tag) {
 			case TAG_GLOB_USAGE:
-				strcpy(globtype,"USAGE");
+				strcpy(globtype, "USAGE");
 				/* Always 1 byte */
 				usage = data;
 				break;
-			case TAG_GLOB_LOG_MIN   :
-				strcpy(globtype,"MIN");
+
+			case TAG_GLOB_LOG_MIN:
+				strcpy(globtype, "MIN");
 				break;
-			case TAG_GLOB_LOG_MAX   :
-				strcpy(globtype,"MAX");
+
+			case TAG_GLOB_LOG_MAX:
+				strcpy(globtype, "MAX");
 				break;
+
 			default:
-				strcpy(globtype,"UNKNOWN");
+				strcpy(globtype, "UNKNOWN");
+				break;
 			}
 
-			switch (size){
+			switch (size) {
 			case 1:
 				dbg("%sLOCALTAG:(%d) %s SIZE: %d Data: 0x%x",
-				    indentstr,tag,globtype,size,data);
+				    indentstr, tag, globtype, size, data);
 				break;
+
 			case 2:
 				dbg("%sLOCALTAG:(%d) %s SIZE: %d Data: 0x%x",
-				    indentstr,tag,globtype,size,data16);
+				    indentstr, tag, globtype, size, data16);
 				break;
+
 			case 4:
 				dbg("%sLOCALTAG:(%d) %s SIZE: %d Data: 0x%x",
-				    indentstr,tag,globtype,size,data32);
+				    indentstr, tag, globtype, size, data32);
 				break;
 			}
 
 			break;
 		}
-
 	}
-
 }
 
-
-
 /*   INPUT DRIVER Routines                               */
 
-
 /*
- *    Called when opening the input device.  This will submit the URB to
- *    the usb system so we start getting reports
+ * Called when opening the input device.  This will submit the URB to
+ * the usb system so we start getting reports
  */
 static int gtco_input_open(struct input_dev *inputdev)
 {
-	struct gtco *device;
-	device = inputdev->private;
+	struct gtco *device = input_get_drvdata(inputdev);
 
 	device->urbinfo->dev = device->usbdev;
-	if (usb_submit_urb(device->urbinfo, GFP_KERNEL)) {
+	if (usb_submit_urb(device->urbinfo, GFP_KERNEL))
 		return -EIO;
-	}
+
 	return 0;
 }
 
-/**
-    Called when closing the input device.  This will unlink the URB
-*/
+/*
+ * Called when closing the input device.  This will unlink the URB
+ */
 static void gtco_input_close(struct input_dev *inputdev)
 {
-	struct gtco *device = inputdev->private;
+	struct gtco *device = input_get_drvdata(inputdev);
 
 	usb_kill_urb(device->urbinfo);
-
 }
 
 
@@ -560,19 +568,16 @@
  *  placed in the struct gtco structure
  *
  */
-static void  gtco_setup_caps(struct input_dev  *inputdev)
+static void gtco_setup_caps(struct input_dev *inputdev)
 {
-	struct gtco *device = inputdev->private;
-
+	struct gtco *device = input_get_drvdata(inputdev);
 
 	/* Which events */
 	inputdev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_MSC);
 
-
 	/* Misc event menu block */
 	inputdev->mscbit[0] = BIT(MSC_SCAN)|BIT(MSC_SERIAL)|BIT(MSC_RAW) ;
 
-
 	/* Absolute values based on HID report info */
 	input_set_abs_params(inputdev, ABS_X, device->min_X, device->max_X,
 			     0, 0);
@@ -590,17 +595,12 @@
 	input_set_abs_params(inputdev, ABS_PRESSURE, device->minpressure,
 			     device->maxpressure, 0, 0);
 
-
 	/* Transducer */
-	input_set_abs_params(inputdev, ABS_MISC, 0,0xFF, 0, 0);
-
+	input_set_abs_params(inputdev, ABS_MISC, 0, 0xFF, 0, 0);
 }
 
-
-
 /*   USB Routines  */
 
-
 /*
  * URB callback routine.  Called when we get IRQ reports from the
  *  digitizer.
@@ -610,9 +610,7 @@
  */
 static void gtco_urb_callback(struct urb *urbinfo)
 {
-
-
-	struct gtco     *device = urbinfo->context;
+	struct gtco *device = urbinfo->context;
 	struct input_dev  *inputdev;
 	int               rc;
 	u32               val = 0;
@@ -621,19 +619,20 @@
 
 	inputdev = device->inputdevice;
 
-
 	/* Was callback OK? */
-	if ((urbinfo->status == -ECONNRESET ) ||
-	    (urbinfo->status == -ENOENT ) ||
-	    (urbinfo->status == -ESHUTDOWN )){
+	if (urbinfo->status == -ECONNRESET ||
+	    urbinfo->status == -ENOENT ||
+	    urbinfo->status == -ESHUTDOWN) {
 
 		/* Shutdown is occurring. Return and don't queue up any more */
 		return;
 	}
 
-	if (urbinfo->status != 0 ) {
-		/* Some unknown error.  Hopefully temporary.  Just go and */
-		/* requeue an URB */
+	if (urbinfo->status != 0) {
+		/*
+		 * Some unknown error.  Hopefully temporary. Just go and
+		 * requeue an URB
+		 */
 		goto resubmit;
 	}
 
@@ -642,10 +641,9 @@
 	 */
 
 	/* PID dependent when we interpret the report */
-	if ((inputdev->id.product == PID_1000 )||
-	    (inputdev->id.product == PID_1001 )||
-	    (inputdev->id.product == PID_1002 ))
-	{
+	if (inputdev->id.product == PID_1000 ||
+	    inputdev->id.product == PID_1001 ||
+	    inputdev->id.product == PID_1002) {
 
 		/*
 		 * Switch on the report ID
@@ -653,10 +651,10 @@
 		 * the report number.  We can just fall through the case
 		 * statements if we start with the highest number report
 		 */
-		switch(device->buffer[0]){
+		switch (device->buffer[0]) {
 		case 5:
 			/* Pressure is 9 bits */
-			val =  ((u16)(device->buffer[8]) << 1);
+			val = ((u16)(device->buffer[8]) << 1);
 			val |= (u16)(device->buffer[7] >> 7);
 			input_report_abs(inputdev, ABS_PRESSURE,
 					 device->buffer[8]);
@@ -664,7 +662,6 @@
 			/* Mask out the Y tilt value used for pressure */
 			device->buffer[7] = (u8)((device->buffer[7]) & 0x7F);
 
-
 			/* Fall thru */
 		case 4:
 			/* Tilt */
@@ -684,11 +681,10 @@
 			input_report_abs(inputdev, ABS_TILT_Y, (s32)valsigned);
 
 			/* Fall thru */
-
 		case 2:
 		case 3:
 			/* Convert buttons, only 5 bits possible */
-			val = (device->buffer[5])&MASK_BUTTON;
+			val = (device->buffer[5]) & MASK_BUTTON;
 
 			/* We don't apply any meaning to the bitmask,
 			   just report */
@@ -696,132 +692,109 @@
 
 			/*  Fall thru */
 		case 1:
-
 			/* All reports have X and Y coords in the same place */
-			val = le16_to_cpu(get_unaligned((__le16 *) &(device->buffer[1])));
+			val = le16_to_cpu(get_unaligned((__le16 *)&device->buffer[1]));
 			input_report_abs(inputdev, ABS_X, val);
 
-			val = le16_to_cpu(get_unaligned((__le16 *) &(device->buffer[3])));
+			val = le16_to_cpu(get_unaligned((__le16 *)&device->buffer[3]));
 			input_report_abs(inputdev, ABS_Y, val);
 
-
 			/* Ditto for proximity bit */
-			if (device->buffer[5]& MASK_INRANGE){
-				val = 1;
-			}else{
-				val=0;
-			}
+			val = device->buffer[5] & MASK_INRANGE ? 1 : 0;
 			input_report_abs(inputdev, ABS_DISTANCE, val);
 
-
 			/* Report 1 is an exception to how we handle buttons */
 			/* Buttons are an index, not a bitmask */
-			if (device->buffer[0] == 1){
+			if (device->buffer[0] == 1) {
 
-				/* Convert buttons, 5 bit index */
-				/* Report value of index set as one,
-				   the rest as 0 */
-				val = device->buffer[5]& MASK_BUTTON;
+				/*
+				 * Convert buttons, 5 bit index
+				 * Report value of index set as one,
+				 * the rest as 0
+				 */
+				val = device->buffer[5] & MASK_BUTTON;
 				dbg("======>>>>>>REPORT 1: val 0x%X(%d)",
-				    val,val);
+				    val, val);
 
 				/*
 				 * We don't apply any meaning to the button
 				 * index, just report it
 				 */
 				input_event(inputdev, EV_MSC, MSC_SERIAL, val);
-
-
 			}
-
 			break;
+
 		case 7:
 			/* Menu blocks */
 			input_event(inputdev, EV_MSC, MSC_SCAN,
 				    device->buffer[1]);
-
-
 			break;
-
 		}
-
-
 	}
+
 	/* Other pid class */
-	if ((inputdev->id.product == PID_400 )||
-	    (inputdev->id.product == PID_401 ))
-	{
+	if (inputdev->id.product == PID_400 ||
+	    inputdev->id.product == PID_401) {
 
 		/* Report 2 */
-		if (device->buffer[0] == 2){
+		if (device->buffer[0] == 2) {
 			/* Menu blocks */
-			input_event(inputdev, EV_MSC, MSC_SCAN,
-				    device->buffer[1]);
+			input_event(inputdev, EV_MSC, MSC_SCAN, device->buffer[1]);
 		}
 
 		/*  Report 1 */
-		if (device->buffer[0] == 1){
+		if (device->buffer[0] == 1) {
 			char buttonbyte;
 
-
 			/*  IF X max > 64K, we still a bit from the y report */
-			if (device->max_X > 0x10000){
+			if (device->max_X > 0x10000) {
 
-				val = (u16)(((u16)(device->buffer[2]<<8))|((u8)(device->buffer[1])));
-				val |= (u32)(((u8)device->buffer[3]&0x1)<< 16);
+				val = (u16)(((u16)(device->buffer[2] << 8)) | (u8)device->buffer[1]);
+				val |= (u32)(((u8)device->buffer[3] & 0x1) << 16);
 
 				input_report_abs(inputdev, ABS_X, val);
 
-				le_buffer[0]  = (u8)((u8)(device->buffer[3])>>1);
-				le_buffer[0] |= (u8)((device->buffer[3]&0x1)<<7);
+				le_buffer[0]  = (u8)((u8)(device->buffer[3]) >> 1);
+				le_buffer[0] |= (u8)((device->buffer[3] & 0x1) << 7);
 
-				le_buffer[1]  = (u8)(device->buffer[4]>>1);
-				le_buffer[1] |= (u8)((device->buffer[5]&0x1)<<7);
+				le_buffer[1]  = (u8)(device->buffer[4] >> 1);
+				le_buffer[1] |= (u8)((device->buffer[5] & 0x1) << 7);
 
-				val = le16_to_cpu(get_unaligned((__le16 *)(le_buffer)));
-
+				val = le16_to_cpu(get_unaligned((__le16 *)le_buffer));
 				input_report_abs(inputdev, ABS_Y, val);
 
-
 				/*
 				 * Shift the button byte right by one to
 				 * make it look like the standard report
 				 */
-				buttonbyte = (device->buffer[5])>>1;
-			}else{
+				buttonbyte = device->buffer[5] >> 1;
+			} else {
 
-				val = le16_to_cpu(get_unaligned((__le16 *) (&(device->buffer[1]))));
+				val = le16_to_cpu(get_unaligned((__le16 *)&device->buffer[1]));
 				input_report_abs(inputdev, ABS_X, val);
 
-				val = le16_to_cpu(get_unaligned((__le16 *) (&(device->buffer[3]))));
+				val = le16_to_cpu(get_unaligned((__le16 *)&device->buffer[3]));
 				input_report_abs(inputdev, ABS_Y, val);
 
 				buttonbyte = device->buffer[5];
-
 			}
 
-
 			/* BUTTONS and PROXIMITY */
-			if (buttonbyte& MASK_INRANGE){
-				val = 1;
-			}else{
-				val=0;
-			}
+			val = buttonbyte & MASK_INRANGE ? 1 : 0;
 			input_report_abs(inputdev, ABS_DISTANCE, val);
 
 			/* Convert buttons, only 4 bits possible */
-			val = buttonbyte&0x0F;
+			val = buttonbyte & 0x0F;
 #ifdef USE_BUTTONS
-			for ( i=0;i<5;i++){
-				input_report_key(inputdev, BTN_DIGI+i,val&(1<<i));
-			}
+			for (i = 0; i < 5; i++)
+				input_report_key(inputdev, BTN_DIGI + i, val & (1 << i));
 #else
 			/* We don't apply any meaning to the bitmask, just report */
 			input_event(inputdev, EV_MSC, MSC_SERIAL, val);
 #endif
+
 			/* TRANSDUCER */
 			input_report_abs(inputdev, ABS_MISC, device->buffer[6]);
-
 		}
 	}
 
@@ -833,10 +806,8 @@
 
  resubmit:
 	rc = usb_submit_urb(urbinfo, GFP_ATOMIC);
-	if (rc != 0) {
-		err("usb_submit_urb failed rc=0x%x",rc);
-	}
-
+	if (rc != 0)
+		err("usb_submit_urb failed rc=0x%x", rc);
 }
 
 /*
@@ -854,58 +825,46 @@
 		      const struct usb_device_id *id)
 {
 
-	struct gtco             *device = NULL;
-	char                    path[PATHLENGTH];
-	struct input_dev        *inputdev;
+	struct gtco             *gtco;
+	struct input_dev        *input_dev;
 	struct hid_descriptor   *hid_desc;
-	char                    *report;
-	int                     result=0, retry;
+	char                    *report = NULL;
+	int                     result = 0, retry;
+	int			error;
 	struct usb_endpoint_descriptor *endpoint;
 
 	/* Allocate memory for device structure */
-	device = kzalloc(sizeof(struct gtco), GFP_KERNEL);
-	if (device == NULL) {
+	gtco = kzalloc(sizeof(struct gtco), GFP_KERNEL);
+	input_dev = input_allocate_device();
+	if (!gtco || !input_dev) {
 		err("No more memory");
-		return -ENOMEM;
+		error = -ENOMEM;
+		goto err_free_devs;
 	}
 
-
-	device->inputdevice = input_allocate_device();
-	if (!device->inputdevice){
-		kfree(device);
-		err("No more memory");
-		return -ENOMEM;
-	}
-
-	/* Get pointer to the input device */
-	inputdev = device->inputdevice;
+	/* Set pointer to the input device */
+	gtco->inputdevice = input_dev;
 
 	/* Save interface information */
-	device->usbdev     = usb_get_dev(interface_to_usbdev(usbinterface));
-
+	gtco->usbdev = usb_get_dev(interface_to_usbdev(usbinterface));
 
 	/* Allocate some data for incoming reports */
-	device->buffer = usb_buffer_alloc(device->usbdev, REPORT_MAX_SIZE,
-					   GFP_KERNEL, &(device->buf_dma));
-	if (!device->buffer){
-		input_free_device(device->inputdevice);
-		kfree(device);
-		err("No more memory");
-		return -ENOMEM;
+	gtco->buffer = usb_buffer_alloc(gtco->usbdev, REPORT_MAX_SIZE,
+					GFP_KERNEL, &gtco->buf_dma);
+	if (!gtco->buffer) {
+		err("No more memory for us buffers");
+		error = -ENOMEM;
+		goto err_free_devs;
 	}
 
 	/* Allocate URB for reports */
-	device->urbinfo = usb_alloc_urb(0, GFP_KERNEL);
-	if (!device->urbinfo) {
-		usb_buffer_free(device->usbdev, REPORT_MAX_SIZE,
-				device->buffer, device->buf_dma);
-		input_free_device(device->inputdevice);
-		kfree(device);
-		err("No more memory");
+	gtco->urbinfo = usb_alloc_urb(0, GFP_KERNEL);
+	if (!gtco->urbinfo) {
+		err("Failed to allocate URB");
 		return -ENOMEM;
+		goto err_free_buf;
 	}
 
-
 	/*
 	 * The endpoint is always altsetting 0, we know this since we know
 	 * this device only has one interrupt endpoint
@@ -913,51 +872,43 @@
 	endpoint = &usbinterface->altsetting[0].endpoint[0].desc;
 
 	/* Some debug */
-	dbg("gtco # interfaces: %d",usbinterface->num_altsetting);
-	dbg("num endpoints:     %d",usbinterface->cur_altsetting->desc.bNumEndpoints);
-	dbg("interface class:   %d",usbinterface->cur_altsetting->desc.bInterfaceClass);
-	dbg("endpoint: attribute:0x%x type:0x%x",endpoint->bmAttributes,endpoint->bDescriptorType);
+	dbg("gtco # interfaces: %d", usbinterface->num_altsetting);
+	dbg("num endpoints:     %d", usbinterface->cur_altsetting->desc.bNumEndpoints);
+	dbg("interface class:   %d", usbinterface->cur_altsetting->desc.bInterfaceClass);
+	dbg("endpoint: attribute:0x%x type:0x%x", endpoint->bmAttributes, endpoint->bDescriptorType);
 	if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)
 		dbg("endpoint: we have interrupt endpoint\n");
 
-	dbg("endpoint extra len:%d ",usbinterface->altsetting[0].extralen);
-
-
+	dbg("endpoint extra len:%d ", usbinterface->altsetting[0].extralen);
 
 	/*
 	 * Find the HID descriptor so we can find out the size of the
 	 * HID report descriptor
 	 */
 	if (usb_get_extra_descriptor(usbinterface->cur_altsetting,
-				     HID_DEVICE_TYPE,&hid_desc) != 0){
+				     HID_DEVICE_TYPE, &hid_desc) != 0){
 		err("Can't retrieve exta USB descriptor to get hid report descriptor length");
-		usb_buffer_free(device->usbdev, REPORT_MAX_SIZE,
-				device->buffer, device->buf_dma);
-		input_free_device(device->inputdevice);
-		kfree(device);
-		return -EIO;
+		error = -EIO;
+		goto err_free_urb;
 	}
 
 	dbg("Extra descriptor success: type:%d  len:%d",
 	    hid_desc->bDescriptorType,  hid_desc->wDescriptorLength);
 
-	if (!(report = kzalloc(hid_desc->wDescriptorLength, GFP_KERNEL))) {
-		usb_buffer_free(device->usbdev, REPORT_MAX_SIZE,
-				device->buffer, device->buf_dma);
-
-		input_free_device(device->inputdevice);
-		kfree(device);
-		err("No more memory");
-		return -ENOMEM;
+	report = kzalloc(hid_desc->wDescriptorLength, GFP_KERNEL);
+	if (!report) {
+		err("No more memory for report");
+		error = -ENOMEM;
+		goto err_free_urb;
 	}
 
 	/* Couple of tries to get reply */
-	for (retry=0;retry<3;retry++) {
-		result = usb_control_msg(device->usbdev,
-					 usb_rcvctrlpipe(device->usbdev, 0),
+	for (retry = 0; retry < 3; retry++) {
+		result = usb_control_msg(gtco->usbdev,
+					 usb_rcvctrlpipe(gtco->usbdev, 0),
 					 USB_REQ_GET_DESCRIPTOR,
 					 USB_RECIP_INTERFACE | USB_DIR_IN,
-					 (REPORT_DEVICE_TYPE << 8),
+					 REPORT_DEVICE_TYPE << 8,
 					 0, /* interface */
 					 report,
 					 hid_desc->wDescriptorLength,
@@ -969,72 +920,76 @@
 
 	/* If we didn't get the report, fail */
 	dbg("usb_control_msg result: :%d", result);
-	if (result != hid_desc->wDescriptorLength){
-		kfree(report);
-		usb_buffer_free(device->usbdev, REPORT_MAX_SIZE,
-				device->buffer, device->buf_dma);
-		input_free_device(device->inputdevice);
-		kfree(device);
+	if (result != hid_desc->wDescriptorLength) {
 		err("Failed to get HID Report Descriptor of size: %d",
 		    hid_desc->wDescriptorLength);
-		return -EIO;
+		error = -EIO;
+		goto err_free_urb;
 	}
 
-
 	/* Now we parse the report */
-	parse_hid_report_descriptor(device,report,result);
+	parse_hid_report_descriptor(gtco, report, result);
 
 	/* Now we delete it */
 	kfree(report);
 
 	/* Create a device file node */
-	usb_make_path(device->usbdev, path, PATHLENGTH);
-	sprintf(device->usbpath, "%s/input0", path);
-
+	usb_make_path(gtco->usbdev, gtco->usbpath, sizeof(gtco->usbpath));
+	strlcat(gtco->usbpath, "/input0", sizeof(gtco->usbpath));
 
 	/* Set Input device functions */
-	inputdev->open     = gtco_input_open;
-	inputdev->close    = gtco_input_close;
+	input_dev->open = gtco_input_open;
+	input_dev->close = gtco_input_close;
 
 	/* Set input device information */
-	inputdev->name     = "GTCO_CalComp";
-	inputdev->phys     = device->usbpath;
-	inputdev->private  = device;
+	input_dev->name = "GTCO_CalComp";
+	input_dev->phys = gtco->usbpath;
 
+	input_set_drvdata(input_dev, gtco);
 
 	/* Now set up all the input device capabilities */
-	gtco_setup_caps(inputdev);
+	gtco_setup_caps(input_dev);
 
 	/* Set input device required ID information */
-	usb_to_input_id(device->usbdev, &device->inputdevice->id);
-	inputdev->cdev.dev = &usbinterface->dev;
+	usb_to_input_id(gtco->usbdev, &input_dev->id);
+	input_dev->dev.parent = &usbinterface->dev;
 
 	/* Setup the URB, it will be posted later on open of input device */
 	endpoint = &usbinterface->altsetting[0].endpoint[0].desc;
 
-	usb_fill_int_urb(device->urbinfo,
-			 device->usbdev,
-			 usb_rcvintpipe(device->usbdev,
+	usb_fill_int_urb(gtco->urbinfo,
+			 gtco->usbdev,
+			 usb_rcvintpipe(gtco->usbdev,
 					endpoint->bEndpointAddress),
-			 device->buffer,
+			 gtco->buffer,
 			 REPORT_MAX_SIZE,
 			 gtco_urb_callback,
-			 device,
+			 gtco,
 			 endpoint->bInterval);
 
-	device->urbinfo->transfer_dma = device->buf_dma;
-	device->urbinfo->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+	gtco->urbinfo->transfer_dma = gtco->buf_dma;
+	gtco->urbinfo->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 
-
-	/* Save device pointer in USB interface device */
-	usb_set_intfdata(usbinterface, device);
+	/* Save gtco pointer in USB interface gtco */
+	usb_set_intfdata(usbinterface, gtco);
 
 	/* All done, now register the input device */
-	input_register_device(inputdev);
+	error = input_register_device(input_dev);
+	if (error)
+		goto err_free_urb;
 
-	info( "gtco driver created usb:  %s\n",  path);
 	return 0;
 
+ err_free_urb:
+	usb_free_urb(gtco->urbinfo);
+ err_free_buf:
+	usb_buffer_free(gtco->usbdev, REPORT_MAX_SIZE,
+			gtco->buffer, gtco->buf_dma);
+ err_free_devs:
+	kfree(report);
+	input_free_device(input_dev);
+	kfree(gtco);
+	return error;
 }
 
 /*
@@ -1044,47 +999,46 @@
  */
 static void gtco_disconnect(struct usb_interface *interface)
 {
-
 	/* Grab private device ptr */
-	struct gtco    *device = usb_get_intfdata (interface);
+	struct gtco *gtco = usb_get_intfdata(interface);
 
 	/* Now reverse all the registration stuff */
-	if (device) {
-		input_unregister_device(device->inputdevice);
-		usb_kill_urb(device->urbinfo);
-		usb_free_urb(device->urbinfo);
-		usb_buffer_free(device->usbdev, REPORT_MAX_SIZE,
-				device->buffer, device->buf_dma);
-		kfree(device);
+	if (gtco) {
+		input_unregister_device(gtco->inputdevice);
+		usb_kill_urb(gtco->urbinfo);
+		usb_free_urb(gtco->urbinfo);
+		usb_buffer_free(gtco->usbdev, REPORT_MAX_SIZE,
+				gtco->buffer, gtco->buf_dma);
+		kfree(gtco);
 	}
 
 	info("gtco driver disconnected");
 }
 
-
 /*   STANDARD MODULE LOAD ROUTINES  */
 
 static struct usb_driver gtco_driverinfo_table = {
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16))
-	.owner      = THIS_MODULE,
-#endif
-	.name       = "gtco",
-	.id_table   = gtco_usbid_table,
-	.probe      = gtco_probe,
-	.disconnect = gtco_disconnect,
+	.name		= "gtco",
+	.id_table	= gtco_usbid_table,
+	.probe		= gtco_probe,
+	.disconnect	= gtco_disconnect,
 };
+
 /*
  *  Register this module with the USB subsystem
  */
 static int __init gtco_init(void)
 {
-	int rc;
-	rc = usb_register(&gtco_driverinfo_table);
-	if (rc) {
-		err("usb_register() failed rc=0x%x", rc);
+	int error;
+
+	error = usb_register(&gtco_driverinfo_table);
+	if (error) {
+		err("usb_register() failed rc=0x%x", error);
+		return error;
 	}
-	printk("GTCO usb driver version: %s",GTCO_VERSION);
-	return rc;
+
+	printk("GTCO usb driver version: %s", GTCO_VERSION);
+	return 0;
 }
 
 /*
@@ -1095,7 +1049,7 @@
 	usb_deregister(&gtco_driverinfo_table);
 }
 
-module_init (gtco_init);
-module_exit (gtco_exit);
+module_init(gtco_init);
+module_exit(gtco_exit);
 
 MODULE_LICENSE("GPL");
diff --git a/drivers/usb/input/itmtouch.c b/drivers/usb/input/itmtouch.c
deleted file mode 100644
index aac968a..0000000
--- a/drivers/usb/input/itmtouch.c
+++ /dev/null
@@ -1,271 +0,0 @@
-/******************************************************************************
- * itmtouch.c  --  Driver for ITM touchscreen panel
- *
- * This program is free software; you can redistribute it and/or
- * 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.
- *
- * Based upon original work by Chris Collins <xfire-itmtouch@xware.cx>.
- *
- * Kudos to ITM for providing me with the datasheet for the panel,
- * even though it was a day later than I had finished writing this
- * driver.
- *
- * It has meant that I've been able to correct my interpretation of the
- * protocol packets however.
- *
- * CC -- 2003/9/29
- *
- * History
- * 1.0 & 1.1  2003 (CC) vojtech@suse.cz
- *   Original version for 2.4.x kernels
- *
- * 1.2  02/03/2005 (HCE) hc@mivu.no
- *   Complete rewrite to support Linux 2.6.10, thanks to mtouchusb.c for hints.
- *   Unfortunately no calibration support at this time.
- *
- * 1.2.1  09/03/2005 (HCE) hc@mivu.no
- *   Code cleanup and adjusting syntax to start matching kernel standards
- * 
- * 1.2.2  10/05/2006 (MJA) massad@gmail.com
- *   Flag for detecting if the screen was being touch was incorrectly 
- *   inverted, so no touch events were being detected. 	
- *   
- *****************************************************************************/
-
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/usb/input.h>
-
-/* only an 8 byte buffer necessary for a single packet */
-#define ITM_BUFSIZE			8
-#define PATH_SIZE			64
-
-#define USB_VENDOR_ID_ITMINC		0x0403
-#define USB_PRODUCT_ID_TOUCHPANEL	0xf9e9
-
-#define DRIVER_AUTHOR "Hans-Christian Egtvedt <hc@mivu.no>"
-#define DRIVER_VERSION "v1.2.2"
-#define DRIVER_DESC "USB ITM Inc Touch Panel Driver"
-#define DRIVER_LICENSE "GPL"
-
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
-MODULE_LICENSE( DRIVER_LICENSE );
-
-struct itmtouch_dev {
-	struct usb_device	*usbdev; /* usb device */
-	struct input_dev	*inputdev; /* input device */
-	struct urb		*readurb; /* urb */
-	char			rbuf[ITM_BUFSIZE]; /* data */
-	int			users;
-	char name[128];
-	char phys[64];
-};
-
-static struct usb_device_id itmtouch_ids [] = {
-	{ USB_DEVICE(USB_VENDOR_ID_ITMINC, USB_PRODUCT_ID_TOUCHPANEL) },
-	{ }
-};
-
-static void itmtouch_irq(struct urb *urb)
-{
-	struct itmtouch_dev *itmtouch = urb->context;
-	unsigned char *data = urb->transfer_buffer;
-	struct input_dev *dev = itmtouch->inputdev;
-	int retval;
-
-	switch (urb->status) {
-	case 0:
-		/* success */
-		break;
-	case -ETIME:
-		/* this urb is timing out */
-		dbg("%s - urb timed out - was the device unplugged?",
-		    __FUNCTION__);
-		return;
-	case -ECONNRESET:
-	case -ENOENT:
-	case -ESHUTDOWN:
-		/* this urb is terminated, clean up */
-		dbg("%s - urb shutting down with status: %d",
-		    __FUNCTION__, urb->status);
-		return;
-	default:
-		dbg("%s - nonzero urb status received: %d",
-		    __FUNCTION__, urb->status);
-		goto exit;
-	}
-
-	/* if pressure has been released, then don't report X/Y */
-	if (!(data[7] & 0x20)) {
-		input_report_abs(dev, ABS_X, (data[0] & 0x1F) << 7 | (data[3] & 0x7F));
-		input_report_abs(dev, ABS_Y, (data[1] & 0x1F) << 7 | (data[4] & 0x7F));
-	}
-
-	input_report_abs(dev, ABS_PRESSURE, (data[2] & 1) << 7 | (data[5] & 0x7F));
-	input_report_key(dev, BTN_TOUCH, ~data[7] & 0x20);
-	input_sync(dev);
-
-exit:
-	retval = usb_submit_urb (urb, GFP_ATOMIC);
-	if (retval)
-		printk(KERN_ERR "%s - usb_submit_urb failed with result: %d",
-				__FUNCTION__, retval);
-}
-
-static int itmtouch_open(struct input_dev *input)
-{
-	struct itmtouch_dev *itmtouch = input->private;
-
-	itmtouch->readurb->dev = itmtouch->usbdev;
-
-	if (usb_submit_urb(itmtouch->readurb, GFP_KERNEL))
-		return -EIO;
-
-	return 0;
-}
-
-static void itmtouch_close(struct input_dev *input)
-{
-	struct itmtouch_dev *itmtouch = input->private;
-
-	usb_kill_urb(itmtouch->readurb);
-}
-
-static int itmtouch_probe(struct usb_interface *intf, const struct usb_device_id *id)
-{
-	struct itmtouch_dev *itmtouch;
-	struct input_dev *input_dev;
-	struct usb_host_interface *interface;
-	struct usb_endpoint_descriptor *endpoint;
-	struct usb_device *udev = interface_to_usbdev(intf);
-	unsigned int pipe;
-	unsigned int maxp;
-
-	interface = intf->cur_altsetting;
-	endpoint = &interface->endpoint[0].desc;
-
-	itmtouch = kzalloc(sizeof(struct itmtouch_dev), GFP_KERNEL);
-	input_dev = input_allocate_device();
-	if (!itmtouch || !input_dev) {
-		err("%s - Out of memory.", __FUNCTION__);
-		goto fail;
-	}
-
-	itmtouch->usbdev = udev;
-	itmtouch->inputdev = input_dev;
-
-	if (udev->manufacturer)
-		strlcpy(itmtouch->name, udev->manufacturer, sizeof(itmtouch->name));
-
-	if (udev->product) {
-		if (udev->manufacturer)
-			strlcat(itmtouch->name, " ", sizeof(itmtouch->name));
-		strlcat(itmtouch->name, udev->product, sizeof(itmtouch->name));
-	}
-
-	if (!strlen(itmtouch->name))
-		sprintf(itmtouch->name, "USB ITM touchscreen");
-
-	usb_make_path(udev, itmtouch->phys, sizeof(itmtouch->phys));
-	strlcpy(itmtouch->phys, "/input0", sizeof(itmtouch->phys));
-
-	input_dev->name = itmtouch->name;
-	input_dev->phys = itmtouch->phys;
-	usb_to_input_id(udev, &input_dev->id);
-	input_dev->cdev.dev = &intf->dev;
-	input_dev->private = itmtouch;
-
-	input_dev->open = itmtouch_open;
-	input_dev->close = itmtouch_close;
-
-	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
-	input_dev->absbit[0] = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE);
-	input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
-
-	/* device limits */
-	/* as specified by the ITM datasheet, X and Y are 12bit,
-	 * Z (pressure) is 8 bit. However, the fields are defined up
-	 * to 14 bits for future possible expansion.
-	 */
-	input_set_abs_params(input_dev, ABS_X, 0, 0x0FFF, 2, 0);
-	input_set_abs_params(input_dev, ABS_Y, 0, 0x0FFF, 2, 0);
-	input_set_abs_params(input_dev, ABS_PRESSURE, 0, 0xFF, 2, 0);
-
-	/* initialise the URB so we can read from the transport stream */
-	pipe = usb_rcvintpipe(itmtouch->usbdev, endpoint->bEndpointAddress);
-	maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe));
-
-	if (maxp > ITM_BUFSIZE)
-		maxp = ITM_BUFSIZE;
-
-	itmtouch->readurb = usb_alloc_urb(0, GFP_KERNEL);
-	if (!itmtouch->readurb) {
-		dbg("%s - usb_alloc_urb failed: itmtouch->readurb", __FUNCTION__);
-		goto fail;
-	}
-
-	usb_fill_int_urb(itmtouch->readurb, itmtouch->usbdev, pipe, itmtouch->rbuf,
-			 maxp, itmtouch_irq, itmtouch, endpoint->bInterval);
-
-	input_register_device(itmtouch->inputdev);
-
-	usb_set_intfdata(intf, itmtouch);
-
-	return 0;
-
- fail:	input_free_device(input_dev);
-	kfree(itmtouch);
-	return -ENOMEM;
-}
-
-static void itmtouch_disconnect(struct usb_interface *intf)
-{
-	struct itmtouch_dev *itmtouch = usb_get_intfdata(intf);
-
-	usb_set_intfdata(intf, NULL);
-
-	if (itmtouch) {
-		input_unregister_device(itmtouch->inputdev);
-		usb_kill_urb(itmtouch->readurb);
-		usb_free_urb(itmtouch->readurb);
-		kfree(itmtouch);
-	}
-}
-
-MODULE_DEVICE_TABLE(usb, itmtouch_ids);
-
-static struct usb_driver itmtouch_driver = {
-	.name =         "itmtouch",
-	.probe =        itmtouch_probe,
-	.disconnect =   itmtouch_disconnect,
-	.id_table =     itmtouch_ids,
-};
-
-static int __init itmtouch_init(void)
-{
-	info(DRIVER_DESC " " DRIVER_VERSION);
-	info(DRIVER_AUTHOR);
-	return usb_register(&itmtouch_driver);
-}
-
-static void __exit itmtouch_exit(void)
-{
-	usb_deregister(&itmtouch_driver);
-}
-
-module_init(itmtouch_init);
-module_exit(itmtouch_exit);
diff --git a/drivers/usb/input/kbtab.c b/drivers/usb/input/kbtab.c
index fedbcb1..c4781b9 100644
--- a/drivers/usb/input/kbtab.c
+++ b/drivers/usb/input/kbtab.c
@@ -100,7 +100,7 @@
 
 static int kbtab_open(struct input_dev *dev)
 {
-	struct kbtab *kbtab = dev->private;
+	struct kbtab *kbtab = input_get_drvdata(dev);
 
 	kbtab->irq->dev = kbtab->usbdev;
 	if (usb_submit_urb(kbtab->irq, GFP_KERNEL))
@@ -111,7 +111,7 @@
 
 static void kbtab_close(struct input_dev *dev)
 {
-	struct kbtab *kbtab = dev->private;
+	struct kbtab *kbtab = input_get_drvdata(dev);
 
 	usb_kill_urb(kbtab->irq);
 }
@@ -122,6 +122,7 @@
 	struct usb_endpoint_descriptor *endpoint;
 	struct kbtab *kbtab;
 	struct input_dev *input_dev;
+	int error = -ENOMEM;
 
 	kbtab = kzalloc(sizeof(struct kbtab), GFP_KERNEL);
 	input_dev = input_allocate_device();
@@ -145,8 +146,9 @@
 	input_dev->name = "KB Gear Tablet";
 	input_dev->phys = kbtab->phys;
 	usb_to_input_id(dev, &input_dev->id);
-	input_dev->cdev.dev = &intf->dev;
-	input_dev->private = kbtab;
+	input_dev->dev.parent = &intf->dev;
+
+	input_set_drvdata(input_dev, kbtab);
 
 	input_dev->open = kbtab_open;
 	input_dev->close = kbtab_close;
@@ -168,15 +170,19 @@
 	kbtab->irq->transfer_dma = kbtab->data_dma;
 	kbtab->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 
-	input_register_device(kbtab->dev);
+	error = input_register_device(kbtab->dev);
+	if (error)
+		goto fail3;
 
 	usb_set_intfdata(intf, kbtab);
+
 	return 0;
 
-fail2:	usb_buffer_free(dev, 10, kbtab->data, kbtab->data_dma);
-fail1:	input_free_device(input_dev);
+ fail3:	usb_free_urb(kbtab->irq);
+ fail2:	usb_buffer_free(dev, 10, kbtab->data, kbtab->data_dma);
+ fail1:	input_free_device(input_dev);
 	kfree(kbtab);
-	return -ENOMEM;
+	return error;
 }
 
 static void kbtab_disconnect(struct usb_interface *intf)
diff --git a/drivers/usb/input/keyspan_remote.c b/drivers/usb/input/keyspan_remote.c
index 98bd323..1bffc9f 100644
--- a/drivers/usb/input/keyspan_remote.c
+++ b/drivers/usb/input/keyspan_remote.c
@@ -394,7 +394,7 @@
 
 static int keyspan_open(struct input_dev *dev)
 {
-	struct usb_keyspan *remote = dev->private;
+	struct usb_keyspan *remote = input_get_drvdata(dev);
 
 	remote->irq_urb->dev = remote->udev;
 	if (usb_submit_urb(remote->irq_urb, GFP_KERNEL))
@@ -405,7 +405,7 @@
 
 static void keyspan_close(struct input_dev *dev)
 {
-	struct usb_keyspan *remote = dev->private;
+	struct usb_keyspan *remote = input_get_drvdata(dev);
 
 	usb_kill_urb(remote->irq_urb);
 }
@@ -437,7 +437,7 @@
 	struct usb_endpoint_descriptor *endpoint;
 	struct usb_keyspan *remote;
 	struct input_dev *input_dev;
-	int i, retval;
+	int i, error;
 
 	endpoint = keyspan_get_in_endpoint(interface->cur_altsetting);
 	if (!endpoint)
@@ -446,7 +446,7 @@
 	remote = kzalloc(sizeof(*remote), GFP_KERNEL);
 	input_dev = input_allocate_device();
 	if (!remote || !input_dev) {
-		retval = -ENOMEM;
+		error = -ENOMEM;
 		goto fail1;
 	}
 
@@ -458,19 +458,19 @@
 
 	remote->in_buffer = usb_buffer_alloc(udev, RECV_SIZE, GFP_ATOMIC, &remote->in_dma);
 	if (!remote->in_buffer) {
-		retval = -ENOMEM;
+		error = -ENOMEM;
 		goto fail1;
 	}
 
 	remote->irq_urb = usb_alloc_urb(0, GFP_KERNEL);
 	if (!remote->irq_urb) {
-		retval = -ENOMEM;
+		error = -ENOMEM;
 		goto fail2;
 	}
 
-	retval = keyspan_setup(udev);
-	if (retval) {
-		retval = -ENODEV;
+	error = keyspan_setup(udev);
+	if (error) {
+		error = -ENODEV;
 		goto fail3;
 	}
 
@@ -495,14 +495,15 @@
 	input_dev->name = remote->name;
 	input_dev->phys = remote->phys;
 	usb_to_input_id(udev, &input_dev->id);
-	input_dev->cdev.dev = &interface->dev;
+	input_dev->dev.parent = &interface->dev;
 
 	input_dev->evbit[0] = BIT(EV_KEY);		/* We will only report KEY events. */
 	for (i = 0; i < ARRAY_SIZE(keyspan_key_table); i++)
 		if (keyspan_key_table[i] != KEY_RESERVED)
 			set_bit(keyspan_key_table[i], input_dev->keybit);
 
-	input_dev->private = remote;
+	input_set_drvdata(input_dev, remote);
+
 	input_dev->open = keyspan_open;
 	input_dev->close = keyspan_close;
 
@@ -517,7 +518,9 @@
 	remote->irq_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 
 	/* we can register the device now, as it is ready */
-	input_register_device(remote->input);
+	error = input_register_device(remote->input);
+	if (error)
+		goto fail3;
 
 	/* save our data pointer in this interface device */
 	usb_set_intfdata(interface, remote);
@@ -529,7 +532,7 @@
  fail1:	kfree(remote);
 	input_free_device(input_dev);
 
-	return retval;
+	return error;
 }
 
 /*
diff --git a/drivers/usb/input/mtouchusb.c b/drivers/usb/input/mtouchusb.c
deleted file mode 100644
index 92c4e07..0000000
--- a/drivers/usb/input/mtouchusb.c
+++ /dev/null
@@ -1,332 +0,0 @@
-/******************************************************************************
- * mtouchusb.c  --  Driver for Microtouch (Now 3M) USB Touchscreens
- *
- * This program is free software; you can redistribute it and/or
- * 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.
- *
- * Based upon original work by Radoslaw Garbacz (usb-support@ite.pl)
- *  (http://freshmeat.net/projects/3mtouchscreendriver)
- *
- * History
- *
- *  0.3 & 0.4  2002 (TEJ) tejohnson@yahoo.com
- *    Updated to 2.4.18, then 2.4.19
- *    Old version still relied on stealing a minor
- *
- *  0.5  02/26/2004 (TEJ) tejohnson@yahoo.com
- *    Complete rewrite using Linux Input in 2.6.3
- *    Unfortunately no calibration support at this time
- *
- *  1.4 04/25/2004 (TEJ) tejohnson@yahoo.com
- *    Changed reset from standard USB dev reset to vendor reset
- *    Changed data sent to host from compensated to raw coordinates
- *    Eliminated vendor/product module params
- *    Performed multiple successful tests with an EXII-5010UC
- *
- *  1.5 02/27/2005 ddstreet@ieee.org
- *    Added module parameter to select raw or hw-calibrated coordinate reporting
- *
- *****************************************************************************/
-
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/usb/input.h>
-
-#define MTOUCHUSB_MIN_XC                0x0
-#define MTOUCHUSB_MAX_RAW_XC            0x4000
-#define MTOUCHUSB_MAX_CALIB_XC          0xffff
-#define MTOUCHUSB_XC_FUZZ               0x0
-#define MTOUCHUSB_XC_FLAT               0x0
-#define MTOUCHUSB_MIN_YC                0x0
-#define MTOUCHUSB_MAX_RAW_YC            0x4000
-#define MTOUCHUSB_MAX_CALIB_YC          0xffff
-#define MTOUCHUSB_YC_FUZZ               0x0
-#define MTOUCHUSB_YC_FLAT               0x0
-
-#define MTOUCHUSB_ASYNC_REPORT          1
-#define MTOUCHUSB_RESET                 7
-#define MTOUCHUSB_REPORT_DATA_SIZE      11
-#define MTOUCHUSB_REQ_CTRLLR_ID         10
-
-#define MTOUCHUSB_GET_RAW_XC(data)      (data[8]<<8 | data[7])
-#define MTOUCHUSB_GET_CALIB_XC(data)    (data[4]<<8 | data[3])
-#define MTOUCHUSB_GET_RAW_YC(data)      (data[10]<<8 | data[9])
-#define MTOUCHUSB_GET_CALIB_YC(data)    (data[6]<<8 | data[5])
-#define MTOUCHUSB_GET_XC(data)          (raw_coordinates ? \
-                                         MTOUCHUSB_GET_RAW_XC(data) : \
-                                         MTOUCHUSB_GET_CALIB_XC(data))
-#define MTOUCHUSB_GET_YC(data)          (raw_coordinates ? \
-                                         MTOUCHUSB_GET_RAW_YC(data) : \
-                                         MTOUCHUSB_GET_CALIB_YC(data))
-#define MTOUCHUSB_GET_TOUCHED(data)     ((data[2] & 0x40) ? 1:0)
-
-#define DRIVER_VERSION "v1.5"
-#define DRIVER_AUTHOR "Todd E. Johnson, tejohnson@yahoo.com"
-#define DRIVER_DESC "3M USB Touchscreen Driver"
-#define DRIVER_LICENSE "GPL"
-
-static int raw_coordinates = 1;
-
-module_param(raw_coordinates, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(raw_coordinates, "report raw coordinate values (y, default) or hardware-calibrated coordinate values (n)");
-
-struct mtouch_usb {
-	unsigned char *data;
-	dma_addr_t data_dma;
-	struct urb *irq;
-	struct usb_device *udev;
-	struct input_dev *input;
-	char name[128];
-	char phys[64];
-};
-
-static struct usb_device_id mtouchusb_devices[] = {
-	{ USB_DEVICE(0x0596, 0x0001) },
-	{ }
-};
-
-static void mtouchusb_irq(struct urb *urb)
-{
-	struct mtouch_usb *mtouch = urb->context;
-	int retval;
-
-	switch (urb->status) {
-	case 0:
-		/* success */
-		break;
-	case -ETIME:
-		/* this urb is timing out */
-		dbg("%s - urb timed out - was the device unplugged?",
-		    __FUNCTION__);
-		return;
-	case -ECONNRESET:
-	case -ENOENT:
-	case -ESHUTDOWN:
-		/* this urb is terminated, clean up */
-		dbg("%s - urb shutting down with status: %d",
-		    __FUNCTION__, urb->status);
-		return;
-	default:
-		dbg("%s - nonzero urb status received: %d",
-		    __FUNCTION__, urb->status);
-		goto exit;
-	}
-
-	input_report_key(mtouch->input, BTN_TOUCH,
-			 MTOUCHUSB_GET_TOUCHED(mtouch->data));
-	input_report_abs(mtouch->input, ABS_X, MTOUCHUSB_GET_XC(mtouch->data));
-	input_report_abs(mtouch->input, ABS_Y,
-			 (raw_coordinates ? MTOUCHUSB_MAX_RAW_YC : MTOUCHUSB_MAX_CALIB_YC)
-			 - MTOUCHUSB_GET_YC(mtouch->data));
-	input_sync(mtouch->input);
-
-exit:
-	retval = usb_submit_urb(urb, GFP_ATOMIC);
-	if (retval)
-		err("%s - usb_submit_urb failed with result: %d",
-		    __FUNCTION__, retval);
-}
-
-static int mtouchusb_open(struct input_dev *input)
-{
-	struct mtouch_usb *mtouch = input->private;
-
-	mtouch->irq->dev = mtouch->udev;
-
-	if (usb_submit_urb(mtouch->irq, GFP_ATOMIC))
-		return -EIO;
-
-	return 0;
-}
-
-static void mtouchusb_close(struct input_dev *input)
-{
-	struct mtouch_usb *mtouch = input->private;
-
-	usb_kill_urb(mtouch->irq);
-}
-
-static int mtouchusb_alloc_buffers(struct usb_device *udev, struct mtouch_usb *mtouch)
-{
-	dbg("%s - called", __FUNCTION__);
-
-	mtouch->data = usb_buffer_alloc(udev, MTOUCHUSB_REPORT_DATA_SIZE,
-					GFP_ATOMIC, &mtouch->data_dma);
-
-	if (!mtouch->data)
-		return -1;
-
-	return 0;
-}
-
-static void mtouchusb_free_buffers(struct usb_device *udev, struct mtouch_usb *mtouch)
-{
-	dbg("%s - called", __FUNCTION__);
-
-	if (mtouch->data)
-		usb_buffer_free(udev, MTOUCHUSB_REPORT_DATA_SIZE,
-				mtouch->data, mtouch->data_dma);
-}
-
-static int mtouchusb_probe(struct usb_interface *intf, const struct usb_device_id *id)
-{
-	struct mtouch_usb *mtouch;
-	struct input_dev *input_dev;
-	struct usb_host_interface *interface;
-	struct usb_endpoint_descriptor *endpoint;
-	struct usb_device *udev = interface_to_usbdev(intf);
-	int nRet;
-
-	dbg("%s - called", __FUNCTION__);
-
-	dbg("%s - setting interface", __FUNCTION__);
-	interface = intf->cur_altsetting;
-
-	dbg("%s - setting endpoint", __FUNCTION__);
-	endpoint = &interface->endpoint[0].desc;
-
-	mtouch = kzalloc(sizeof(struct mtouch_usb), GFP_KERNEL);
-	input_dev = input_allocate_device();
-	if (!mtouch || !input_dev) {
-		err("%s - Out of memory.", __FUNCTION__);
-		goto fail1;
-	}
-
-	dbg("%s - allocating buffers", __FUNCTION__);
-	if (mtouchusb_alloc_buffers(udev, mtouch))
-		goto fail2;
-
-	mtouch->udev = udev;
-	mtouch->input = input_dev;
-
-	if (udev->manufacturer)
-		strlcpy(mtouch->name, udev->manufacturer, sizeof(mtouch->name));
-
-	if (udev->product) {
-		if (udev->manufacturer)
-			strlcat(mtouch->name, " ", sizeof(mtouch->name));
-		strlcat(mtouch->name, udev->product, sizeof(mtouch->name));
-	}
-
-	if (!strlen(mtouch->name))
-		snprintf(mtouch->name, sizeof(mtouch->name),
-			"USB Touchscreen %04x:%04x",
-			le16_to_cpu(udev->descriptor.idVendor),
-			le16_to_cpu(udev->descriptor.idProduct));
-
-	usb_make_path(udev, mtouch->phys, sizeof(mtouch->phys));
-	strlcpy(mtouch->phys, "/input0", sizeof(mtouch->phys));
-
-	input_dev->name = mtouch->name;
-	input_dev->phys = mtouch->phys;
-	usb_to_input_id(udev, &input_dev->id);
-	input_dev->cdev.dev = &intf->dev;
-	input_dev->private = mtouch;
-
-	input_dev->open = mtouchusb_open;
-	input_dev->close = mtouchusb_close;
-
-	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
-	input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
-	input_set_abs_params(input_dev, ABS_X, MTOUCHUSB_MIN_XC,
-		raw_coordinates ? MTOUCHUSB_MAX_RAW_XC : MTOUCHUSB_MAX_CALIB_XC,
-				MTOUCHUSB_XC_FUZZ, MTOUCHUSB_XC_FLAT);
-	input_set_abs_params(input_dev, ABS_Y, MTOUCHUSB_MIN_YC,
-		raw_coordinates ? MTOUCHUSB_MAX_RAW_YC : MTOUCHUSB_MAX_CALIB_YC,
-		MTOUCHUSB_YC_FUZZ, MTOUCHUSB_YC_FLAT);
-
-	nRet = usb_control_msg(mtouch->udev, usb_rcvctrlpipe(udev, 0),
-			       MTOUCHUSB_RESET,
-			       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-			       1, 0, NULL, 0, USB_CTRL_SET_TIMEOUT);
-	dbg("%s - usb_control_msg - MTOUCHUSB_RESET - bytes|err: %d",
-	    __FUNCTION__, nRet);
-
-	dbg("%s - usb_alloc_urb: mtouch->irq", __FUNCTION__);
-	mtouch->irq = usb_alloc_urb(0, GFP_KERNEL);
-	if (!mtouch->irq) {
-		dbg("%s - usb_alloc_urb failed: mtouch->irq", __FUNCTION__);
-		goto fail2;
-	}
-
-	dbg("%s - usb_fill_int_urb", __FUNCTION__);
-	usb_fill_int_urb(mtouch->irq, mtouch->udev,
-			 usb_rcvintpipe(mtouch->udev, 0x81),
-			 mtouch->data, MTOUCHUSB_REPORT_DATA_SIZE,
-			 mtouchusb_irq, mtouch, endpoint->bInterval);
-
-	dbg("%s - input_register_device", __FUNCTION__);
-	input_register_device(mtouch->input);
-
-	nRet = usb_control_msg(mtouch->udev, usb_rcvctrlpipe(udev, 0),
-			       MTOUCHUSB_ASYNC_REPORT,
-			       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-			       1, 1, NULL, 0, USB_CTRL_SET_TIMEOUT);
-	dbg("%s - usb_control_msg - MTOUCHUSB_ASYNC_REPORT - bytes|err: %d",
-	    __FUNCTION__, nRet);
-
-	usb_set_intfdata(intf, mtouch);
-	return 0;
-
-fail2:	mtouchusb_free_buffers(udev, mtouch);
-fail1:	input_free_device(input_dev);
-	kfree(mtouch);
-	return -ENOMEM;
-}
-
-static void mtouchusb_disconnect(struct usb_interface *intf)
-{
-	struct mtouch_usb *mtouch = usb_get_intfdata(intf);
-
-	dbg("%s - called", __FUNCTION__);
-	usb_set_intfdata(intf, NULL);
-	if (mtouch) {
-		dbg("%s - mtouch is initialized, cleaning up", __FUNCTION__);
-		usb_kill_urb(mtouch->irq);
-		input_unregister_device(mtouch->input);
-		usb_free_urb(mtouch->irq);
-		mtouchusb_free_buffers(interface_to_usbdev(intf), mtouch);
-		kfree(mtouch);
-	}
-}
-
-MODULE_DEVICE_TABLE(usb, mtouchusb_devices);
-
-static struct usb_driver mtouchusb_driver = {
-	.name		= "mtouchusb",
-	.probe		= mtouchusb_probe,
-	.disconnect	= mtouchusb_disconnect,
-	.id_table	= mtouchusb_devices,
-};
-
-static int __init mtouchusb_init(void)
-{
-	dbg("%s - called", __FUNCTION__);
-	return usb_register(&mtouchusb_driver);
-}
-
-static void __exit mtouchusb_cleanup(void)
-{
-	dbg("%s - called", __FUNCTION__);
-	usb_deregister(&mtouchusb_driver);
-}
-
-module_init(mtouchusb_init);
-module_exit(mtouchusb_cleanup);
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL");
diff --git a/drivers/usb/input/powermate.c b/drivers/usb/input/powermate.c
index fea97e5..4f93a76 100644
--- a/drivers/usb/input/powermate.c
+++ b/drivers/usb/input/powermate.c
@@ -252,7 +252,7 @@
 static int powermate_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int _value)
 {
 	unsigned int command = (unsigned int)_value;
-	struct powermate_device *pm = dev->private;
+	struct powermate_device *pm = input_get_drvdata(dev);
 
 	if (type == EV_MSC && code == MSC_PULSELED){
 		/*
@@ -308,7 +308,7 @@
 	struct powermate_device *pm;
 	struct input_dev *input_dev;
 	int pipe, maxp;
-	int err = -ENOMEM;
+	int error = -ENOMEM;
 
 	interface = intf->cur_altsetting;
 	endpoint = &interface->endpoint[0].desc;
@@ -359,8 +359,9 @@
 
 	input_dev->phys = pm->phys;
 	usb_to_input_id(udev, &input_dev->id);
-	input_dev->cdev.dev = &intf->dev;
-	input_dev->private = pm;
+	input_dev->dev.parent = &intf->dev;
+
+	input_set_drvdata(input_dev, pm);
 
 	input_dev->event = powermate_input_event;
 
@@ -387,11 +388,14 @@
 
 	/* register our interrupt URB with the USB system */
 	if (usb_submit_urb(pm->irq, GFP_KERNEL)) {
-		err = -EIO;
+		error = -EIO;
 		goto fail4;
 	}
 
-	input_register_device(pm->input);
+	error = input_register_device(pm->input);
+	if (error)
+		goto fail5;
+
 
 	/* force an update of everything */
 	pm->requires_update = UPDATE_PULSE_ASLEEP | UPDATE_PULSE_AWAKE | UPDATE_PULSE_MODE | UPDATE_STATIC_BRIGHTNESS;
@@ -400,12 +404,13 @@
 	usb_set_intfdata(intf, pm);
 	return 0;
 
-fail4:	usb_free_urb(pm->config);
-fail3:	usb_free_urb(pm->irq);
-fail2:	powermate_free_buffers(udev, pm);
-fail1:	input_free_device(input_dev);
+ fail5:	usb_kill_urb(pm->irq);
+ fail4:	usb_free_urb(pm->config);
+ fail3:	usb_free_urb(pm->irq);
+ fail2:	powermate_free_buffers(udev, pm);
+ fail1:	input_free_device(input_dev);
 	kfree(pm);
-	return err;
+	return error;
 }
 
 /* Called when a USB device we've accepted ownership of is removed */
diff --git a/drivers/usb/input/touchkitusb.c b/drivers/usb/input/touchkitusb.c
deleted file mode 100644
index 2a314b0..0000000
--- a/drivers/usb/input/touchkitusb.c
+++ /dev/null
@@ -1,392 +0,0 @@
-/******************************************************************************
- * touchkitusb.c  --  Driver for eGalax TouchKit USB Touchscreens
- *
- * Copyright (C) 2004-2005 by Daniel Ritz <daniel.ritz@gmx.ch>
- * Copyright (C) by Todd E. Johnson (mtouchusb.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., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Based upon mtouchusb.c
- *
- *****************************************************************************/
-
-//#define DEBUG
-
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/usb/input.h>
-
-#define TOUCHKIT_MIN_XC			0x0
-#define TOUCHKIT_MAX_XC			0x07ff
-#define TOUCHKIT_XC_FUZZ		0x0
-#define TOUCHKIT_XC_FLAT		0x0
-#define TOUCHKIT_MIN_YC			0x0
-#define TOUCHKIT_MAX_YC			0x07ff
-#define TOUCHKIT_YC_FUZZ		0x0
-#define TOUCHKIT_YC_FLAT		0x0
-#define TOUCHKIT_REPORT_DATA_SIZE	16
-
-#define TOUCHKIT_DOWN			0x01
-
-#define TOUCHKIT_PKT_TYPE_MASK		0xFE
-#define TOUCHKIT_PKT_TYPE_REPT		0x80
-#define TOUCHKIT_PKT_TYPE_DIAG		0x0A
-
-#define DRIVER_VERSION			"v0.1"
-#define DRIVER_AUTHOR			"Daniel Ritz <daniel.ritz@gmx.ch>"
-#define DRIVER_DESC			"eGalax TouchKit USB HID Touchscreen Driver"
-
-static int swap_xy;
-module_param(swap_xy, bool, 0644);
-MODULE_PARM_DESC(swap_xy, "If set X and Y axes are swapped.");
-
-struct touchkit_usb {
-	unsigned char *data;
-	dma_addr_t data_dma;
-	char buffer[TOUCHKIT_REPORT_DATA_SIZE];
-	int buf_len;
-	struct urb *irq;
-	struct usb_device *udev;
-	struct input_dev *input;
-	char name[128];
-	char phys[64];
-};
-
-static struct usb_device_id touchkit_devices[] = {
-	{USB_DEVICE(0x3823, 0x0001)},
-	{USB_DEVICE(0x0123, 0x0001)},
-	{USB_DEVICE(0x0eef, 0x0001)},
-	{USB_DEVICE(0x0eef, 0x0002)},
-	{}
-};
-
-/* helpers to read the data */
-static inline int touchkit_get_touched(char *data)
-{
-	return (data[0] & TOUCHKIT_DOWN) ? 1 : 0;
-}
-
-static inline int touchkit_get_x(char *data)
-{
-	return ((data[3] & 0x0F) << 7) | (data[4] & 0x7F);
-}
-
-static inline int touchkit_get_y(char *data)
-{
-	return ((data[1] & 0x0F) << 7) | (data[2] & 0x7F);
-}
-
-
-/* processes one input packet. */
-static void touchkit_process_pkt(struct touchkit_usb *touchkit, char *pkt)
-{
-	int x, y;
-
-	/* only process report packets */
-	if ((pkt[0] & TOUCHKIT_PKT_TYPE_MASK) != TOUCHKIT_PKT_TYPE_REPT)
-		return;
-
-	if (swap_xy) {
-		y = touchkit_get_x(pkt);
-		x = touchkit_get_y(pkt);
-	} else {
-		x = touchkit_get_x(pkt);
-		y = touchkit_get_y(pkt);
-	}
-
-	input_report_key(touchkit->input, BTN_TOUCH, touchkit_get_touched(pkt));
-	input_report_abs(touchkit->input, ABS_X, x);
-	input_report_abs(touchkit->input, ABS_Y, y);
-	input_sync(touchkit->input);
-}
-
-
-static int touchkit_get_pkt_len(char *buf)
-{
-	switch (buf[0] & TOUCHKIT_PKT_TYPE_MASK) {
-	case TOUCHKIT_PKT_TYPE_REPT:
-		return 5;
-
-	case TOUCHKIT_PKT_TYPE_DIAG:
-		return buf[1] + 2;
-	}
-
-	return 0;
-}
-
-static void touchkit_process(struct touchkit_usb *touchkit, int len)
-{
-	char *buffer;
-	int pkt_len, buf_len, pos;
-
-	/* if the buffer contains data, append */
-	if (unlikely(touchkit->buf_len)) {
-		int tmp;
-
-		/* if only 1 byte in buffer, add another one to get length */
-		if (touchkit->buf_len == 1)
-			touchkit->buffer[1] = touchkit->data[0];
-
-		pkt_len = touchkit_get_pkt_len(touchkit->buffer);
-
-		/* unknown packet: drop everything */
-		if (!pkt_len)
-			return;
-
-		/* append, process */
-		tmp = pkt_len - touchkit->buf_len;
-		memcpy(touchkit->buffer + touchkit->buf_len, touchkit->data, tmp);
-		touchkit_process_pkt(touchkit, touchkit->buffer);
-
-		buffer = touchkit->data + tmp;
-		buf_len = len - tmp;
-	} else {
-		buffer = touchkit->data;
-		buf_len = len;
-	}
-
-	/* only one byte left in buffer */
-	if (unlikely(buf_len == 1)) {
-		touchkit->buffer[0] = buffer[0];
-		touchkit->buf_len = 1;
-		return;
-	}
-
-	/* loop over the buffer */
-	pos = 0;
-	while (pos < buf_len) {
-		/* get packet len */
-		pkt_len = touchkit_get_pkt_len(buffer + pos);
-
-		/* unknown packet: drop everything */
-		if (unlikely(!pkt_len))
-			return;
-
-		/* full packet: process */
-		if (likely(pkt_len <= buf_len)) {
-			touchkit_process_pkt(touchkit, buffer + pos);
-		} else {
-			/* incomplete packet: save in buffer */
-			memcpy(touchkit->buffer, buffer + pos, buf_len - pos);
-			touchkit->buf_len = buf_len - pos;
-		}
-		pos += pkt_len;
-	}
-}
-
-
-static void touchkit_irq(struct urb *urb)
-{
-	struct touchkit_usb *touchkit = urb->context;
-	int retval;
-
-	switch (urb->status) {
-	case 0:
-		/* success */
-		break;
-	case -ETIME:
-		/* this urb is timing out */
-		dbg("%s - urb timed out - was the device unplugged?",
-		    __FUNCTION__);
-		return;
-	case -ECONNRESET:
-	case -ENOENT:
-	case -ESHUTDOWN:
-		/* this urb is terminated, clean up */
-		dbg("%s - urb shutting down with status: %d",
-		    __FUNCTION__, urb->status);
-		return;
-	default:
-		dbg("%s - nonzero urb status received: %d",
-		    __FUNCTION__, urb->status);
-		goto exit;
-	}
-
-	touchkit_process(touchkit, urb->actual_length);
-
-exit:
-	retval = usb_submit_urb(urb, GFP_ATOMIC);
-	if (retval)
-		err("%s - usb_submit_urb failed with result: %d",
-		    __FUNCTION__, retval);
-}
-
-static int touchkit_open(struct input_dev *input)
-{
-	struct touchkit_usb *touchkit = input->private;
-
-	touchkit->irq->dev = touchkit->udev;
-
-	if (usb_submit_urb(touchkit->irq, GFP_ATOMIC))
-		return -EIO;
-
-	return 0;
-}
-
-static void touchkit_close(struct input_dev *input)
-{
-	struct touchkit_usb *touchkit = input->private;
-
-	usb_kill_urb(touchkit->irq);
-}
-
-static int touchkit_alloc_buffers(struct usb_device *udev,
-				  struct touchkit_usb *touchkit)
-{
-	touchkit->data = usb_buffer_alloc(udev, TOUCHKIT_REPORT_DATA_SIZE,
-	                                  GFP_ATOMIC, &touchkit->data_dma);
-
-	if (!touchkit->data)
-		return -1;
-
-	return 0;
-}
-
-static void touchkit_free_buffers(struct usb_device *udev,
-				  struct touchkit_usb *touchkit)
-{
-	if (touchkit->data)
-		usb_buffer_free(udev, TOUCHKIT_REPORT_DATA_SIZE,
-		                touchkit->data, touchkit->data_dma);
-}
-
-static int touchkit_probe(struct usb_interface *intf,
-			  const struct usb_device_id *id)
-{
-	struct touchkit_usb *touchkit;
-	struct input_dev *input_dev;
-	struct usb_host_interface *interface;
-	struct usb_endpoint_descriptor *endpoint;
-	struct usb_device *udev = interface_to_usbdev(intf);
-
-	interface = intf->cur_altsetting;
-	endpoint = &interface->endpoint[0].desc;
-
-	touchkit = kzalloc(sizeof(struct touchkit_usb), GFP_KERNEL);
-	input_dev = input_allocate_device();
-	if (!touchkit || !input_dev)
-		goto out_free;
-
-	if (touchkit_alloc_buffers(udev, touchkit))
-		goto out_free;
-
-	touchkit->irq = usb_alloc_urb(0, GFP_KERNEL);
-	if (!touchkit->irq) {
-		dbg("%s - usb_alloc_urb failed: touchkit->irq", __FUNCTION__);
-		goto out_free_buffers;
-	}
-
-	touchkit->udev = udev;
-	touchkit->input = input_dev;
-
-	if (udev->manufacturer)
-		strlcpy(touchkit->name, udev->manufacturer, sizeof(touchkit->name));
-
-	if (udev->product) {
-		if (udev->manufacturer)
-			strlcat(touchkit->name, " ", sizeof(touchkit->name));
-		strlcat(touchkit->name, udev->product, sizeof(touchkit->name));
-	}
-
-	if (!strlen(touchkit->name))
-		snprintf(touchkit->name, sizeof(touchkit->name),
-			"USB Touchscreen %04x:%04x",
-			 le16_to_cpu(udev->descriptor.idVendor),
-			 le16_to_cpu(udev->descriptor.idProduct));
-
-	usb_make_path(udev, touchkit->phys, sizeof(touchkit->phys));
-	strlcpy(touchkit->phys, "/input0", sizeof(touchkit->phys));
-
-	input_dev->name = touchkit->name;
-	input_dev->phys = touchkit->phys;
-	usb_to_input_id(udev, &input_dev->id);
-	input_dev->cdev.dev = &intf->dev;
-	input_dev->private = touchkit;
-	input_dev->open = touchkit_open;
-	input_dev->close = touchkit_close;
-
-	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
-	input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
-	input_set_abs_params(input_dev, ABS_X, TOUCHKIT_MIN_XC, TOUCHKIT_MAX_XC,
-				TOUCHKIT_XC_FUZZ, TOUCHKIT_XC_FLAT);
-	input_set_abs_params(input_dev, ABS_Y, TOUCHKIT_MIN_YC, TOUCHKIT_MAX_YC,
-				TOUCHKIT_YC_FUZZ, TOUCHKIT_YC_FLAT);
-
-	usb_fill_int_urb(touchkit->irq, touchkit->udev,
-			 usb_rcvintpipe(touchkit->udev, 0x81),
-			 touchkit->data, TOUCHKIT_REPORT_DATA_SIZE,
-			 touchkit_irq, touchkit, endpoint->bInterval);
-
-	touchkit->irq->transfer_dma = touchkit->data_dma;
-	touchkit->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
-
-	input_register_device(touchkit->input);
-
-	usb_set_intfdata(intf, touchkit);
-	return 0;
-
-out_free_buffers:
-	touchkit_free_buffers(udev, touchkit);
-out_free:
-	input_free_device(input_dev);
-	kfree(touchkit);
-	return -ENOMEM;
-}
-
-static void touchkit_disconnect(struct usb_interface *intf)
-{
-	struct touchkit_usb *touchkit = usb_get_intfdata(intf);
-
-	dbg("%s - called", __FUNCTION__);
-
-	if (!touchkit)
-		return;
-
-	dbg("%s - touchkit is initialized, cleaning up", __FUNCTION__);
-	usb_set_intfdata(intf, NULL);
-	usb_kill_urb(touchkit->irq);
-	input_unregister_device(touchkit->input);
-	usb_free_urb(touchkit->irq);
-	touchkit_free_buffers(interface_to_usbdev(intf), touchkit);
-	kfree(touchkit);
-}
-
-MODULE_DEVICE_TABLE(usb, touchkit_devices);
-
-static struct usb_driver touchkit_driver = {
-	.name		= "touchkitusb",
-	.probe		= touchkit_probe,
-	.disconnect	= touchkit_disconnect,
-	.id_table	= touchkit_devices,
-};
-
-static int __init touchkit_init(void)
-{
-	return usb_register(&touchkit_driver);
-}
-
-static void __exit touchkit_cleanup(void)
-{
-	usb_deregister(&touchkit_driver);
-}
-
-module_init(touchkit_init);
-module_exit(touchkit_cleanup);
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL");
diff --git a/drivers/usb/input/usbtouchscreen.c b/drivers/usb/input/usbtouchscreen.c
index 86e37a2..e082941 100644
--- a/drivers/usb/input/usbtouchscreen.c
+++ b/drivers/usb/input/usbtouchscreen.c
@@ -647,7 +647,7 @@
 
 static int usbtouch_open(struct input_dev *input)
 {
-	struct usbtouch_usb *usbtouch = input->private;
+	struct usbtouch_usb *usbtouch = input_get_drvdata(input);
 
 	usbtouch->irq->dev = usbtouch->udev;
 
@@ -659,7 +659,7 @@
 
 static void usbtouch_close(struct input_dev *input)
 {
-	struct usbtouch_usb *usbtouch = input->private;
+	struct usbtouch_usb *usbtouch = input_get_drvdata(input);
 
 	usb_kill_urb(usbtouch->irq);
 }
@@ -740,8 +740,10 @@
 	input_dev->name = usbtouch->name;
 	input_dev->phys = usbtouch->phys;
 	usb_to_input_id(udev, &input_dev->id);
-	input_dev->cdev.dev = &intf->dev;
-	input_dev->private = usbtouch;
+	input_dev->dev.parent = &intf->dev;
+
+	input_set_drvdata(input_dev, usbtouch);
+
 	input_dev->open = usbtouch_open;
 	input_dev->close = usbtouch_close;
 
diff --git a/drivers/usb/input/wacom_sys.c b/drivers/usb/input/wacom_sys.c
index 12b4274..1fe4820 100644
--- a/drivers/usb/input/wacom_sys.c
+++ b/drivers/usb/input/wacom_sys.c
@@ -122,7 +122,7 @@
 
 static int wacom_open(struct input_dev *dev)
 {
-	struct wacom *wacom = dev->private;
+	struct wacom *wacom = input_get_drvdata(dev);
 
 	wacom->irq->dev = wacom->usbdev;
 	if (usb_submit_urb(wacom->irq, GFP_KERNEL))
@@ -133,7 +133,7 @@
 
 static void wacom_close(struct input_dev *dev)
 {
-	struct wacom *wacom = dev->private;
+	struct wacom *wacom = input_get_drvdata(dev);
 
 	usb_kill_urb(wacom->irq);
 }
@@ -201,6 +201,7 @@
 	struct wacom *wacom;
 	struct wacom_wac *wacom_wac;
 	struct input_dev *input_dev;
+	int error = -ENOMEM;
 	char rep_data[2], limit = 0;
 
 	wacom = kzalloc(sizeof(struct wacom), GFP_KERNEL);
@@ -229,8 +230,10 @@
 	wacom->wacom_wac = wacom_wac;
 	usb_to_input_id(dev, &input_dev->id);
 
-	input_dev->cdev.dev = &intf->dev;
-	input_dev->private = wacom;
+	input_dev->dev.parent = &intf->dev;
+
+	input_set_drvdata(input_dev, wacom);
+
 	input_dev->open = wacom_open;
 	input_dev->close = wacom_close;
 
@@ -252,7 +255,9 @@
 	wacom->irq->transfer_dma = wacom->data_dma;
 	wacom->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 
-	input_register_device(wacom->dev);
+	error = input_register_device(wacom->dev);
+	if (error)
+		goto fail3;
 
 	/* Ask the tablet to report tablet data. Repeat until it succeeds */
 	do {
@@ -265,11 +270,12 @@
 	usb_set_intfdata(intf, wacom);
 	return 0;
 
-fail2:	usb_buffer_free(dev, 10, wacom_wac->data, wacom->data_dma);
-fail1:	input_free_device(input_dev);
+ fail3:	usb_free_urb(wacom->irq);
+ fail2:	usb_buffer_free(dev, 10, wacom_wac->data, wacom->data_dma);
+ fail1:	input_free_device(input_dev);
 	kfree(wacom);
 	kfree(wacom_wac);
-	return -ENOMEM;
+	return error;
 }
 
 static void wacom_disconnect(struct usb_interface *intf)
diff --git a/drivers/usb/input/xpad.c b/drivers/usb/input/xpad.c
index e4bc76e..7357239 100644
--- a/drivers/usb/input/xpad.c
+++ b/drivers/usb/input/xpad.c
@@ -267,7 +267,7 @@
 
 static int xpad_open (struct input_dev *dev)
 {
-	struct usb_xpad *xpad = dev->private;
+	struct usb_xpad *xpad = input_get_drvdata(dev);
 
 	xpad->irq_in->dev = xpad->udev;
 	if (usb_submit_urb(xpad->irq_in, GFP_KERNEL))
@@ -278,7 +278,7 @@
 
 static void xpad_close (struct input_dev *dev)
 {
-	struct usb_xpad *xpad = dev->private;
+	struct usb_xpad *xpad = input_get_drvdata(dev);
 
 	usb_kill_urb(xpad->irq_in);
 }
@@ -312,6 +312,7 @@
 	struct input_dev *input_dev;
 	struct usb_endpoint_descriptor *ep_irq_in;
 	int i;
+	int error = -ENOMEM;
 
 	for (i = 0; xpad_device[i].idVendor; i++) {
 		if ((le16_to_cpu(udev->descriptor.idVendor) == xpad_device[i].idVendor) &&
@@ -344,8 +345,10 @@
 	input_dev->name = xpad_device[i].name;
 	input_dev->phys = xpad->phys;
 	usb_to_input_id(udev, &input_dev->id);
-	input_dev->cdev.dev = &intf->dev;
-	input_dev->private = xpad;
+	input_dev->dev.parent = &intf->dev;
+
+	input_set_drvdata(input_dev, xpad);
+
 	input_dev->open = xpad_open;
 	input_dev->close = xpad_close;
 
@@ -373,15 +376,18 @@
 	xpad->irq_in->transfer_dma = xpad->idata_dma;
 	xpad->irq_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 
-	input_register_device(xpad->dev);
+	error = input_register_device(xpad->dev);
+	if (error)
+		goto fail3;
 
 	usb_set_intfdata(intf, xpad);
 	return 0;
 
-fail2:	usb_buffer_free(udev, XPAD_PKT_LEN, xpad->idata, xpad->idata_dma);
-fail1:	input_free_device(input_dev);
+ fail3:	usb_free_urb(xpad->irq_in);
+ fail2:	usb_buffer_free(udev, XPAD_PKT_LEN, xpad->idata, xpad->idata_dma);
+ fail1:	input_free_device(input_dev);
 	kfree(xpad);
-	return -ENOMEM;
+	return error;
 
 }
 
diff --git a/drivers/usb/input/yealink.c b/drivers/usb/input/yealink.c
index caff8e6..c54f1a5 100644
--- a/drivers/usb/input/yealink.c
+++ b/drivers/usb/input/yealink.c
@@ -502,7 +502,7 @@
 
 static int input_open(struct input_dev *dev)
 {
-	struct yealink_dev *yld = dev->private;
+	struct yealink_dev *yld = input_get_drvdata(dev);
 	int i, ret;
 
 	dbg("%s", __FUNCTION__);
@@ -529,7 +529,7 @@
 
 static void input_close(struct input_dev *dev)
 {
-	struct yealink_dev *yld = dev->private;
+	struct yealink_dev *yld = input_get_drvdata(dev);
 
 	usb_kill_urb(yld->urb_ctl);
 	usb_kill_urb(yld->urb_irq);
@@ -937,9 +937,10 @@
 	input_dev->name = nfo->name;
 	input_dev->phys = yld->phys;
 	usb_to_input_id(udev, &input_dev->id);
-	input_dev->cdev.dev = &intf->dev;
+	input_dev->dev.parent = &intf->dev;
 
-	input_dev->private = yld;
+	input_set_drvdata(input_dev, yld);
+
 	input_dev->open = input_open;
 	input_dev->close = input_close;
 	/* input_dev->event = input_ev;	TODO */
@@ -955,7 +956,9 @@
 		}
 	}
 
-	input_register_device(yld->idev);
+	ret = input_register_device(yld->idev);
+	if (ret)
+		return usb_cleanup(yld, ret);
 
 	usb_set_intfdata(intf, yld);
 
diff --git a/drivers/usb/net/kaweth.c b/drivers/usb/net/kaweth.c
index a0cc05d..60d2944 100644
--- a/drivers/usb/net/kaweth.c
+++ b/drivers/usb/net/kaweth.c
@@ -55,7 +55,6 @@
 #include <linux/usb.h>
 #include <linux/types.h>
 #include <linux/ethtool.h>
-#include <linux/pci.h>
 #include <linux/dma-mapping.h>
 #include <linux/wait.h>
 #include <asm/uaccess.h>
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index b1cb72c..d18b51f 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -389,7 +389,10 @@
 
 config FB_ATARI
 	bool "Atari native chipset support"
-	depends on (FB = y) && ATARI && BROKEN
+	depends on (FB = y) && ATARI
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
 	help
 	  This is the frame buffer device driver for the builtin graphics
 	  chipset found in Ataris.
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 760305c..8693517 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -63,7 +63,8 @@
 obj-$(CONFIG_FB_LEO)              += leo.o sbuslib.o
 obj-$(CONFIG_FB_SGIVW)            += sgivwfb.o
 obj-$(CONFIG_FB_ACORN)            += acornfb.o
-obj-$(CONFIG_FB_ATARI)            += atafb.o
+obj-$(CONFIG_FB_ATARI)            += atafb.o c2p.o atafb_mfb.o \
+                                     atafb_iplan2p2.o atafb_iplan2p4.o atafb_iplan2p8.o
 obj-$(CONFIG_FB_MAC)              += macfb.o
 obj-$(CONFIG_FB_HGA)              += hgafb.o
 obj-$(CONFIG_FB_IGA)              += igafb.o
diff --git a/drivers/video/atafb.c b/drivers/video/atafb.c
index bffe2b9..0038a05 100644
--- a/drivers/video/atafb.c
+++ b/drivers/video/atafb.c
@@ -2,7 +2,7 @@
  * linux/drivers/video/atafb.c -- Atari builtin chipset frame buffer device
  *
  *  Copyright (C) 1994 Martin Schaller & Roman Hodek
- *  
+ *
  * 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.
@@ -70,14 +70,8 @@
 #include <linux/fb.h>
 #include <asm/atarikb.h>
 
-#include <video/fbcon.h>
-#include <video/fbcon-cfb8.h>
-#include <video/fbcon-cfb16.h>
-#include <video/fbcon-iplan2p2.h>
-#include <video/fbcon-iplan2p4.h>
-#include <video/fbcon-iplan2p8.h>
-#include <video/fbcon-mfb.h>
-
+#include "c2p.h"
+#include "atafb.h"
 
 #define SWITCH_ACIA 0x01		/* modes for switch on OverScan */
 #define SWITCH_SND6 0x40
@@ -87,22 +81,48 @@
 
 #define up(x, r) (((x) + (r) - 1) & ~((r)-1))
 
+	/*
+	 * Interface to the world
+	 */
 
-static int default_par=0;	/* default resolution (0=none) */
+static int atafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info);
+static int atafb_set_par(struct fb_info *info);
+static int atafb_setcolreg(unsigned int regno, unsigned int red, unsigned int green,
+			   unsigned int blue, unsigned int transp,
+			   struct fb_info *info);
+static int atafb_blank(int blank, struct fb_info *info);
+static int atafb_pan_display(struct fb_var_screeninfo *var,
+			     struct fb_info *info);
+static void atafb_fillrect(struct fb_info *info,
+			   const struct fb_fillrect *rect);
+static void atafb_copyarea(struct fb_info *info,
+			   const struct fb_copyarea *region);
+static void atafb_imageblit(struct fb_info *info, const struct fb_image *image);
+static int atafb_ioctl(struct fb_info *info, unsigned int cmd,
+		       unsigned long arg);
 
-static unsigned long default_mem_req=0;
 
-static int hwscroll=-1;
+static int default_par;		/* default resolution (0=none) */
+
+static unsigned long default_mem_req;
+
+static int hwscroll = -1;
 
 static int use_hwscroll = 1;
 
-static int sttt_xres=640,st_yres=400,tt_yres=480;
-static int sttt_xres_virtual=640,sttt_yres_virtual=400;
-static int ovsc_offset=0, ovsc_addlen=0;
+static int sttt_xres = 640, st_yres = 400, tt_yres = 480;
+static int sttt_xres_virtual = 640, sttt_yres_virtual = 400;
+static int ovsc_offset, ovsc_addlen;
+
+	/*
+	 * Hardware parameters for current mode
+	 */
 
 static struct atafb_par {
 	void *screen_base;
 	int yres_virtual;
+	u_long next_line;
+	u_long next_plane;
 #if defined ATAFB_TT || defined ATAFB_STE
 	union {
 		struct {
@@ -138,7 +158,7 @@
 /* Don't calculate an own resolution, and thus don't change the one found when
  * booting (currently used for the Falcon to keep settings for internal video
  * hardware extensions (e.g. ScreenBlaster)  */
-static int DontCalcRes = 0; 
+static int DontCalcRes = 0;
 
 #ifdef ATAFB_FALCON
 #define HHT hw.falcon.hht
@@ -163,83 +183,84 @@
 #define VMO_PREMASK		0x0c
 #endif
 
-static struct fb_info fb_info;
+static struct fb_info fb_info = {
+	.fix = {
+		.id	= "Atari ",
+		.visual	= FB_VISUAL_PSEUDOCOLOR,
+		.accel	= FB_ACCEL_NONE,
+	}
+};
 
 static void *screen_base;	/* base address of screen */
 static void *real_screen_base;	/* (only for Overscan) */
 
 static int screen_len;
 
-static int current_par_valid=0; 
+static int current_par_valid;
 
-static int mono_moni=0;
-
-static struct display disp;
+static int mono_moni;
 
 
 #ifdef ATAFB_EXT
+
 /* external video handling */
+static unsigned int external_xres;
+static unsigned int external_xres_virtual;
+static unsigned int external_yres;
 
-static unsigned			external_xres;
-static unsigned			external_xres_virtual;
-static unsigned			external_yres;
-/* not needed - atafb will never support panning/hardwarescroll with external
- * static unsigned		external_yres_virtual;	
-*/
+/*
+ * not needed - atafb will never support panning/hardwarescroll with external
+ * static unsigned int external_yres_virtual;
+ */
+static unsigned int external_depth;
+static int external_pmode;
+static void *external_addr;
+static unsigned long external_len;
+static unsigned long external_vgaiobase;
+static unsigned int external_bitspercol = 6;
 
-static unsigned			external_depth;
-static int				external_pmode;
-static void *external_addr = 0;
-static unsigned long	external_len;
-static unsigned long	external_vgaiobase = 0;
-static unsigned int		external_bitspercol = 6;
-
-/* 
-JOE <joe@amber.dinoco.de>: 
-added card type for external driver, is only needed for
-colormap handling.
-*/
-
+/*
+ * JOE <joe@amber.dinoco.de>:
+ * added card type for external driver, is only needed for
+ * colormap handling.
+ */
 enum cardtype { IS_VGA, IS_MV300 };
 static enum cardtype external_card_type = IS_VGA;
 
 /*
-The MV300 mixes the color registers. So we need an array of munged
-indices in order to access the correct reg.
-*/
-static int MV300_reg_1bit[2]={0,1};
-static int MV300_reg_4bit[16]={
-0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15 };
-static int MV300_reg_8bit[256]={
-0, 128, 64, 192, 32, 160, 96, 224, 16, 144, 80, 208, 48, 176, 112, 240, 
-8, 136, 72, 200, 40, 168, 104, 232, 24, 152, 88, 216, 56, 184, 120, 248, 
-4, 132, 68, 196, 36, 164, 100, 228, 20, 148, 84, 212, 52, 180, 116, 244, 
-12, 140, 76, 204, 44, 172, 108, 236, 28, 156, 92, 220, 60, 188, 124, 252, 
-2, 130, 66, 194, 34, 162, 98, 226, 18, 146, 82, 210, 50, 178, 114, 242, 
-10, 138, 74, 202, 42, 170, 106, 234, 26, 154, 90, 218, 58, 186, 122, 250, 
-6, 134, 70, 198, 38, 166, 102, 230, 22, 150, 86, 214, 54, 182, 118, 246, 
-14, 142, 78, 206, 46, 174, 110, 238, 30, 158, 94, 222, 62, 190, 126, 254, 
-1, 129, 65, 193, 33, 161, 97, 225, 17, 145, 81, 209, 49, 177, 113, 241, 
-9, 137, 73, 201, 41, 169, 105, 233, 25, 153, 89, 217, 57, 185, 121, 249, 
-5, 133, 69, 197, 37, 165, 101, 229, 21, 149, 85, 213, 53, 181, 117, 245, 
-13, 141, 77, 205, 45, 173, 109, 237, 29, 157, 93, 221, 61, 189, 125, 253, 
-3, 131, 67, 195, 35, 163, 99, 227, 19, 147, 83, 211, 51, 179, 115, 243, 
-11, 139, 75, 203, 43, 171, 107, 235, 27, 155, 91, 219, 59, 187, 123, 251, 
-7, 135, 71, 199, 39, 167, 103, 231, 23, 151, 87, 215, 55, 183, 119, 247, 
-15, 143, 79, 207, 47, 175, 111, 239, 31, 159, 95, 223, 63, 191, 127, 255 }; 
+ * The MV300 mixes the color registers. So we need an array of munged
+ * indices in order to access the correct reg.
+ */
+static int MV300_reg_1bit[2] = {
+	0, 1
+};
+static int MV300_reg_4bit[16] = {
+	0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15
+};
+static int MV300_reg_8bit[256] = {
+	0, 128, 64, 192, 32, 160, 96, 224, 16, 144, 80, 208, 48, 176, 112, 240,
+	8, 136, 72, 200, 40, 168, 104, 232, 24, 152, 88, 216, 56, 184, 120, 248,
+	4, 132, 68, 196, 36, 164, 100, 228, 20, 148, 84, 212, 52, 180, 116, 244,
+	12, 140, 76, 204, 44, 172, 108, 236, 28, 156, 92, 220, 60, 188, 124, 252,
+	2, 130, 66, 194, 34, 162, 98, 226, 18, 146, 82, 210, 50, 178, 114, 242,
+	10, 138, 74, 202, 42, 170, 106, 234, 26, 154, 90, 218, 58, 186, 122, 250,
+	6, 134, 70, 198, 38, 166, 102, 230, 22, 150, 86, 214, 54, 182, 118, 246,
+	14, 142, 78, 206, 46, 174, 110, 238, 30, 158, 94, 222, 62, 190, 126, 254,
+	1, 129, 65, 193, 33, 161, 97, 225, 17, 145, 81, 209, 49, 177, 113, 241,
+	9, 137, 73, 201, 41, 169, 105, 233, 25, 153, 89, 217, 57, 185, 121, 249,
+	5, 133, 69, 197, 37, 165, 101, 229, 21, 149, 85, 213, 53, 181, 117, 245,
+	13, 141, 77, 205, 45, 173, 109, 237, 29, 157, 93, 221, 61, 189, 125, 253,
+	3, 131, 67, 195, 35, 163, 99, 227, 19, 147, 83, 211, 51, 179, 115, 243,
+	11, 139, 75, 203, 43, 171, 107, 235, 27, 155, 91, 219, 59, 187, 123, 251,
+	7, 135, 71, 199, 39, 167, 103, 231, 23, 151, 87, 215, 55, 183, 119, 247,
+	15, 143, 79, 207, 47, 175, 111, 239, 31, 159, 95, 223, 63, 191, 127, 255
+};
 
 static int *MV300_reg = MV300_reg_8bit;
-
-/*
-And on the MV300 it's difficult to read out the hardware palette. So we
-just keep track of the set colors in our own array here, and use that!
-*/
-
-static struct { unsigned char red,green,blue,pad; } ext_color[256];
 #endif /* ATAFB_EXT */
 
 
-static int inverse=0;
+static int inverse;
 
 extern int fontheight_8x8;
 extern int fontwidth_8x8;
@@ -249,96 +270,154 @@
 extern int fontwidth_8x16;
 extern unsigned char fontdata_8x16[];
 
+/*
+ * struct fb_ops {
+ *	* open/release and usage marking
+ *	struct module *owner;
+ *	int (*fb_open)(struct fb_info *info, int user);
+ *	int (*fb_release)(struct fb_info *info, int user);
+ *
+ *	* For framebuffers with strange non linear layouts or that do not
+ *	* work with normal memory mapped access
+ *	ssize_t (*fb_read)(struct file *file, char __user *buf, size_t count, loff_t *ppos);
+ *	ssize_t (*fb_write)(struct file *file, const char __user *buf, size_t count, loff_t *ppos);
+ *
+ *	* checks var and eventually tweaks it to something supported,
+ *	* DOES NOT MODIFY PAR *
+ *	int (*fb_check_var)(struct fb_var_screeninfo *var, struct fb_info *info);
+ *
+ *	* set the video mode according to info->var *
+ *	int (*fb_set_par)(struct fb_info *info);
+ *
+ *	* set color register *
+ *	int (*fb_setcolreg)(unsigned int regno, unsigned int red, unsigned int green,
+ *			    unsigned int blue, unsigned int transp, struct fb_info *info);
+ *
+ *	* set color registers in batch *
+ *	int (*fb_setcmap)(struct fb_cmap *cmap, struct fb_info *info);
+ *
+ *	* blank display *
+ *	int (*fb_blank)(int blank, struct fb_info *info);
+ *
+ *	* pan display *
+ *	int (*fb_pan_display)(struct fb_var_screeninfo *var, struct fb_info *info);
+ *
+ *	*** The meat of the drawing engine ***
+ *	* Draws a rectangle *
+ *	void (*fb_fillrect) (struct fb_info *info, const struct fb_fillrect *rect);
+ *	* Copy data from area to another *
+ *	void (*fb_copyarea) (struct fb_info *info, const struct fb_copyarea *region);
+ *	* Draws a image to the display *
+ *	void (*fb_imageblit) (struct fb_info *info, const struct fb_image *image);
+ *
+ *	* Draws cursor *
+ *	int (*fb_cursor) (struct fb_info *info, struct fb_cursor *cursor);
+ *
+ *	* Rotates the display *
+ *	void (*fb_rotate)(struct fb_info *info, int angle);
+ *
+ *	* wait for blit idle, optional *
+ *	int (*fb_sync)(struct fb_info *info);
+ *
+ *	* perform fb specific ioctl (optional) *
+ *	int (*fb_ioctl)(struct fb_info *info, unsigned int cmd,
+ *			unsigned long arg);
+ *
+ *	* Handle 32bit compat ioctl (optional) *
+ *	int (*fb_compat_ioctl)(struct fb_info *info, unsigned int cmd,
+ *			unsigned long arg);
+ *
+ *	* perform fb specific mmap *
+ *	int (*fb_mmap)(struct fb_info *info, struct vm_area_struct *vma);
+ *
+ *	* save current hardware state *
+ *	void (*fb_save_state)(struct fb_info *info);
+ *
+ *	* restore saved state *
+ *	void (*fb_restore_state)(struct fb_info *info);
+ * } ;
+ */
+
+
 /* ++roman: This structure abstracts from the underlying hardware (ST(e),
  * TT, or Falcon.
  *
- * int (*detect)( void )
+ * int (*detect)(void)
  *   This function should detect the current video mode settings and
  *   store them in atafb_predefined[0] for later reference by the
  *   user. Return the index+1 of an equivalent predefined mode or 0
  *   if there is no such.
- * 
- * int (*encode_fix)( struct fb_fix_screeninfo *fix,
- *                    struct atafb_par *par )
+ *
+ * int (*encode_fix)(struct fb_fix_screeninfo *fix,
+ *                   struct atafb_par *par)
  *   This function should fill in the 'fix' structure based on the
  *   values in the 'par' structure.
- *   
- * int (*decode_var)( struct fb_var_screeninfo *var,
- *                    struct atafb_par *par )
+ * !!! Obsolete, perhaps !!!
+ *
+ * int (*decode_var)(struct fb_var_screeninfo *var,
+ *                   struct atafb_par *par)
  *   Get the video params out of 'var'. If a value doesn't fit, round
  *   it up, if it's too big, return EINVAL.
- *   Round up in the following order: bits_per_pixel, xres, yres, 
- *   xres_virtual, yres_virtual, xoffset, yoffset, grayscale, bitfields, 
+ *   Round up in the following order: bits_per_pixel, xres, yres,
+ *   xres_virtual, yres_virtual, xoffset, yoffset, grayscale, bitfields,
  *   horizontal timing, vertical timing.
  *
- * int (*encode_var)( struct fb_var_screeninfo *var,
- *                    struct atafb_par *par );
+ * int (*encode_var)(struct fb_var_screeninfo *var,
+ *                   struct atafb_par *par);
  *   Fill the 'var' structure based on the values in 'par' and maybe
  *   other values read out of the hardware.
- *   
- * void (*get_par)( struct atafb_par *par )
+ *
+ * void (*get_par)(struct atafb_par *par)
  *   Fill the hardware's 'par' structure.
- *   
- * void (*set_par)( struct atafb_par *par )
+ *   !!! Used only by detect() !!!
+ *
+ * void (*set_par)(struct atafb_par *par)
  *   Set the hardware according to 'par'.
- *   
- * int (*getcolreg)( unsigned regno, unsigned *red,
- *                   unsigned *green, unsigned *blue,
- *                   unsigned *transp, struct fb_info *info )
- *   Read a single color register and split it into
- *   colors/transparent. Return != 0 for invalid regno.
  *
  * void (*set_screen_base)(void *s_base)
  *   Set the base address of the displayed frame buffer. Only called
  *   if yres_virtual > yres or xres_virtual > xres.
  *
- * int (*blank)( int blank_mode )
- *   Blank the screen if blank_mode!=0, else unblank. If blank==NULL then
+ * int (*blank)(int blank_mode)
+ *   Blank the screen if blank_mode != 0, else unblank. If blank == NULL then
  *   the caller blanks by setting the CLUT to all black. Return 0 if blanking
  *   succeeded, !=0 if un-/blanking failed due to e.g. a video mode which
  *   doesn't support it. Implements VESA suspend and powerdown modes on
  *   hardware that supports disabling hsync/vsync:
- *       blank_mode==2: suspend vsync, 3:suspend hsync, 4: powerdown.
+ *       blank_mode == 2: suspend vsync, 3:suspend hsync, 4: powerdown.
  */
 
 static struct fb_hwswitch {
-	int  (*detect)( void );
-	int  (*encode_fix)( struct fb_fix_screeninfo *fix,
-						struct atafb_par *par );
-	int  (*decode_var)( struct fb_var_screeninfo *var,
-						struct atafb_par *par );
-	int  (*encode_var)( struct fb_var_screeninfo *var,
-						struct atafb_par *par );
-	void (*get_par)( struct atafb_par *par );
-	void (*set_par)( struct atafb_par *par );
-	int  (*getcolreg)( unsigned regno, unsigned *red,
-					   unsigned *green, unsigned *blue,
-					   unsigned *transp, struct fb_info *info );
+	int (*detect)(void);
+	int (*encode_fix)(struct fb_fix_screeninfo *fix,
+			  struct atafb_par *par);
+	int (*decode_var)(struct fb_var_screeninfo *var,
+			  struct atafb_par *par);
+	int (*encode_var)(struct fb_var_screeninfo *var,
+			  struct atafb_par *par);
+	void (*get_par)(struct atafb_par *par);
+	void (*set_par)(struct atafb_par *par);
 	void (*set_screen_base)(void *s_base);
-	int  (*blank)( int blank_mode );
-	int  (*pan_display)( struct fb_var_screeninfo *var,
-						 struct atafb_par *par);
+	int (*blank)(int blank_mode);
+	int (*pan_display)(struct fb_var_screeninfo *var,
+			   struct fb_info *info);
 } *fbhw;
 
-static char *autodetect_names[] = {"autodetect", NULL};
-static char *stlow_names[] = {"stlow", NULL};
-static char *stmid_names[] = {"stmid", "default5", NULL};
-static char *sthigh_names[] = {"sthigh", "default4", NULL};
-static char *ttlow_names[] = {"ttlow", NULL};
-static char *ttmid_names[]= {"ttmid", "default1", NULL};
-static char *tthigh_names[]= {"tthigh", "default2", NULL};
-static char *vga2_names[] = {"vga2", NULL};
-static char *vga4_names[] = {"vga4", NULL};
-static char *vga16_names[] = {"vga16", "default3", NULL};
-static char *vga256_names[] = {"vga256", NULL};
-static char *falh2_names[] = {"falh2", NULL};
-static char *falh16_names[] = {"falh16", NULL};
+static char *autodetect_names[] = { "autodetect", NULL };
+static char *stlow_names[] = { "stlow", NULL };
+static char *stmid_names[] = { "stmid", "default5", NULL };
+static char *sthigh_names[] = { "sthigh", "default4", NULL };
+static char *ttlow_names[] = { "ttlow", NULL };
+static char *ttmid_names[] = { "ttmid", "default1", NULL };
+static char *tthigh_names[] = { "tthigh", "default2", NULL };
+static char *vga2_names[] = { "vga2", NULL };
+static char *vga4_names[] = { "vga4", NULL };
+static char *vga16_names[] = { "vga16", "default3", NULL };
+static char *vga256_names[] = { "vga256", NULL };
+static char *falh2_names[] = { "falh2", NULL };
+static char *falh16_names[] = { "falh16", NULL };
 
 static char **fb_var_names[] = {
-	/* Writing the name arrays directly in this array (via "(char *[]){...}")
-	 * crashes gcc 2.5.8 (sigsegv) if the inner array
-	 * contains more than two items. I've also seen that all elements
-	 * were identical to the last (my cross-gcc) :-(*/
 	autodetect_names,
 	stlow_names,
 	stmid_names,
@@ -353,18 +432,17 @@
 	falh2_names,
 	falh16_names,
 	NULL
-	/* ,NULL */ /* this causes a sigsegv on my gcc-2.5.8 */
 };
 
 static struct fb_var_screeninfo atafb_predefined[] = {
- 	/*
- 	 * yres_virtual==0 means use hw-scrolling if possible, else yres
- 	 */
- 	{ /* autodetect */
-	  0, 0, 0, 0, 0, 0, 0, 0,   		/* xres-grayscale */
-	  {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, 	/* red green blue tran*/
+	/*
+	 * yres_virtual == 0 means use hw-scrolling if possible, else yres
+	 */
+	{ /* autodetect */
+	  0, 0, 0, 0, 0, 0, 0, 0,		/* xres-grayscale */
+	  {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},	/* red green blue tran*/
 	  0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
- 	{ /* st low */
+	{ /* st low */
 	  320, 200, 320, 0, 0, 0, 4, 0,
 	  {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
 	  0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
@@ -414,27 +492,100 @@
 	  0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
 };
 
-static int num_atafb_predefined=ARRAY_SIZE(atafb_predefined);
+static int num_atafb_predefined = ARRAY_SIZE(atafb_predefined);
+
+static struct fb_videomode atafb_modedb[] __initdata = {
+	/*
+	 *  Atari Video Modes
+	 *
+	 *  If you change these, make sure to update DEFMODE_* as well!
+	 */
+
+	/*
+	 *  ST/TT Video Modes
+	 */
+
+	{
+		/* 320x200, 15 kHz, 60 Hz (ST low) */
+		"st-low", 60, 320, 200, 32000, 32, 16, 31, 14, 96, 4,
+		0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
+	}, {
+		/* 640x200, 15 kHz, 60 Hz (ST medium) */
+		"st-mid", 60, 640, 200, 32000, 32, 16, 31, 14, 96, 4,
+		0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
+	}, {
+		/* 640x400, 30.25 kHz, 63.5 Hz (ST high) */
+		"st-high", 63, 640, 400, 32000, 128, 0, 40, 14, 128, 4,
+		0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
+	}, {
+		/* 320x480, 15 kHz, 60 Hz (TT low) */
+		"tt-low", 60, 320, 480, 31041, 120, 100, 8, 16, 140, 30,
+		0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
+	}, {
+		/* 640x480, 29 kHz, 57 Hz (TT medium) */
+		"tt-mid", 60, 640, 480, 31041, 120, 100, 8, 16, 140, 30,
+		0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
+	}, {
+		/* 1280x960, 29 kHz, 60 Hz (TT high) */
+		"tt-high", 57, 640, 960, 31041, 120, 100, 8, 16, 140, 30,
+		0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
+	},
+
+	/*
+	 *  VGA Video Modes
+	 */
+
+	{
+		/* 640x480, 31 kHz, 60 Hz (VGA) */
+		"vga", 63.5, 640, 480, 32000, 18, 42, 31, 11, 96, 3,
+		0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
+	}, {
+		/* 640x400, 31 kHz, 70 Hz (VGA) */
+		"vga70", 70, 640, 400, 32000, 18, 42, 31, 11, 96, 3,
+		FB_SYNC_VERT_HIGH_ACT | FB_SYNC_COMP_HIGH_ACT, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
+	},
+
+	/*
+	 *  Falcon HiRes Video Modes
+	 */
+
+	{
+		/* 896x608, 31 kHz, 60 Hz (Falcon High) */
+		"falh", 60, 896, 608, 32000, 18, 42, 31, 1, 96,3,
+		0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
+	},
+};
+
+#define NUM_TOTAL_MODES  ARRAY_SIZE(atafb_modedb)
+
+static char *mode_option __initdata = NULL;
+
+ /* default modes */
+
+#define DEFMODE_TT	5		/* "tt-high" for TT */
+#define DEFMODE_F30	7		/* "vga70" for Falcon */
+#define DEFMODE_STE	2		/* "st-high" for ST/E */
+#define DEFMODE_EXT	6		/* "vga" for external */
 
 
-static int
-get_video_mode(char *vname)
+static int get_video_mode(char *vname)
 {
-    char ***name_list;
-    char **name;
-    int i;
-    name_list=fb_var_names;
-    for (i = 0 ; i < num_atafb_predefined ; i++) {
-	name=*(name_list++);
-	if (! name || ! *name)
-	    break;
-	while (*name) {
-	    if (! strcmp(vname, *name))
-		return i+1;
-	    name++;
+	char ***name_list;
+	char **name;
+	int i;
+
+	name_list = fb_var_names;
+	for (i = 0; i < num_atafb_predefined; i++) {
+		name = *name_list++;
+		if (!name || !*name)
+			break;
+		while (*name) {
+			if (!strcmp(vname, *name))
+				return i + 1;
+			name++;
+		}
 	}
-    }
-    return 0;
+	return 0;
 }
 
 
@@ -443,93 +594,84 @@
 
 #ifdef ATAFB_TT
 
-static int tt_encode_fix( struct fb_fix_screeninfo *fix,
-						  struct atafb_par *par )
-
+static int tt_encode_fix(struct fb_fix_screeninfo *fix, struct atafb_par *par)
 {
 	int mode;
 
-	strcpy(fix->id,"Atari Builtin");
+	strcpy(fix->id, "Atari Builtin");
 	fix->smem_start = (unsigned long)real_screen_base;
 	fix->smem_len = screen_len;
-	fix->type=FB_TYPE_INTERLEAVED_PLANES;
-	fix->type_aux=2;
-	fix->visual=FB_VISUAL_PSEUDOCOLOR;
+	fix->type = FB_TYPE_INTERLEAVED_PLANES;
+	fix->type_aux = 2;
+	fix->visual = FB_VISUAL_PSEUDOCOLOR;
 	mode = par->hw.tt.mode & TT_SHIFTER_MODEMASK;
 	if (mode == TT_SHIFTER_TTHIGH || mode == TT_SHIFTER_STHIGH) {
-		fix->type=FB_TYPE_PACKED_PIXELS;
-		fix->type_aux=0;
+		fix->type = FB_TYPE_PACKED_PIXELS;
+		fix->type_aux = 0;
 		if (mode == TT_SHIFTER_TTHIGH)
-			fix->visual=FB_VISUAL_MONO01;
+			fix->visual = FB_VISUAL_MONO01;
 	}
-	fix->xpanstep=0;
-	fix->ypanstep=1;
-	fix->ywrapstep=0;
+	fix->xpanstep = 0;
+	fix->ypanstep = 1;
+	fix->ywrapstep = 0;
 	fix->line_length = 0;
 	fix->accel = FB_ACCEL_ATARIBLITT;
 	return 0;
 }
 
-
-static int tt_decode_var( struct fb_var_screeninfo *var,
-						  struct atafb_par *par )
+static int tt_decode_var(struct fb_var_screeninfo *var, struct atafb_par *par)
 {
-	int xres=var->xres;
-	int yres=var->yres;
-	int bpp=var->bits_per_pixel;
+	int xres = var->xres;
+	int yres = var->yres;
+	int bpp = var->bits_per_pixel;
 	int linelen;
 	int yres_virtual = var->yres_virtual;
 
 	if (mono_moni) {
-		if (bpp > 1 || xres > sttt_xres*2 || yres >tt_yres*2)
+		if (bpp > 1 || xres > sttt_xres * 2 || yres > tt_yres * 2)
 			return -EINVAL;
-		par->hw.tt.mode=TT_SHIFTER_TTHIGH;
-		xres=sttt_xres*2;
-		yres=tt_yres*2;
-		bpp=1;
+		par->hw.tt.mode = TT_SHIFTER_TTHIGH;
+		xres = sttt_xres * 2;
+		yres = tt_yres * 2;
+		bpp = 1;
 	} else {
 		if (bpp > 8 || xres > sttt_xres || yres > tt_yres)
 			return -EINVAL;
 		if (bpp > 4) {
-			if (xres > sttt_xres/2 || yres > tt_yres)
+			if (xres > sttt_xres / 2 || yres > tt_yres)
 				return -EINVAL;
-			par->hw.tt.mode=TT_SHIFTER_TTLOW;
-			xres=sttt_xres/2;
-			yres=tt_yres;
-			bpp=8;
-		}
-		else if (bpp > 2) {
+			par->hw.tt.mode = TT_SHIFTER_TTLOW;
+			xres = sttt_xres / 2;
+			yres = tt_yres;
+			bpp = 8;
+		} else if (bpp > 2) {
 			if (xres > sttt_xres || yres > tt_yres)
 				return -EINVAL;
-			if (xres > sttt_xres/2 || yres > st_yres/2) {
-				par->hw.tt.mode=TT_SHIFTER_TTMID;
-				xres=sttt_xres;
-				yres=tt_yres;
-				bpp=4;
+			if (xres > sttt_xres / 2 || yres > st_yres / 2) {
+				par->hw.tt.mode = TT_SHIFTER_TTMID;
+				xres = sttt_xres;
+				yres = tt_yres;
+				bpp = 4;
+			} else {
+				par->hw.tt.mode = TT_SHIFTER_STLOW;
+				xres = sttt_xres / 2;
+				yres = st_yres / 2;
+				bpp = 4;
 			}
-			else {
-				par->hw.tt.mode=TT_SHIFTER_STLOW;
-				xres=sttt_xres/2;
-				yres=st_yres/2;
-				bpp=4;
-			}
-		}
-		else if (bpp > 1) {
-			if (xres > sttt_xres || yres > st_yres/2)
+		} else if (bpp > 1) {
+			if (xres > sttt_xres || yres > st_yres / 2)
 				return -EINVAL;
-			par->hw.tt.mode=TT_SHIFTER_STMID;
-			xres=sttt_xres;
-			yres=st_yres/2;
-			bpp=2;
-		}
-		else if (var->xres > sttt_xres || var->yres > st_yres) {
+			par->hw.tt.mode = TT_SHIFTER_STMID;
+			xres = sttt_xres;
+			yres = st_yres / 2;
+			bpp = 2;
+		} else if (var->xres > sttt_xres || var->yres > st_yres) {
 			return -EINVAL;
-		}
-		else {
-			par->hw.tt.mode=TT_SHIFTER_STHIGH;
-			xres=sttt_xres;
-			yres=st_yres;
-			bpp=1;
+		} else {
+			par->hw.tt.mode = TT_SHIFTER_STHIGH;
+			xres = sttt_xres;
+			yres = st_yres;
+			bpp = 1;
 		}
 	}
 	if (yres_virtual <= 0)
@@ -537,10 +679,10 @@
 	else if (yres_virtual < yres)
 		yres_virtual = yres;
 	if (var->sync & FB_SYNC_EXT)
-		par->hw.tt.sync=0;
+		par->hw.tt.sync = 0;
 	else
-		par->hw.tt.sync=1;
-	linelen=xres*bpp/8;
+		par->hw.tt.sync = 1;
+	linelen = xres * bpp / 8;
 	if (yres_virtual * linelen > screen_len && screen_len)
 		return -EINVAL;
 	if (yres * linelen > screen_len && screen_len)
@@ -552,154 +694,123 @@
 	return 0;
 }
 
-static int tt_encode_var( struct fb_var_screeninfo *var,
-						  struct atafb_par *par )
+static int tt_encode_var(struct fb_var_screeninfo *var, struct atafb_par *par)
 {
 	int linelen;
 	memset(var, 0, sizeof(struct fb_var_screeninfo));
-	var->red.offset=0;
-	var->red.length=4;
-	var->red.msb_right=0;
-	var->grayscale=0;
+	var->red.offset = 0;
+	var->red.length = 4;
+	var->red.msb_right = 0;
+	var->grayscale = 0;
 
-	var->pixclock=31041;
-	var->left_margin=120;		/* these may be incorrect 	*/
-	var->right_margin=100;
-	var->upper_margin=8;
-	var->lower_margin=16;
-	var->hsync_len=140;
-	var->vsync_len=30;
+	var->pixclock = 31041;
+	var->left_margin = 120;		/* these may be incorrect */
+	var->right_margin = 100;
+	var->upper_margin = 8;
+	var->lower_margin = 16;
+	var->hsync_len = 140;
+	var->vsync_len = 30;
 
-	var->height=-1;
-	var->width=-1;
+	var->height = -1;
+	var->width = -1;
 
 	if (par->hw.tt.sync & 1)
-		var->sync=0;
+		var->sync = 0;
 	else
-		var->sync=FB_SYNC_EXT;
+		var->sync = FB_SYNC_EXT;
 
 	switch (par->hw.tt.mode & TT_SHIFTER_MODEMASK) {
 	case TT_SHIFTER_STLOW:
-		var->xres=sttt_xres/2;
-		var->xres_virtual=sttt_xres_virtual/2;
-		var->yres=st_yres/2;
-		var->bits_per_pixel=4;
+		var->xres = sttt_xres / 2;
+		var->xres_virtual = sttt_xres_virtual / 2;
+		var->yres = st_yres / 2;
+		var->bits_per_pixel = 4;
 		break;
 	case TT_SHIFTER_STMID:
-		var->xres=sttt_xres;
-		var->xres_virtual=sttt_xres_virtual;
-		var->yres=st_yres/2;
-		var->bits_per_pixel=2;
+		var->xres = sttt_xres;
+		var->xres_virtual = sttt_xres_virtual;
+		var->yres = st_yres / 2;
+		var->bits_per_pixel = 2;
 		break;
 	case TT_SHIFTER_STHIGH:
-		var->xres=sttt_xres;
-		var->xres_virtual=sttt_xres_virtual;
-		var->yres=st_yres;
-		var->bits_per_pixel=1;
+		var->xres = sttt_xres;
+		var->xres_virtual = sttt_xres_virtual;
+		var->yres = st_yres;
+		var->bits_per_pixel = 1;
 		break;
 	case TT_SHIFTER_TTLOW:
-		var->xres=sttt_xres/2;
-		var->xres_virtual=sttt_xres_virtual/2;
-		var->yres=tt_yres;
-		var->bits_per_pixel=8;
+		var->xres = sttt_xres / 2;
+		var->xres_virtual = sttt_xres_virtual / 2;
+		var->yres = tt_yres;
+		var->bits_per_pixel = 8;
 		break;
 	case TT_SHIFTER_TTMID:
-		var->xres=sttt_xres;
-		var->xres_virtual=sttt_xres_virtual;
-		var->yres=tt_yres;
-		var->bits_per_pixel=4;
+		var->xres = sttt_xres;
+		var->xres_virtual = sttt_xres_virtual;
+		var->yres = tt_yres;
+		var->bits_per_pixel = 4;
 		break;
 	case TT_SHIFTER_TTHIGH:
-		var->red.length=0;
-		var->xres=sttt_xres*2;
-		var->xres_virtual=sttt_xres_virtual*2;
-		var->yres=tt_yres*2;
-		var->bits_per_pixel=1;
+		var->red.length = 0;
+		var->xres = sttt_xres * 2;
+		var->xres_virtual = sttt_xres_virtual * 2;
+		var->yres = tt_yres * 2;
+		var->bits_per_pixel = 1;
 		break;
-	}		
-	var->blue=var->green=var->red;
-	var->transp.offset=0;
-	var->transp.length=0;
-	var->transp.msb_right=0;
-	linelen=var->xres_virtual * var->bits_per_pixel / 8;
-	if (! use_hwscroll)
-		var->yres_virtual=var->yres;
+	}
+	var->blue = var->green = var->red;
+	var->transp.offset = 0;
+	var->transp.length = 0;
+	var->transp.msb_right = 0;
+	linelen = var->xres_virtual * var->bits_per_pixel / 8;
+	if (!use_hwscroll)
+		var->yres_virtual = var->yres;
 	else if (screen_len) {
 		if (par->yres_virtual)
 			var->yres_virtual = par->yres_virtual;
 		else
-			/* yres_virtual==0 means use maximum */
+			/* yres_virtual == 0 means use maximum */
 			var->yres_virtual = screen_len / linelen;
 	} else {
 		if (hwscroll < 0)
 			var->yres_virtual = 2 * var->yres;
 		else
-			var->yres_virtual=var->yres+hwscroll * 16;
+			var->yres_virtual = var->yres + hwscroll * 16;
 	}
-	var->xoffset=0;
+	var->xoffset = 0;
 	if (screen_base)
-		var->yoffset=(par->screen_base - screen_base)/linelen;
+		var->yoffset = (par->screen_base - screen_base) / linelen;
 	else
-		var->yoffset=0;
-	var->nonstd=0;
-	var->activate=0;
-	var->vmode=FB_VMODE_NONINTERLACED;
+		var->yoffset = 0;
+	var->nonstd = 0;
+	var->activate = 0;
+	var->vmode = FB_VMODE_NONINTERLACED;
 	return 0;
 }
 
-
-static void tt_get_par( struct atafb_par *par )
+static void tt_get_par(struct atafb_par *par)
 {
 	unsigned long addr;
-	par->hw.tt.mode=shifter_tt.tt_shiftmode;
-	par->hw.tt.sync=shifter.syncmode;
+	par->hw.tt.mode = shifter_tt.tt_shiftmode;
+	par->hw.tt.sync = shifter.syncmode;
 	addr = ((shifter.bas_hi & 0xff) << 16) |
 	       ((shifter.bas_md & 0xff) << 8)  |
 	       ((shifter.bas_lo & 0xff));
 	par->screen_base = phys_to_virt(addr);
 }
 
-static void tt_set_par( struct atafb_par *par )
+static void tt_set_par(struct atafb_par *par)
 {
-	shifter_tt.tt_shiftmode=par->hw.tt.mode;
-	shifter.syncmode=par->hw.tt.sync;
+	shifter_tt.tt_shiftmode = par->hw.tt.mode;
+	shifter.syncmode = par->hw.tt.sync;
 	/* only set screen_base if really necessary */
 	if (current_par.screen_base != par->screen_base)
 		fbhw->set_screen_base(par->screen_base);
 }
 
-
-static int tt_getcolreg(unsigned regno, unsigned *red,
-			unsigned *green, unsigned *blue,
-			unsigned *transp, struct fb_info *info)
-{
-	int t, col;
-
-	if ((shifter_tt.tt_shiftmode & TT_SHIFTER_MODEMASK) == TT_SHIFTER_STHIGH)
-		regno += 254;
-	if (regno > 255)
-		return 1;
-	t = tt_palette[regno];
-	col = t & 15;
-	col |= col << 4;
-	col |= col << 8;
-	*blue = col;
-	col = (t >> 4) & 15;
-	col |= col << 4;
-	col |= col << 8;
-	*green = col;
-	col = (t >> 8) & 15;
-	col |= col << 4;
-	col |= col << 8;
-	*red = col;
-	*transp = 0;
-	return 0;
-}
-
-
-static int tt_setcolreg(unsigned regno, unsigned red,
-			unsigned green, unsigned blue,
-			unsigned transp, struct fb_info *info)
+static int tt_setcolreg(unsigned int regno, unsigned int red,
+			unsigned int green, unsigned int blue,
+			unsigned int transp, struct fb_info *info)
 {
 	if ((shifter_tt.tt_shiftmode & TT_SHIFTER_MODEMASK) == TT_SHIFTER_STHIGH)
 		regno += 254;
@@ -708,15 +819,14 @@
 	tt_palette[regno] = (((red >> 12) << 8) | ((green >> 12) << 4) |
 			     (blue >> 12));
 	if ((shifter_tt.tt_shiftmode & TT_SHIFTER_MODEMASK) ==
-		TT_SHIFTER_STHIGH && regno == 254)
+	    TT_SHIFTER_STHIGH && regno == 254)
 		tt_palette[0] = 0;
 	return 0;
 }
 
-						  
-static int tt_detect( void )
-
-{	struct atafb_par par;
+static int tt_detect(void)
+{
+	struct atafb_par par;
 
 	/* Determine the connected monitor: The DMA sound must be
 	 * disabled before reading the MFP GPIP, because the Sound
@@ -726,9 +836,9 @@
 	 * announced that the Eagle is TT compatible, but only the PCM is
 	 * missing...
 	 */
-	if (ATARIHW_PRESENT(PCM_8BIT)) { 
+	if (ATARIHW_PRESENT(PCM_8BIT)) {
 		tt_dmasnd.ctrl = DMASND_CTRL_OFF;
-		udelay(20);	/* wait a while for things to settle down */
+		udelay(20);		/* wait a while for things to settle down */
 	}
 	mono_moni = (mfp.par_dt_reg & 0x80) == 0;
 
@@ -755,19 +865,24 @@
 	unsigned long f;	/* f/[Hz] */
 	unsigned long t;	/* t/[ps] (=1/f) */
 	int right, hsync, left;	/* standard timing in clock cycles, not pixel */
-		/* hsync initialized in falcon_detect() */
+	/* hsync initialized in falcon_detect() */
 	int sync_mask;		/* or-mask for hw.falcon.sync to set this clock */
 	int control_mask;	/* ditto, for hw.falcon.vid_control */
-}
-f25  = {25175000, 39721, 18, 0, 42, 0x0, VCO_CLOCK25},
-f32  = {32000000, 31250, 18, 0, 42, 0x0, 0},
-fext = {       0,     0, 18, 0, 42, 0x1, 0};
+} f25 = {
+	25175000, 39721, 18, 0, 42, 0x0, VCO_CLOCK25
+}, f32 = {
+	32000000, 31250, 18, 0, 42, 0x0, 0
+}, fext = {
+	0, 0, 18, 0, 42, 0x1, 0
+};
 
 /* VIDEL-prescale values [mon_type][pixel_length from VCO] */
-static int vdl_prescale[4][3] = {{4,2,1}, {4,2,1}, {4,2,2}, {4,2,1}};
+static int vdl_prescale[4][3] = {
+	{ 4,2,1 }, { 4,2,1 }, { 4,2,2 }, { 4,2,1 }
+};
 
 /* Default hsync timing [mon_type] in picoseconds */
-static long h_syncs[4] = {3000000, 4875000, 4000000, 4875000};
+static long h_syncs[4] = { 3000000, 4875000, 4000000, 4875000 };
 
 #ifdef FBCON_HAS_CFB16
 static u16 fbcon_cfb16_cmap[16];
@@ -775,12 +890,12 @@
 
 static inline int hxx_prescale(struct falcon_hw *hw)
 {
-	return hw->ste_mode ? 16 :
-		   vdl_prescale[mon_type][hw->vid_mode >> 2 & 0x3];
+	return hw->ste_mode ? 16
+			    : vdl_prescale[mon_type][hw->vid_mode >> 2 & 0x3];
 }
 
-static int falcon_encode_fix( struct fb_fix_screeninfo *fix,
-							  struct atafb_par *par )
+static int falcon_encode_fix(struct fb_fix_screeninfo *fix,
+			     struct atafb_par *par)
 {
 	strcpy(fix->id, "Atari Builtin");
 	fix->smem_start = (unsigned long)real_screen_base;
@@ -796,8 +911,7 @@
 		fix->type_aux = 0;
 		/* no smooth scrolling with longword aligned video mem */
 		fix->xpanstep = 32;
-	}
-	else if (par->hw.falcon.f_shift & 0x100) {
+	} else if (par->hw.falcon.f_shift & 0x100) {
 		fix->type = FB_TYPE_PACKED_PIXELS;
 		fix->type_aux = 0;
 		/* Is this ok or should it be DIRECTCOLOR? */
@@ -809,9 +923,8 @@
 	return 0;
 }
 
-
-static int falcon_decode_var( struct fb_var_screeninfo *var,
-							  struct atafb_par *par )
+static int falcon_decode_var(struct fb_var_screeninfo *var,
+			     struct atafb_par *par)
 {
 	int bpp = var->bits_per_pixel;
 	int xres = var->xres;
@@ -823,17 +936,19 @@
 	int linelen;
 	int interlace = 0, doubleline = 0;
 	struct pixel_clock *pclock;
-	int plen; /* width of pixel in clock cycles */
+	int plen;			/* width of pixel in clock cycles */
 	int xstretch;
 	int prescale;
 	int longoffset = 0;
 	int hfreq, vfreq;
+	int hdb_off, hde_off, base_off;
+	int gstart, gend1, gend2, align;
 
 /*
 	Get the video params out of 'var'. If a value doesn't fit, round
 	it up, if it's too big, return EINVAL.
-	Round up in the following order: bits_per_pixel, xres, yres, 
-	xres_virtual, yres_virtual, xoffset, yoffset, grayscale, bitfields, 
+	Round up in the following order: bits_per_pixel, xres, yres,
+	xres_virtual, yres_virtual, xoffset, yoffset, grayscale, bitfields,
 	horizontal timing, vertical timing.
 
 	There is a maximum of screen resolution determined by pixelclock
@@ -843,11 +958,11 @@
 	Frequency range for multisync monitors is given via command line.
 	For TV and SM124 both frequencies are fixed.
 
-	X % 16 == 0 to fit 8x?? font (except 1 bitplane modes must use X%32==0)
+	X % 16 == 0 to fit 8x?? font (except 1 bitplane modes must use X%32 == 0)
 	Y % 16 == 0 to fit 8x16 font
 	Y % 8 == 0 if Y<400
 
-	Currently interlace and doubleline mode in var are ignored. 
+	Currently interlace and doubleline mode in var are ignored.
 	On SM124 and TV only the standard resolutions can be used.
 */
 
@@ -855,43 +970,38 @@
 	if (!xres || !yres || !bpp)
 		return -EINVAL;
 
-	if (mon_type == F_MON_SM && bpp != 1) {
+	if (mon_type == F_MON_SM && bpp != 1)
 		return -EINVAL;
-	}
-	else if (bpp <= 1) {
+
+	if (bpp <= 1) {
 		bpp = 1;
 		par->hw.falcon.f_shift = 0x400;
 		par->hw.falcon.st_shift = 0x200;
-	}
-	else if (bpp <= 2) {
+	} else if (bpp <= 2) {
 		bpp = 2;
 		par->hw.falcon.f_shift = 0x000;
 		par->hw.falcon.st_shift = 0x100;
-	}
-	else if (bpp <= 4) {
+	} else if (bpp <= 4) {
 		bpp = 4;
 		par->hw.falcon.f_shift = 0x000;
 		par->hw.falcon.st_shift = 0x000;
-	}
-	else if (bpp <= 8) {
+	} else if (bpp <= 8) {
 		bpp = 8;
 		par->hw.falcon.f_shift = 0x010;
-	}
-	else if (bpp <= 16) {
-		bpp = 16; /* packed pixel mode */
-		par->hw.falcon.f_shift = 0x100; /* hicolor, no overlay */
-	}
-	else
+	} else if (bpp <= 16) {
+		bpp = 16;		/* packed pixel mode */
+		par->hw.falcon.f_shift = 0x100;	/* hicolor, no overlay */
+	} else
 		return -EINVAL;
 	par->hw.falcon.bpp = bpp;
 
 	if (mon_type == F_MON_SM || DontCalcRes) {
 		/* Skip all calculations. VGA/TV/SC1224 only supported. */
 		struct fb_var_screeninfo *myvar = &atafb_predefined[0];
-		
+
 		if (bpp > myvar->bits_per_pixel ||
-			var->xres > myvar->xres ||
-			var->yres > myvar->yres)
+		    var->xres > myvar->xres ||
+		    var->yres > myvar->yres)
 			return -EINVAL;
 		fbhw->get_par(par);	/* Current par will be new par */
 		goto set_screen_base;	/* Don't forget this */
@@ -910,8 +1020,8 @@
 		yres = 400;
 
 	/* 2 planes must use STE compatibility mode */
-	par->hw.falcon.ste_mode = bpp==2;
-	par->hw.falcon.mono = bpp==1;
+	par->hw.falcon.ste_mode = bpp == 2;
+	par->hw.falcon.mono = bpp == 1;
 
 	/* Total and visible scanline length must be a multiple of one longword,
 	 * this and the console fontwidth yields the alignment for xres and
@@ -967,8 +1077,7 @@
 		left_margin = hsync_len = 128 / plen;
 		right_margin = 0;
 		/* TODO set all margins */
-	}
-	else
+	} else
 #endif
 	if (mon_type == F_MON_SC || mon_type == F_MON_TV) {
 		plen = 2 * xstretch;
@@ -1002,26 +1111,24 @@
 				vsync_len *= 2;
 			}
 		}
-	}
-	else
-	{	/* F_MON_VGA */
+	} else {			/* F_MON_VGA */
 		if (bpp == 16)
-			xstretch = 2; /* Double pixel width only for hicolor */
+			xstretch = 2;	/* Double pixel width only for hicolor */
 		/* Default values are used for vert./hor. timing if no pixelclock given. */
 		if (var->pixclock == 0) {
 			int linesize;
 
 			/* Choose master pixelclock depending on hor. timing */
 			plen = 1 * xstretch;
-			if ((plen * xres + f25.right+f25.hsync+f25.left) *
+			if ((plen * xres + f25.right + f25.hsync + f25.left) *
 			    fb_info.monspecs.hfmin < f25.f)
 				pclock = &f25;
-			else if ((plen * xres + f32.right+f32.hsync+f32.left) * 
-			    fb_info.monspecs.hfmin < f32.f)
+			else if ((plen * xres + f32.right + f32.hsync +
+				  f32.left) * fb_info.monspecs.hfmin < f32.f)
 				pclock = &f32;
-			else if ((plen * xres + fext.right+fext.hsync+fext.left) * 
-			    fb_info.monspecs.hfmin < fext.f
-			         && fext.f)
+			else if ((plen * xres + fext.right + fext.hsync +
+				  fext.left) * fb_info.monspecs.hfmin < fext.f &&
+			         fext.f)
 				pclock = &fext;
 			else
 				return -EINVAL;
@@ -1033,22 +1140,24 @@
 			upper_margin = 31;
 			lower_margin = 11;
 			vsync_len = 3;
-		}
-		else {
+		} else {
 			/* Choose largest pixelclock <= wanted clock */
 			int i;
 			unsigned long pcl = ULONG_MAX;
 			pclock = 0;
-			for (i=1; i <= 4; i *= 2) {
-				if (f25.t*i >= var->pixclock && f25.t*i < pcl) {
+			for (i = 1; i <= 4; i *= 2) {
+				if (f25.t * i >= var->pixclock &&
+				    f25.t * i < pcl) {
 					pcl = f25.t * i;
 					pclock = &f25;
 				}
-				if (f32.t*i >= var->pixclock && f32.t*i < pcl) {
+				if (f32.t * i >= var->pixclock &&
+				    f32.t * i < pcl) {
 					pcl = f32.t * i;
 					pclock = &f32;
 				}
-				if (fext.t && fext.t*i >= var->pixclock && fext.t*i < pcl) {
+				if (fext.t && fext.t * i >= var->pixclock &&
+				    fext.t * i < pcl) {
 					pcl = fext.t * i;
 					pclock = &fext;
 				}
@@ -1070,8 +1179,7 @@
 				upper_margin = (upper_margin + 1) / 2;
 				lower_margin = (lower_margin + 1) / 2;
 				vsync_len = (vsync_len + 1) / 2;
-			}
-			else if (var->vmode & FB_VMODE_DOUBLE) {
+			} else if (var->vmode & FB_VMODE_DOUBLE) {
 				/* External unit is [double lines per frame] */
 				upper_margin *= 2;
 				lower_margin *= 2;
@@ -1079,7 +1187,7 @@
 			}
 		}
 		if (pclock == &fext)
-			longoffset = 1; /* VIDEL doesn't synchronize on short offset */
+			longoffset = 1;	/* VIDEL doesn't synchronize on short offset */
 	}
 	/* Is video bus bandwidth (32MB/s) too low for this resolution? */
 	/* this is definitely wrong if bus clock != 32MHz */
@@ -1098,7 +1206,7 @@
 	 * between interlace and non-interlace without messing around
 	 * with these.
 	 */
-  again:
+again:
 	/* Set base_offset 128 and video bus width */
 	par->hw.falcon.vid_control = mon_type | f030_bus_width;
 	if (!longoffset)
@@ -1112,37 +1220,34 @@
 	/* External or internal clock */
 	par->hw.falcon.sync = pclock->sync_mask | 0x2;
 	/* Pixellength and prescale */
-	par->hw.falcon.vid_mode = (2/plen) << 2;
+	par->hw.falcon.vid_mode = (2 / plen) << 2;
 	if (doubleline)
 		par->hw.falcon.vid_mode |= VMO_DOUBLE;
 	if (interlace)
 		par->hw.falcon.vid_mode |= VMO_INTER;
 
 	/*********************
-	Horizontal timing: unit = [master clock cycles]
-	unit of hxx-registers: [master clock cycles * prescale]
-	Hxx-registers are 9 bit wide
-
-	1 line = ((hht + 2) * 2 * prescale) clock cycles
-
-	graphic output = hdb & 0x200 ?
-	       ((hht+2)*2 - hdb + hde) * prescale - hdboff + hdeoff:
-	       ( hht + 2  - hdb + hde) * prescale - hdboff + hdeoff
-	(this must be a multiple of plen*128/bpp, on VGA pixels
-	 to the right may be cut off with a bigger right margin)
-
-	start of graphics relative to start of 1st halfline = hdb & 0x200 ?
-	       (hdb - hht - 2) * prescale + hdboff :
-	       hdb * prescale + hdboff
-
-	end of graphics relative to start of 1st halfline =
-	       (hde + hht + 2) * prescale + hdeoff
-	*********************/
+	 * Horizontal timing: unit = [master clock cycles]
+	 * unit of hxx-registers: [master clock cycles * prescale]
+	 * Hxx-registers are 9 bit wide
+	 *
+	 * 1 line = ((hht + 2) * 2 * prescale) clock cycles
+	 *
+	 * graphic output = hdb & 0x200 ?
+	 *        ((hht + 2) * 2 - hdb + hde) * prescale - hdboff + hdeoff:
+	 *        (hht + 2  - hdb + hde) * prescale - hdboff + hdeoff
+	 * (this must be a multiple of plen*128/bpp, on VGA pixels
+	 *  to the right may be cut off with a bigger right margin)
+	 *
+	 * start of graphics relative to start of 1st halfline = hdb & 0x200 ?
+	 *        (hdb - hht - 2) * prescale + hdboff :
+	 *        hdb * prescale + hdboff
+	 *
+	 * end of graphics relative to start of 1st halfline =
+	 *        (hde + hht + 2) * prescale + hdeoff
+	 *********************/
 	/* Calculate VIDEL registers */
-	{
-	int hdb_off, hde_off, base_off;
-	int gstart, gend1, gend2, align;
-
+{
 	prescale = hxx_prescale(&par->hw.falcon);
 	base_off = par->hw.falcon.vid_control & VCO_SHORTOFFS ? 64 : 128;
 
@@ -1154,8 +1259,7 @@
 		align = 1;
 		hde_off = 0;
 		hdb_off = (base_off + 16 * plen) + prescale;
-	}
-	else {
+	} else {
 		align = 128 / bpp;
 		hde_off = ((128 / bpp + 2) * plen);
 		if (par->hw.falcon.ste_mode)
@@ -1164,23 +1268,24 @@
 			hdb_off = (base_off + (128 / bpp + 18) * plen) + prescale;
 	}
 
-	gstart = (prescale/2 + plen * left_margin) / prescale;
+	gstart = (prescale / 2 + plen * left_margin) / prescale;
 	/* gend1 is for hde (gend-gstart multiple of align), shifter's xres */
-	gend1 = gstart + ((xres + align-1) / align)*align * plen / prescale;
+	gend1 = gstart + ((xres + align - 1) / align) * align * plen / prescale;
 	/* gend2 is for hbb, visible xres (rest to gend1 is cut off by hblank) */
 	gend2 = gstart + xres * plen / prescale;
 	par->HHT = plen * (left_margin + xres + right_margin) /
 			   (2 * prescale) - 2;
 /*	par->HHT = (gend2 + plen * right_margin / prescale) / 2 - 2;*/
 
-	par->HDB = gstart - hdb_off/prescale;
+	par->HDB = gstart - hdb_off / prescale;
 	par->HBE = gstart;
-	if (par->HDB < 0) par->HDB += par->HHT + 2 + 0x200;
-	par->HDE = gend1 - par->HHT - 2 - hde_off/prescale;
+	if (par->HDB < 0)
+		par->HDB += par->HHT + 2 + 0x200;
+	par->HDE = gend1 - par->HHT - 2 - hde_off / prescale;
 	par->HBB = gend2 - par->HHT - 2;
 #if 0
 	/* One more Videl constraint: data fetch of two lines must not overlap */
-	if ((par->HDB & 0x200)  &&  (par->HDB & ~0x200) - par->HDE <= 5) {
+	if ((par->HDB & 0x200) && (par->HDB & ~0x200) - par->HDE <= 5) {
 		/* if this happens increase margins, decrease hfreq. */
 	}
 #endif
@@ -1189,11 +1294,11 @@
 	par->HSS = par->HHT + 2 - plen * hsync_len / prescale;
 	if (par->HSS < par->HBB)
 		par->HSS = par->HBB;
-	}
+}
 
 	/*  check hor. frequency */
-	hfreq = pclock->f / ((par->HHT+2)*prescale*2);
-	if (hfreq > fb_info.monspecs.hfmax && mon_type!=F_MON_VGA) {
+	hfreq = pclock->f / ((par->HHT + 2) * prescale * 2);
+	if (hfreq > fb_info.monspecs.hfmax && mon_type != F_MON_VGA) {
 		/* ++guenther:   ^^^^^^^^^^^^^^^^^^^ can't remember why I did this */
 		/* Too high -> enlarge margin */
 		left_margin += 1;
@@ -1213,12 +1318,14 @@
 	par->VBE = (upper_margin * 2 + 1); /* must begin on odd halfline */
 	par->VDB = par->VBE;
 	par->VDE = yres;
-	if (!interlace) par->VDE <<= 1;
-	if (doubleline) par->VDE <<= 1;  /* VDE now half lines per (half-)frame */
+	if (!interlace)
+		par->VDE <<= 1;
+	if (doubleline)
+		par->VDE <<= 1;		/* VDE now half lines per (half-)frame */
 	par->VDE += par->VDB;
 	par->VBB = par->VDE;
 	par->VFT = par->VBB + (lower_margin * 2 - 1) - 1;
-	par->VSS = par->VFT+1 - (vsync_len * 2 - 1);
+	par->VSS = par->VFT + 1 - (vsync_len * 2 - 1);
 	/* vbb,vss,vft must be even in interlace mode */
 	if (interlace) {
 		par->VBB++;
@@ -1229,55 +1336,53 @@
 	/* V-frequency check, hope I didn't create any loop here. */
 	/* Interlace and doubleline are mutually exclusive. */
 	vfreq = (hfreq * 2) / (par->VFT + 1);
-	if      (vfreq > fb_info.monspecs.vfmax && !doubleline && !interlace) {
+	if (vfreq > fb_info.monspecs.vfmax && !doubleline && !interlace) {
 		/* Too high -> try again with doubleline */
 		doubleline = 1;
 		goto again;
-	}
-	else if (vfreq < fb_info.monspecs.vfmin && !interlace && !doubleline) {
+	} else if (vfreq < fb_info.monspecs.vfmin && !interlace && !doubleline) {
 		/* Too low -> try again with interlace */
 		interlace = 1;
 		goto again;
-	}
-	else if (vfreq < fb_info.monspecs.vfmin && doubleline) {
+	} else if (vfreq < fb_info.monspecs.vfmin && doubleline) {
 		/* Doubleline too low -> clear doubleline and enlarge margins */
 		int lines;
 		doubleline = 0;
-		for (lines=0;
-		     (hfreq*2)/(par->VFT+1+4*lines-2*yres)>fb_info.monspecs.vfmax;
+		for (lines = 0;
+		     (hfreq * 2) / (par->VFT + 1 + 4 * lines - 2 * yres) >
+		     fb_info.monspecs.vfmax;
 		     lines++)
 			;
 		upper_margin += lines;
 		lower_margin += lines;
 		goto again;
-	}
-	else if (vfreq > fb_info.monspecs.vfmax && doubleline) {
+	} else if (vfreq > fb_info.monspecs.vfmax && doubleline) {
 		/* Doubleline too high -> enlarge margins */
 		int lines;
-		for (lines=0;
-		     (hfreq*2)/(par->VFT+1+4*lines)>fb_info.monspecs.vfmax;
-		     lines+=2)
+		for (lines = 0;
+		     (hfreq * 2) / (par->VFT + 1 + 4 * lines) >
+		     fb_info.monspecs.vfmax;
+		     lines += 2)
 			;
 		upper_margin += lines;
 		lower_margin += lines;
 		goto again;
-	}
-	else if (vfreq > fb_info.monspecs.vfmax && interlace) {
+	} else if (vfreq > fb_info.monspecs.vfmax && interlace) {
 		/* Interlace, too high -> enlarge margins */
 		int lines;
-		for (lines=0;
-		     (hfreq*2)/(par->VFT+1+4*lines)>fb_info.monspecs.vfmax;
+		for (lines = 0;
+		     (hfreq * 2) / (par->VFT + 1 + 4 * lines) >
+		     fb_info.monspecs.vfmax;
 		     lines++)
 			;
 		upper_margin += lines;
 		lower_margin += lines;
 		goto again;
-	}
-	else if (vfreq < fb_info.monspecs.vfmin ||
-		 vfreq > fb_info.monspecs.vfmax)
+	} else if (vfreq < fb_info.monspecs.vfmin ||
+		   vfreq > fb_info.monspecs.vfmax)
 		return -EINVAL;
 
-  set_screen_base:
+set_screen_base:
 	linelen = xres_virtual * bpp / 8;
 	if (yres_virtual * linelen > screen_len && screen_len)
 		return -EINVAL;
@@ -1289,11 +1394,20 @@
 	par->screen_base = screen_base + var->yoffset * linelen;
 	par->hw.falcon.xoffset = 0;
 
+	// FIXME!!! sort of works, no crash
+	//par->next_line = linelen;
+	//par->next_plane = yres_virtual * linelen;
+	par->next_line = linelen;
+	par->next_plane = 2;
+	// crashes
+	//par->next_plane = linelen;
+	//par->next_line  = yres_virtual * linelen;
+
 	return 0;
 }
 
-static int falcon_encode_var( struct fb_var_screeninfo *var,
-							  struct atafb_par *par )
+static int falcon_encode_var(struct fb_var_screeninfo *var,
+			     struct atafb_par *par)
 {
 /* !!! only for VGA !!! */
 	int linelen;
@@ -1306,10 +1420,10 @@
 	var->pixclock = hw->sync & 0x1 ? fext.t :
 	                hw->vid_control & VCO_CLOCK25 ? f25.t : f32.t;
 
-	var->height=-1;
-	var->width=-1;
+	var->height = -1;
+	var->width = -1;
 
-	var->sync=0;
+	var->sync = 0;
 	if (hw->vid_control & VCO_HSYPOS)
 		var->sync |= FB_SYNC_HOR_HIGH_ACT;
 	if (hw->vid_control & VCO_VSYPOS)
@@ -1320,7 +1434,7 @@
 		var->vmode |= FB_VMODE_INTERLACED;
 	if (hw->vid_mode & VMO_DOUBLE)
 		var->vmode |= FB_VMODE_DOUBLE;
-	
+
 	/* visible y resolution:
 	 * Graphics display starts at line VDB and ends at line
 	 * VDE. If interlace mode off unit of VC-registers is
@@ -1332,14 +1446,15 @@
 	if (var->vmode & FB_VMODE_DOUBLE)
 		var->yres >>= 1;
 
-	/* to get bpp, we must examine f_shift and st_shift.
+	/*
+	 * to get bpp, we must examine f_shift and st_shift.
 	 * f_shift is valid if any of bits no. 10, 8 or 4
 	 * is set. Priority in f_shift is: 10 ">" 8 ">" 4, i.e.
 	 * if bit 10 set then bit 8 and bit 4 don't care...
 	 * If all these bits are 0 get display depth from st_shift
 	 * (as for ST and STE)
 	 */
-	if (hw->f_shift & 0x400)		/* 2 colors */
+	if (hw->f_shift & 0x400)	/* 2 colors */
 		var->bits_per_pixel = 1;
 	else if (hw->f_shift & 0x100)	/* hicolor */
 		var->bits_per_pixel = 16;
@@ -1349,7 +1464,7 @@
 		var->bits_per_pixel = 4;
 	else if (hw->st_shift == 0x100)
 		var->bits_per_pixel = 2;
-	else /* if (hw->st_shift == 0x200) */
+	else				/* if (hw->st_shift == 0x200) */
 		var->bits_per_pixel = 1;
 
 	var->xres = hw->line_width * 16 / var->bits_per_pixel;
@@ -1358,42 +1473,42 @@
 		var->xres_virtual += 16;
 
 	if (var->bits_per_pixel == 16) {
-		var->red.offset=11;
-		var->red.length=5;
-		var->red.msb_right=0;
-		var->green.offset=5;
-		var->green.length=6;
-		var->green.msb_right=0;
-		var->blue.offset=0;
-		var->blue.length=5;
-		var->blue.msb_right=0;
-	}
-	else {
-		var->red.offset=0;
+		var->red.offset = 11;
+		var->red.length = 5;
+		var->red.msb_right = 0;
+		var->green.offset = 5;
+		var->green.length = 6;
+		var->green.msb_right = 0;
+		var->blue.offset = 0;
+		var->blue.length = 5;
+		var->blue.msb_right = 0;
+	} else {
+		var->red.offset = 0;
 		var->red.length = hw->ste_mode ? 4 : 6;
-		var->red.msb_right=0;
-		var->grayscale=0;
-		var->blue=var->green=var->red;
+		if (var->red.length > var->bits_per_pixel)
+			var->red.length = var->bits_per_pixel;
+		var->red.msb_right = 0;
+		var->grayscale = 0;
+		var->blue = var->green = var->red;
 	}
-	var->transp.offset=0;
-	var->transp.length=0;
-	var->transp.msb_right=0;
+	var->transp.offset = 0;
+	var->transp.length = 0;
+	var->transp.msb_right = 0;
 
 	linelen = var->xres_virtual * var->bits_per_pixel / 8;
 	if (screen_len) {
 		if (par->yres_virtual)
 			var->yres_virtual = par->yres_virtual;
 		else
-			/* yres_virtual==0 means use maximum */
+			/* yres_virtual == 0 means use maximum */
 			var->yres_virtual = screen_len / linelen;
-	}
-	else {
+	} else {
 		if (hwscroll < 0)
 			var->yres_virtual = 2 * var->yres;
 		else
-			var->yres_virtual=var->yres+hwscroll * 16;
+			var->yres_virtual = var->yres + hwscroll * 16;
 	}
-	var->xoffset=0; /* TODO change this */
+	var->xoffset = 0;		/* TODO change this */
 
 	/* hdX-offsets */
 	prescale = hxx_prescale(hw);
@@ -1402,8 +1517,7 @@
 	if (hw->f_shift & 0x100) {
 		hde_off = 0;
 		hdb_off = (base_off + 16 * plen) + prescale;
-	}
-	else {
+	} else {
 		hde_off = ((128 / var->bits_per_pixel + 2) * plen);
 		if (hw->ste_mode)
 			hdb_off = (64 + base_off + (128 / var->bits_per_pixel + 2) * plen)
@@ -1415,8 +1529,8 @@
 
 	/* Right margin includes hsync */
 	var->left_margin = hdb_off + prescale * ((hw->hdb & 0x1ff) -
-					   (hw->hdb & 0x200 ? 2+hw->hht : 0));
-	if (hw->ste_mode || mon_type!=F_MON_VGA)
+					   (hw->hdb & 0x200 ? 2 + hw->hht : 0));
+	if (hw->ste_mode || mon_type != F_MON_VGA)
 		var->right_margin = prescale * (hw->hht + 2 - hw->hde) - hde_off;
 	else
 		/* can't use this in ste_mode, because hbb is +1 off */
@@ -1424,15 +1538,14 @@
 	var->hsync_len = prescale * (hw->hht + 2 - hw->hss);
 
 	/* Lower margin includes vsync */
-	var->upper_margin = hw->vdb / 2 ;  /* round down to full lines */
-	var->lower_margin = (hw->vft+1 - hw->vde + 1) / 2; /* round up */
-	var->vsync_len    = (hw->vft+1 - hw->vss + 1) / 2; /* round up */
+	var->upper_margin = hw->vdb / 2;	/* round down to full lines */
+	var->lower_margin = (hw->vft + 1 - hw->vde + 1) / 2;	/* round up */
+	var->vsync_len = (hw->vft + 1 - hw->vss + 1) / 2;	/* round up */
 	if (var->vmode & FB_VMODE_INTERLACED) {
 		var->upper_margin *= 2;
 		var->lower_margin *= 2;
 		var->vsync_len *= 2;
-	}
-	else if (var->vmode & FB_VMODE_DOUBLE) {
+	} else if (var->vmode & FB_VMODE_DOUBLE) {
 		var->upper_margin = (var->upper_margin + 1) / 2;
 		var->lower_margin = (var->lower_margin + 1) / 2;
 		var->vsync_len = (var->vsync_len + 1) / 2;
@@ -1447,20 +1560,19 @@
 	var->lower_margin -= var->vsync_len;
 
 	if (screen_base)
-		var->yoffset=(par->screen_base - screen_base)/linelen;
+		var->yoffset = (par->screen_base - screen_base) / linelen;
 	else
-		var->yoffset=0;
-	var->nonstd=0;	/* what is this for? */
-	var->activate=0;
+		var->yoffset = 0;
+	var->nonstd = 0;		/* what is this for? */
+	var->activate = 0;
 	return 0;
 }
 
-
-static int f_change_mode = 0;
+static int f_change_mode;
 static struct falcon_hw f_new_mode;
-static int f_pan_display = 0;
+static int f_pan_display;
 
-static void falcon_get_par( struct atafb_par *par )
+static void falcon_get_par(struct atafb_par *par)
 {
 	unsigned long addr;
 	struct falcon_hw *hw = &par->hw.falcon;
@@ -1492,12 +1604,12 @@
 	par->screen_base = phys_to_virt(addr);
 
 	/* derived parameters */
-	hw->ste_mode = (hw->f_shift & 0x510)==0 && hw->st_shift==0x100;
+	hw->ste_mode = (hw->f_shift & 0x510) == 0 && hw->st_shift == 0x100;
 	hw->mono = (hw->f_shift & 0x400) ||
-	           ((hw->f_shift & 0x510)==0 && hw->st_shift==0x200);
+	           ((hw->f_shift & 0x510) == 0 && hw->st_shift == 0x200);
 }
 
-static void falcon_set_par( struct atafb_par *par )
+static void falcon_set_par(struct atafb_par *par)
 {
 	f_change_mode = 0;
 
@@ -1519,8 +1631,7 @@
 	f_change_mode = 1;
 }
 
-
-static irqreturn_t falcon_vbl_switcher( int irq, void *dummy )
+static irqreturn_t falcon_vbl_switcher(int irq, void *dummy)
 {
 	struct falcon_hw *hw = &f_new_mode;
 
@@ -1529,11 +1640,10 @@
 
 		if (hw->sync & 0x1) {
 			/* Enable external pixelclock. This code only for ScreenWonder */
-			*(volatile unsigned short*)0xffff9202 = 0xffbf;
-		}
-		else {
+			*(volatile unsigned short *)0xffff9202 = 0xffbf;
+		} else {
 			/* Turn off external clocks. Read sets all output bits to 1. */
-			*(volatile unsigned short*)0xffff9202;
+			*(volatile unsigned short *)0xffff9202;
 		}
 		shifter.syncmode = hw->sync;
 
@@ -1550,15 +1660,14 @@
 		videl.vde = hw->vde;
 		videl.vss = hw->vss;
 
-		videl.f_shift = 0; /* write enables Falcon palette, 0: 4 planes */
+		videl.f_shift = 0;	/* write enables Falcon palette, 0: 4 planes */
 		if (hw->ste_mode) {
-			videl.st_shift = hw->st_shift; /* write enables STE palette */
-		}
-		else {
+			videl.st_shift = hw->st_shift;	/* write enables STE palette */
+		} else {
 			/* IMPORTANT:
-			 * set st_shift 0, so we can tell the screen-depth if f_shift==0.
+			 * set st_shift 0, so we can tell the screen-depth if f_shift == 0.
 			 * Writing 0 to f_shift enables 4 plane Falcon mode but
-			 * doesn't set st_shift. st_shift!=0 (!=4planes) is impossible
+			 * doesn't set st_shift. st_shift != 0 (!= 4planes) is impossible
 			 * with Falcon palette.
 			 */
 			videl.st_shift = 0;
@@ -1580,12 +1689,13 @@
 	return IRQ_HANDLED;
 }
 
-
-static int falcon_pan_display( struct fb_var_screeninfo *var,
-							   struct atafb_par *par )
+static int falcon_pan_display(struct fb_var_screeninfo *var,
+			      struct fb_info *info)
 {
+	struct atafb_par *par = (struct atafb_par *)info->par;
+
 	int xoffset;
-	int bpp = fb_display[fb_info.currcon].var.bits_per_pixel;
+	int bpp = info->var.bits_per_pixel;
 
 	if (bpp == 1)
 		var->xoffset = up(var->xoffset, 32);
@@ -1596,45 +1706,24 @@
 		var->xoffset = up(var->xoffset, 2);
 	}
 	par->hw.falcon.line_offset = bpp *
-	       	(fb_display[fb_info.currcon].var.xres_virtual - fb_display[fb_info.currcon].var.xres) / 16;
+		(info->var.xres_virtual - info->var.xres) / 16;
 	if (par->hw.falcon.xoffset)
 		par->hw.falcon.line_offset -= bpp;
 	xoffset = var->xoffset - par->hw.falcon.xoffset;
 
 	par->screen_base = screen_base +
-	        (var->yoffset * fb_display[fb_info.currcon].var.xres_virtual + xoffset) * bpp / 8;
+	        (var->yoffset * info->var.xres_virtual + xoffset) * bpp / 8;
 	if (fbhw->set_screen_base)
-		fbhw->set_screen_base (par->screen_base);
+		fbhw->set_screen_base(par->screen_base);
 	else
-		return -EINVAL; /* shouldn't happen */
+		return -EINVAL;		/* shouldn't happen */
 	f_pan_display = 1;
 	return 0;
 }
 
-
-static int falcon_getcolreg( unsigned regno, unsigned *red,
-				 unsigned *green, unsigned *blue,
-				 unsigned *transp, struct fb_info *info )
-{	unsigned long col;
-	
-	if (regno > 255)
-		return 1;
-	/* This works in STE-mode (with 4bit/color) since f030_col-registers
-	 * hold up to 6bit/color.
-	 * Even with hicolor r/g/b=5/6/5 bit!
-	 */
-	col = f030_col[regno];
-	*red = (col >> 16) & 0xff00;
-	*green = (col >> 8) & 0xff00;
-	*blue = (col << 8) & 0xff00;
-	*transp = 0;
-	return 0;
-}
-
-
-static int falcon_setcolreg( unsigned regno, unsigned red,
-							 unsigned green, unsigned blue,
-							 unsigned transp, struct fb_info *info )
+static int falcon_setcolreg(unsigned int regno, unsigned int red,
+			    unsigned int green, unsigned int blue,
+			    unsigned int transp, struct fb_info *info)
 {
 	if (regno > 255)
 		return 1;
@@ -1655,13 +1744,12 @@
 	return 0;
 }
 
-
-static int falcon_blank( int blank_mode )
+static int falcon_blank(int blank_mode)
 {
-/* ++guenther: we can switch off graphics by changing VDB and VDE,
- * so VIDEL doesn't hog the bus while saving.
- * (this may affect usleep()).
- */
+	/* ++guenther: we can switch off graphics by changing VDB and VDE,
+	 * so VIDEL doesn't hog the bus while saving.
+	 * (this may affect usleep()).
+	 */
 	int vdb, vss, hbe, hss;
 
 	if (mon_type == F_MON_SM)	/* this doesn't work on SM124 */
@@ -1694,14 +1782,13 @@
 	return 0;
 }
 
- 
-static int falcon_detect( void )
+static int falcon_detect(void)
 {
 	struct atafb_par par;
 	unsigned char fhw;
 
 	/* Determine connected monitor and set monitor parameters */
-	fhw = *(unsigned char*)0xffff8006;
+	fhw = *(unsigned char *)0xffff8006;
 	mon_type = fhw >> 6 & 0x3;
 	/* bit 1 of fhw: 1=32 bit ram bus, 0=16 bit */
 	f030_bus_width = fhw << 6 & 0x80;
@@ -1715,7 +1802,7 @@
 	case F_MON_SC:
 	case F_MON_TV:
 		/* PAL...NTSC */
-		fb_info.monspecs.vfmin = 49; /* not 50, since TOS defaults to 49.9x Hz */
+		fb_info.monspecs.vfmin = 49;	/* not 50, since TOS defaults to 49.9x Hz */
 		fb_info.monspecs.vfmax = 60;
 		fb_info.monspecs.hfmin = 15620;
 		fb_info.monspecs.hfmax = 15755;
@@ -1740,13 +1827,12 @@
 
 #ifdef ATAFB_STE
 
-static int stste_encode_fix( struct fb_fix_screeninfo *fix,
-							 struct atafb_par *par )
-
+static int stste_encode_fix(struct fb_fix_screeninfo *fix,
+			    struct atafb_par *par)
 {
 	int mode;
 
-	strcpy(fix->id,"Atari Builtin");
+	strcpy(fix->id, "Atari Builtin");
 	fix->smem_start = (unsigned long)real_screen_base;
 	fix->smem_len = screen_len;
 	fix->type = FB_TYPE_INTERLEAVED_PLANES;
@@ -1771,43 +1857,40 @@
 	return 0;
 }
 
-
-static int stste_decode_var( struct fb_var_screeninfo *var,
-						  struct atafb_par *par )
+static int stste_decode_var(struct fb_var_screeninfo *var,
+			    struct atafb_par *par)
 {
-	int xres=var->xres;
-	int yres=var->yres;
-	int bpp=var->bits_per_pixel;
+	int xres = var->xres;
+	int yres = var->yres;
+	int bpp = var->bits_per_pixel;
 	int linelen;
 	int yres_virtual = var->yres_virtual;
 
 	if (mono_moni) {
 		if (bpp > 1 || xres > sttt_xres || yres > st_yres)
 			return -EINVAL;
-		par->hw.st.mode=ST_HIGH;
-		xres=sttt_xres;
-		yres=st_yres;
-		bpp=1;
+		par->hw.st.mode = ST_HIGH;
+		xres = sttt_xres;
+		yres = st_yres;
+		bpp = 1;
 	} else {
 		if (bpp > 4 || xres > sttt_xres || yres > st_yres)
 			return -EINVAL;
 		if (bpp > 2) {
-			if (xres > sttt_xres/2 || yres > st_yres/2)
+			if (xres > sttt_xres / 2 || yres > st_yres / 2)
 				return -EINVAL;
-			par->hw.st.mode=ST_LOW;
-			xres=sttt_xres/2;
-			yres=st_yres/2;
-			bpp=4;
-		}
-		else if (bpp > 1) {
-			if (xres > sttt_xres || yres > st_yres/2)
+			par->hw.st.mode = ST_LOW;
+			xres = sttt_xres / 2;
+			yres = st_yres / 2;
+			bpp = 4;
+		} else if (bpp > 1) {
+			if (xres > sttt_xres || yres > st_yres / 2)
 				return -EINVAL;
-			par->hw.st.mode=ST_MID;
-			xres=sttt_xres;
-			yres=st_yres/2;
-			bpp=2;
-		}
-		else
+			par->hw.st.mode = ST_MID;
+			xres = sttt_xres;
+			yres = st_yres / 2;
+			bpp = 2;
+		} else
 			return -EINVAL;
 	}
 	if (yres_virtual <= 0)
@@ -1815,10 +1898,10 @@
 	else if (yres_virtual < yres)
 		yres_virtual = yres;
 	if (var->sync & FB_SYNC_EXT)
-		par->hw.st.sync=(par->hw.st.sync & ~1) | 1;
+		par->hw.st.sync = (par->hw.st.sync & ~1) | 1;
 	else
-		par->hw.st.sync=(par->hw.st.sync & ~1);
-	linelen=xres*bpp/8;
+		par->hw.st.sync = (par->hw.st.sync & ~1);
+	linelen = xres * bpp / 8;
 	if (yres_virtual * linelen > screen_len && screen_len)
 		return -EINVAL;
 	if (yres * linelen > screen_len && screen_len)
@@ -1826,93 +1909,91 @@
 	if (var->yoffset + yres > yres_virtual && yres_virtual)
 		return -EINVAL;
 	par->yres_virtual = yres_virtual;
-	par->screen_base=screen_base+ var->yoffset*linelen;
+	par->screen_base = screen_base + var->yoffset * linelen;
 	return 0;
 }
 
-static int stste_encode_var( struct fb_var_screeninfo *var,
-						  struct atafb_par *par )
+static int stste_encode_var(struct fb_var_screeninfo *var,
+			    struct atafb_par *par)
 {
 	int linelen;
 	memset(var, 0, sizeof(struct fb_var_screeninfo));
-	var->red.offset=0;
+	var->red.offset = 0;
 	var->red.length = ATARIHW_PRESENT(EXTD_SHIFTER) ? 4 : 3;
-	var->red.msb_right=0;
-	var->grayscale=0;
+	var->red.msb_right = 0;
+	var->grayscale = 0;
 
-	var->pixclock=31041;
-	var->left_margin=120;		/* these are incorrect */
-	var->right_margin=100;
-	var->upper_margin=8;
-	var->lower_margin=16;
-	var->hsync_len=140;
-	var->vsync_len=30;
+	var->pixclock = 31041;
+	var->left_margin = 120;		/* these are incorrect */
+	var->right_margin = 100;
+	var->upper_margin = 8;
+	var->lower_margin = 16;
+	var->hsync_len = 140;
+	var->vsync_len = 30;
 
-	var->height=-1;
-	var->width=-1;
+	var->height = -1;
+	var->width = -1;
 
 	if (!(par->hw.st.sync & 1))
-		var->sync=0;
+		var->sync = 0;
 	else
-		var->sync=FB_SYNC_EXT;
+		var->sync = FB_SYNC_EXT;
 
 	switch (par->hw.st.mode & 3) {
 	case ST_LOW:
-		var->xres=sttt_xres/2;
-		var->yres=st_yres/2;
-		var->bits_per_pixel=4;
+		var->xres = sttt_xres / 2;
+		var->yres = st_yres / 2;
+		var->bits_per_pixel = 4;
 		break;
 	case ST_MID:
-		var->xres=sttt_xres;
-		var->yres=st_yres/2;
-		var->bits_per_pixel=2;
+		var->xres = sttt_xres;
+		var->yres = st_yres / 2;
+		var->bits_per_pixel = 2;
 		break;
 	case ST_HIGH:
-		var->xres=sttt_xres;
-		var->yres=st_yres;
-		var->bits_per_pixel=1;
+		var->xres = sttt_xres;
+		var->yres = st_yres;
+		var->bits_per_pixel = 1;
 		break;
-	}		
-	var->blue=var->green=var->red;
-	var->transp.offset=0;
-	var->transp.length=0;
-	var->transp.msb_right=0;
-	var->xres_virtual=sttt_xres_virtual;
-	linelen=var->xres_virtual * var->bits_per_pixel / 8;
-	ovsc_addlen=linelen*(sttt_yres_virtual - st_yres);
-	
-	if (! use_hwscroll)
-		var->yres_virtual=var->yres;
+	}
+	var->blue = var->green = var->red;
+	var->transp.offset = 0;
+	var->transp.length = 0;
+	var->transp.msb_right = 0;
+	var->xres_virtual = sttt_xres_virtual;
+	linelen = var->xres_virtual * var->bits_per_pixel / 8;
+	ovsc_addlen = linelen * (sttt_yres_virtual - st_yres);
+
+	if (!use_hwscroll)
+		var->yres_virtual = var->yres;
 	else if (screen_len) {
 		if (par->yres_virtual)
 			var->yres_virtual = par->yres_virtual;
 		else
-			/* yres_virtual==0 means use maximum */
+			/* yres_virtual == 0 means use maximum */
 			var->yres_virtual = screen_len / linelen;
-	}
-	else {
+	} else {
 		if (hwscroll < 0)
 			var->yres_virtual = 2 * var->yres;
 		else
-			var->yres_virtual=var->yres+hwscroll * 16;
+			var->yres_virtual = var->yres + hwscroll * 16;
 	}
-	var->xoffset=0;
+	var->xoffset = 0;
 	if (screen_base)
-		var->yoffset=(par->screen_base - screen_base)/linelen;
+		var->yoffset = (par->screen_base - screen_base) / linelen;
 	else
-		var->yoffset=0;
-	var->nonstd=0;
-	var->activate=0;
-	var->vmode=FB_VMODE_NONINTERLACED;
+		var->yoffset = 0;
+	var->nonstd = 0;
+	var->activate = 0;
+	var->vmode = FB_VMODE_NONINTERLACED;
 	return 0;
 }
 
-
-static void stste_get_par( struct atafb_par *par )
+static void stste_get_par(struct atafb_par *par)
 {
 	unsigned long addr;
-	par->hw.st.mode=shifter_tt.st_shiftmode;
-	par->hw.st.sync=shifter.syncmode;
+	par->hw.st.mode = shifter_tt.st_shiftmode;
+	par->hw.st.sync = shifter.syncmode;
 	addr = ((shifter.bas_hi & 0xff) << 16) |
 	       ((shifter.bas_md & 0xff) << 8);
 	if (ATARIHW_PRESENT(EXTD_SHIFTER))
@@ -1920,55 +2001,18 @@
 	par->screen_base = phys_to_virt(addr);
 }
 
-static void stste_set_par( struct atafb_par *par )
+static void stste_set_par(struct atafb_par *par)
 {
-	shifter_tt.st_shiftmode=par->hw.st.mode;
-	shifter.syncmode=par->hw.st.sync;
+	shifter_tt.st_shiftmode = par->hw.st.mode;
+	shifter.syncmode = par->hw.st.sync;
 	/* only set screen_base if really necessary */
 	if (current_par.screen_base != par->screen_base)
 		fbhw->set_screen_base(par->screen_base);
 }
 
-
-static int stste_getcolreg(unsigned regno, unsigned *red,
-			   unsigned *green, unsigned *blue,
-			   unsigned *transp, struct fb_info *info)
-{
-	unsigned col, t;
-	
-	if (regno > 15)
-		return 1;
-	col = shifter_tt.color_reg[regno];
-	if (ATARIHW_PRESENT(EXTD_SHIFTER)) {
-		t = ((col >> 7) & 0xe) | ((col >> 11) & 1);
-		t |= t << 4;
-		*red = t | (t << 8);
-		t = ((col >> 3) & 0xe) | ((col >> 7) & 1);
-		t |= t << 4;
-		*green = t | (t << 8);
-		t = ((col << 1) & 0xe) | ((col >> 3) & 1);
-		t |= t << 4;
-		*blue = t | (t << 8);
-	}
-	else {
-		t = (col >> 7) & 0xe;
-		t |= t << 4;
-		*red = t | (t << 8);
-		t = (col >> 3) & 0xe;
-		t |= t << 4;
-		*green = t | (t << 8);
-		t = (col << 1) & 0xe;
-		t |= t << 4;
-		*blue = t | (t << 8);
-	}
-	*transp = 0;
-	return 0;
-}
-
-
-static int stste_setcolreg(unsigned regno, unsigned red,
-			   unsigned green, unsigned blue,
-			   unsigned transp, struct fb_info *info)
+static int stste_setcolreg(unsigned int regno, unsigned int red,
+			   unsigned int green, unsigned int blue,
+			   unsigned int transp, struct fb_info *info)
 {
 	if (regno > 15)
 		return 1;
@@ -1988,10 +2032,9 @@
 	return 0;
 }
 
-						  
-static int stste_detect( void )
-
-{	struct atafb_par par;
+static int stste_detect(void)
+{
+	struct atafb_par par;
 
 	/* Determine the connected monitor: The DMA sound must be
 	 * disabled before reading the MFP GPIP, because the Sound
@@ -1999,7 +2042,7 @@
 	 */
 	if (ATARIHW_PRESENT(PCM_8BIT)) {
 		tt_dmasnd.ctrl = DMASND_CTRL_OFF;
-		udelay(20);	/* wait a while for things to settle down */
+		udelay(20);		/* wait a while for things to settle down */
 	}
 	mono_moni = (mfp.par_dt_reg & 0x80) == 0;
 
@@ -2014,12 +2057,12 @@
 static void stste_set_screen_base(void *s_base)
 {
 	unsigned long addr;
-	addr= virt_to_phys(s_base);
+	addr = virt_to_phys(s_base);
 	/* Setup Screen Memory */
-	shifter.bas_hi=(unsigned char) ((addr & 0xff0000) >> 16);
-  	shifter.bas_md=(unsigned char) ((addr & 0x00ff00) >> 8);
+	shifter.bas_hi = (unsigned char)((addr & 0xff0000) >> 16);
+	shifter.bas_md = (unsigned char)((addr & 0x00ff00) >> 8);
 	if (ATARIHW_PRESENT(EXTD_SHIFTER))
-		shifter.bas_lo=(unsigned char)  (addr & 0x0000ff);
+		shifter.bas_lo = (unsigned char)(addr & 0x0000ff);
 }
 
 #endif /* ATAFB_STE */
@@ -2045,51 +2088,49 @@
 /* SWITCH_ACIA may be used for Falcon (ScreenBlaster III internal!) */
 static void st_ovsc_switch(void)
 {
-    unsigned long flags;
-    register unsigned char old, new;
+	unsigned long flags;
+	register unsigned char old, new;
 
-    if (!(atari_switches & ATARI_SWITCH_OVSC_MASK))
-	return;
-    local_irq_save(flags);
+	if (!(atari_switches & ATARI_SWITCH_OVSC_MASK))
+		return;
+	local_irq_save(flags);
 
-    mfp.tim_ct_b = 0x10;
-    mfp.active_edge |= 8;
-    mfp.tim_ct_b = 0;
-    mfp.tim_dt_b = 0xf0;
-    mfp.tim_ct_b = 8;
-    while (mfp.tim_dt_b > 1)	/* TOS does it this way, don't ask why */
-	;
-    new = mfp.tim_dt_b;
-    do {
-	udelay(LINE_DELAY);
-	old = new;
+	mfp.tim_ct_b = 0x10;
+	mfp.active_edge |= 8;
+	mfp.tim_ct_b = 0;
+	mfp.tim_dt_b = 0xf0;
+	mfp.tim_ct_b = 8;
+	while (mfp.tim_dt_b > 1)	/* TOS does it this way, don't ask why */
+		;
 	new = mfp.tim_dt_b;
-    } while (old != new);
-    mfp.tim_ct_b = 0x10;
-    udelay(SYNC_DELAY);
+	do {
+		udelay(LINE_DELAY);
+		old = new;
+		new = mfp.tim_dt_b;
+	} while (old != new);
+	mfp.tim_ct_b = 0x10;
+	udelay(SYNC_DELAY);
 
-    if (atari_switches & ATARI_SWITCH_OVSC_IKBD)
-	acia.key_ctrl = ACIA_DIV64 | ACIA_D8N1S | ACIA_RHTID | ACIA_RIE;
-    if (atari_switches & ATARI_SWITCH_OVSC_MIDI)
-	acia.mid_ctrl = ACIA_DIV16 | ACIA_D8N1S | ACIA_RHTID;
-    if (atari_switches & (ATARI_SWITCH_OVSC_SND6|ATARI_SWITCH_OVSC_SND7)) {
-	sound_ym.rd_data_reg_sel = 14;
-	sound_ym.wd_data = sound_ym.rd_data_reg_sel |
-			   ((atari_switches&ATARI_SWITCH_OVSC_SND6) ? 0x40:0) |
-			   ((atari_switches&ATARI_SWITCH_OVSC_SND7) ? 0x80:0);
-    }
-    local_irq_restore(flags);
+	if (atari_switches & ATARI_SWITCH_OVSC_IKBD)
+		acia.key_ctrl = ACIA_DIV64 | ACIA_D8N1S | ACIA_RHTID | ACIA_RIE;
+	if (atari_switches & ATARI_SWITCH_OVSC_MIDI)
+		acia.mid_ctrl = ACIA_DIV16 | ACIA_D8N1S | ACIA_RHTID;
+	if (atari_switches & (ATARI_SWITCH_OVSC_SND6|ATARI_SWITCH_OVSC_SND7)) {
+		sound_ym.rd_data_reg_sel = 14;
+		sound_ym.wd_data = sound_ym.rd_data_reg_sel |
+				   ((atari_switches & ATARI_SWITCH_OVSC_SND6) ? 0x40:0) |
+				   ((atari_switches & ATARI_SWITCH_OVSC_SND7) ? 0x80:0);
+	}
+	local_irq_restore(flags);
 }
 
 /* ------------------- External Video ---------------------- */
 
 #ifdef ATAFB_EXT
 
-static int ext_encode_fix( struct fb_fix_screeninfo *fix,
-						   struct atafb_par *par )
-
+static int ext_encode_fix(struct fb_fix_screeninfo *fix, struct atafb_par *par)
 {
-	strcpy(fix->id,"Unknown Extern");
+	strcpy(fix->id, "Unknown Extern");
 	fix->smem_start = (unsigned long)external_addr;
 	fix->smem_len = PAGE_ALIGN(external_len);
 	if (external_depth == 1) {
@@ -2099,31 +2140,29 @@
 		fix->visual =
 			(external_pmode == FB_TYPE_INTERLEAVED_PLANES ||
 			 external_pmode == FB_TYPE_PACKED_PIXELS) ?
-				FB_VISUAL_MONO10 :
-					FB_VISUAL_MONO01;
-	}
-	else {
+				FB_VISUAL_MONO10 : FB_VISUAL_MONO01;
+	} else {
 		/* Use STATIC if we don't know how to access color registers */
 		int visual = external_vgaiobase ?
 					 FB_VISUAL_PSEUDOCOLOR :
 					 FB_VISUAL_STATIC_PSEUDOCOLOR;
 		switch (external_pmode) {
-		    case -1:              /* truecolor */
-			fix->type=FB_TYPE_PACKED_PIXELS;
-			fix->visual=FB_VISUAL_TRUECOLOR;
+		case -1:		/* truecolor */
+			fix->type = FB_TYPE_PACKED_PIXELS;
+			fix->visual = FB_VISUAL_TRUECOLOR;
 			break;
-		    case FB_TYPE_PACKED_PIXELS:
-			fix->type=FB_TYPE_PACKED_PIXELS;
-			fix->visual=visual;
+		case FB_TYPE_PACKED_PIXELS:
+			fix->type = FB_TYPE_PACKED_PIXELS;
+			fix->visual = visual;
 			break;
-		    case FB_TYPE_PLANES:
-			fix->type=FB_TYPE_PLANES;
-			fix->visual=visual;
+		case FB_TYPE_PLANES:
+			fix->type = FB_TYPE_PLANES;
+			fix->visual = visual;
 			break;
-		    case FB_TYPE_INTERLEAVED_PLANES:
-			fix->type=FB_TYPE_INTERLEAVED_PLANES;
-			fix->type_aux=2;
-			fix->visual=visual;
+		case FB_TYPE_INTERLEAVED_PLANES:
+			fix->type = FB_TYPE_INTERLEAVED_PLANES;
+			fix->type_aux = 2;
+			fix->visual = visual;
 			break;
 		}
 	}
@@ -2134,137 +2173,112 @@
 	return 0;
 }
 
-
-static int ext_decode_var( struct fb_var_screeninfo *var,
-						   struct atafb_par *par )
+static int ext_decode_var(struct fb_var_screeninfo *var, struct atafb_par *par)
 {
 	struct fb_var_screeninfo *myvar = &atafb_predefined[0];
-	
+
 	if (var->bits_per_pixel > myvar->bits_per_pixel ||
-		var->xres > myvar->xres ||
-		var->xres_virtual > myvar->xres_virtual ||
-		var->yres > myvar->yres ||
-		var->xoffset > 0 ||
-		var->yoffset > 0)
+	    var->xres > myvar->xres ||
+	    var->xres_virtual > myvar->xres_virtual ||
+	    var->yres > myvar->yres ||
+	    var->xoffset > 0 ||
+	    var->yoffset > 0)
 		return -EINVAL;
 	return 0;
 }
 
-
-static int ext_encode_var( struct fb_var_screeninfo *var,
-						   struct atafb_par *par )
+static int ext_encode_var(struct fb_var_screeninfo *var, struct atafb_par *par)
 {
 	memset(var, 0, sizeof(struct fb_var_screeninfo));
-	var->red.offset=0;
-	var->red.length=(external_pmode == -1) ? external_depth/3 : 
+	var->red.offset = 0;
+	var->red.length = (external_pmode == -1) ? external_depth / 3 :
 			(external_vgaiobase ? external_bitspercol : 0);
-	var->red.msb_right=0;
-	var->grayscale=0;
+	var->red.msb_right = 0;
+	var->grayscale = 0;
 
-	var->pixclock=31041;
-	var->left_margin=120;		/* these are surely incorrect 	*/
-	var->right_margin=100;
-	var->upper_margin=8;
-	var->lower_margin=16;
-	var->hsync_len=140;
-	var->vsync_len=30;
+	var->pixclock = 31041;
+	var->left_margin = 120;		/* these are surely incorrect */
+	var->right_margin = 100;
+	var->upper_margin = 8;
+	var->lower_margin = 16;
+	var->hsync_len = 140;
+	var->vsync_len = 30;
 
-	var->height=-1;
-	var->width=-1;
+	var->height = -1;
+	var->width = -1;
 
-	var->sync=0;
+	var->sync = 0;
 
 	var->xres = external_xres;
 	var->yres = external_yres;
 	var->xres_virtual = external_xres_virtual;
 	var->bits_per_pixel = external_depth;
-	
-	var->blue=var->green=var->red;
-	var->transp.offset=0;
-	var->transp.length=0;
-	var->transp.msb_right=0;
-	var->yres_virtual=var->yres;
-	var->xoffset=0;
-	var->yoffset=0;
-	var->nonstd=0;
-	var->activate=0;
-	var->vmode=FB_VMODE_NONINTERLACED;
+
+	var->blue = var->green = var->red;
+	var->transp.offset = 0;
+	var->transp.length = 0;
+	var->transp.msb_right = 0;
+	var->yres_virtual = var->yres;
+	var->xoffset = 0;
+	var->yoffset = 0;
+	var->nonstd = 0;
+	var->activate = 0;
+	var->vmode = FB_VMODE_NONINTERLACED;
 	return 0;
 }
 
-
-static void ext_get_par( struct atafb_par *par )
+static void ext_get_par(struct atafb_par *par)
 {
 	par->screen_base = external_addr;
 }
 
-static void ext_set_par( struct atafb_par *par )
+static void ext_set_par(struct atafb_par *par)
 {
 }
 
 #define OUTB(port,val) \
-	*((unsigned volatile char *) ((port)+external_vgaiobase))=(val)
+	*((unsigned volatile char *) ((port)+external_vgaiobase)) = (val)
 #define INB(port) \
 	(*((unsigned volatile char *) ((port)+external_vgaiobase)))
-#define DACDelay 				\
+#define DACDelay				\
 	do {					\
-		unsigned char tmp=INB(0x3da);	\
-		tmp=INB(0x3da);			\
+		unsigned char tmp = INB(0x3da);	\
+		tmp = INB(0x3da);			\
 	} while (0)
 
-static int ext_getcolreg( unsigned regno, unsigned *red,
-						  unsigned *green, unsigned *blue,
-						  unsigned *transp, struct fb_info *info )
+static int ext_setcolreg(unsigned int regno, unsigned int red,
+			 unsigned int green, unsigned int blue,
+			 unsigned int transp, struct fb_info *info)
 {
-	if (! external_vgaiobase)
+	unsigned char colmask = (1 << external_bitspercol) - 1;
+
+	if (!external_vgaiobase)
 		return 1;
 
-	    *red   = ext_color[regno].red;
-	    *green = ext_color[regno].green;
-	    *blue  = ext_color[regno].blue;
-	    *transp=0;
-	    return 0;
-}
-	
-static int ext_setcolreg( unsigned regno, unsigned red,
-						  unsigned green, unsigned blue,
-						  unsigned transp, struct fb_info *info )
-
-{	unsigned char colmask = (1 << external_bitspercol) - 1;
-
-	if (! external_vgaiobase)
-		return 1;
-
-	ext_color[regno].red = red;
-	ext_color[regno].green = green;
-	ext_color[regno].blue = blue;
-
 	switch (external_card_type) {
-	  case IS_VGA:
-	    OUTB(0x3c8, regno);
-	    DACDelay;
-	    OUTB(0x3c9, red & colmask);
-	    DACDelay;
-	    OUTB(0x3c9, green & colmask);
-	    DACDelay;
-	    OUTB(0x3c9, blue & colmask);
-	    DACDelay;
-	    return 0;
+	case IS_VGA:
+		OUTB(0x3c8, regno);
+		DACDelay;
+		OUTB(0x3c9, red & colmask);
+		DACDelay;
+		OUTB(0x3c9, green & colmask);
+		DACDelay;
+		OUTB(0x3c9, blue & colmask);
+		DACDelay;
+		return 0;
 
-	  case IS_MV300:
-	    OUTB((MV300_reg[regno] << 2)+1, red);
-	    OUTB((MV300_reg[regno] << 2)+1, green);
-	    OUTB((MV300_reg[regno] << 2)+1, blue);
-	    return 0;
+	case IS_MV300:
+		OUTB((MV300_reg[regno] << 2) + 1, red);
+		OUTB((MV300_reg[regno] << 2) + 1, green);
+		OUTB((MV300_reg[regno] << 2) + 1, blue);
+		return 0;
 
-	  default:
-	    return 1;
-	  }
+	default:
+		return 1;
+	}
 }
-	
 
-static int ext_detect( void )
-
+static int ext_detect(void)
 {
 	struct fb_var_screeninfo *myvar = &atafb_predefined[0];
 	struct atafb_par dummy_par;
@@ -2284,213 +2298,182 @@
 static void set_screen_base(void *s_base)
 {
 	unsigned long addr;
-	addr= virt_to_phys(s_base);
+
+	addr = virt_to_phys(s_base);
 	/* Setup Screen Memory */
-	shifter.bas_hi=(unsigned char) ((addr & 0xff0000) >> 16);
-  	shifter.bas_md=(unsigned char) ((addr & 0x00ff00) >> 8);
-  	shifter.bas_lo=(unsigned char)  (addr & 0x0000ff);
+	shifter.bas_hi = (unsigned char)((addr & 0xff0000) >> 16);
+	shifter.bas_md = (unsigned char)((addr & 0x00ff00) >> 8);
+	shifter.bas_lo = (unsigned char)(addr & 0x0000ff);
 }
 
-
-static int pan_display( struct fb_var_screeninfo *var,
-                        struct atafb_par *par )
+static int pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
 {
+	struct atafb_par *par = (struct atafb_par *)info->par;
+
 	if (!fbhw->set_screen_base ||
-		(!ATARIHW_PRESENT(EXTD_SHIFTER) && var->xoffset))
+	    (!ATARIHW_PRESENT(EXTD_SHIFTER) && var->xoffset))
 		return -EINVAL;
 	var->xoffset = up(var->xoffset, 16);
 	par->screen_base = screen_base +
-	        (var->yoffset * fb_display[fb_info.currcon].var.xres_virtual + var->xoffset)
-	        * fb_display[fb_info.currcon].var.bits_per_pixel / 8;
-	fbhw->set_screen_base (par->screen_base);
+	        (var->yoffset * info->var.xres_virtual + var->xoffset)
+	        * info->var.bits_per_pixel / 8;
+	fbhw->set_screen_base(par->screen_base);
 	return 0;
 }
 
-
 /* ------------ Interfaces to hardware functions ------------ */
 
-
 #ifdef ATAFB_TT
 static struct fb_hwswitch tt_switch = {
-	tt_detect, tt_encode_fix, tt_decode_var, tt_encode_var,
-	tt_get_par, tt_set_par, tt_getcolreg, 
-	set_screen_base, NULL, pan_display
+	.detect		= tt_detect,
+	.encode_fix	= tt_encode_fix,
+	.decode_var	= tt_decode_var,
+	.encode_var	= tt_encode_var,
+	.get_par	= tt_get_par,
+	.set_par	= tt_set_par,
+	.set_screen_base = set_screen_base,
+	.pan_display	= pan_display,
 };
 #endif
 
 #ifdef ATAFB_FALCON
 static struct fb_hwswitch falcon_switch = {
-	falcon_detect, falcon_encode_fix, falcon_decode_var, falcon_encode_var,
-	falcon_get_par, falcon_set_par, falcon_getcolreg,
-	set_screen_base, falcon_blank, falcon_pan_display
+	.detect		= falcon_detect,
+	.encode_fix	= falcon_encode_fix,
+	.decode_var	= falcon_decode_var,
+	.encode_var	= falcon_encode_var,
+	.get_par	= falcon_get_par,
+	.set_par	= falcon_set_par,
+	.set_screen_base = set_screen_base,
+	.blank		= falcon_blank,
+	.pan_display	= falcon_pan_display,
 };
 #endif
 
 #ifdef ATAFB_STE
 static struct fb_hwswitch st_switch = {
-	stste_detect, stste_encode_fix, stste_decode_var, stste_encode_var,
-	stste_get_par, stste_set_par, stste_getcolreg,
-	stste_set_screen_base, NULL, pan_display
+	.detect		= stste_detect,
+	.encode_fix	= stste_encode_fix,
+	.decode_var	= stste_decode_var,
+	.encode_var	= stste_encode_var,
+	.get_par	= stste_get_par,
+	.set_par	= stste_set_par,
+	.set_screen_base = stste_set_screen_base,
+	.pan_display	= pan_display
 };
 #endif
 
 #ifdef ATAFB_EXT
 static struct fb_hwswitch ext_switch = {
-	ext_detect, ext_encode_fix, ext_decode_var, ext_encode_var,
-	ext_get_par, ext_set_par, ext_getcolreg, NULL, NULL, NULL
+	.detect		= ext_detect,
+	.encode_fix	= ext_encode_fix,
+	.decode_var	= ext_decode_var,
+	.encode_var	= ext_encode_var,
+	.get_par	= ext_get_par,
+	.set_par	= ext_set_par,
 };
 #endif
 
-
-
-static void atafb_get_par( struct atafb_par *par )
+static void ata_get_par(struct atafb_par *par)
 {
-	if (current_par_valid) {
-		*par=current_par;
-	}
+	if (current_par_valid)
+		*par = current_par;
 	else
 		fbhw->get_par(par);
 }
 
-
-static void atafb_set_par( struct atafb_par *par )
+static void ata_set_par(struct atafb_par *par)
 {
 	fbhw->set_par(par);
-	current_par=*par;
-	current_par_valid=1;
+	current_par = *par;
+	current_par_valid = 1;
 }
 
 
-
 /* =========================================================== */
 /* ============== Hardware Independent Functions ============= */
 /* =========================================================== */
 
-
 /* used for hardware scrolling */
 
-static int
-fb_update_var(int con, struct fb_info *info)
+static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive)
 {
-	int off=fb_display[con].var.yoffset*fb_display[con].var.xres_virtual*
-			fb_display[con].var.bits_per_pixel>>3;
-
-	current_par.screen_base=screen_base + off;
-
-	if (fbhw->set_screen_base)
-		fbhw->set_screen_base(current_par.screen_base);
-	return 0;
-}
-
-static int
-do_fb_set_var(struct fb_var_screeninfo *var, int isactive)
-{
-	int err,activate;
+	int err, activate;
 	struct atafb_par par;
-	if ((err=fbhw->decode_var(var, &par)))
+
+	err = fbhw->decode_var(var, &par);
+	if (err)
 		return err;
-	activate=var->activate;
+	activate = var->activate;
 	if (((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) && isactive)
-		atafb_set_par(&par);
+		ata_set_par(&par);
 	fbhw->encode_var(var, &par);
-	var->activate=activate;
+	var->activate = activate;
 	return 0;
 }
 
-static int
-atafb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
+static int atafb_get_fix(struct fb_fix_screeninfo *fix, struct fb_info *info)
 {
 	struct atafb_par par;
-	if (con == -1)
-		atafb_get_par(&par);
-	else {
-	  int err;
-		if ((err=fbhw->decode_var(&fb_display[con].var,&par)))
-		  return err;
-	}
+	int err;
+	// Get fix directly (case con == -1 before)??
+	err = fbhw->decode_var(&info->var, &par);
+	if (err)
+		return err;
 	memset(fix, 0, sizeof(struct fb_fix_screeninfo));
 	return fbhw->encode_fix(fix, &par);
 }
-	
-static int
-atafb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
+
+static int atafb_get_var(struct fb_var_screeninfo *var, struct fb_info *info)
 {
 	struct atafb_par par;
-	if (con == -1) {
-		atafb_get_par(&par);
-		fbhw->encode_var(var, &par);
-	}
-	else
-		*var=fb_display[con].var;
+
+	ata_get_par(&par);
+	fbhw->encode_var(var, &par);
+
 	return 0;
 }
 
-static void
-atafb_set_disp(int con, struct fb_info *info)
+// No longer called by fbcon!
+// Still called by set_var internally
+
+static void atafb_set_disp(struct fb_info *info)
 {
-	struct fb_fix_screeninfo fix;
-	struct fb_var_screeninfo var;
-	struct display *display;
+	atafb_get_var(&info->var, info);
+	atafb_get_fix(&info->fix, info);
 
-	if (con >= 0)
-		display = &fb_display[con];
-	else
-		display = &disp;	/* used during initialization */
+	info->screen_base = (void *)info->fix.smem_start;
 
-	atafb_get_fix(&fix, con, info);
-	atafb_get_var(&var, con, info);
-	if (con == -1)
-		con=0;
-	info->screen_base = (void *)fix.smem_start;
-	display->visual = fix.visual;
-	display->type = fix.type;
-	display->type_aux = fix.type_aux;
-	display->ypanstep = fix.ypanstep;
-	display->ywrapstep = fix.ywrapstep;
-	display->line_length = fix.line_length;
-	if (fix.visual != FB_VISUAL_PSEUDOCOLOR &&
-		fix.visual != FB_VISUAL_DIRECTCOLOR)
-		display->can_soft_blank = 0;
-	else
-		display->can_soft_blank = 1;
-	display->inverse =
-	    (fix.visual == FB_VISUAL_MONO01 ? !inverse : inverse);
-	switch (fix.type) {
-	    case FB_TYPE_INTERLEAVED_PLANES:
-		switch (var.bits_per_pixel) {
-#ifdef FBCON_HAS_IPLAN2P2
-		    case 2:
-			display->dispsw = &fbcon_iplan2p2;
+	switch (info->fix.type) {
+	case FB_TYPE_INTERLEAVED_PLANES:
+		switch (info->var.bits_per_pixel) {
+		case 2:
+			// display->dispsw = &fbcon_iplan2p2;
 			break;
-#endif
-#ifdef FBCON_HAS_IPLAN2P4
-		    case 4:
-			display->dispsw = &fbcon_iplan2p4;
+		case 4:
+			// display->dispsw = &fbcon_iplan2p4;
 			break;
-#endif
-#ifdef FBCON_HAS_IPLAN2P8
-		    case 8:
-			display->dispsw = &fbcon_iplan2p8;
+		case 8:
+			// display->dispsw = &fbcon_iplan2p8;
 			break;
-#endif
 		}
 		break;
-	    case FB_TYPE_PACKED_PIXELS:
-		switch (var.bits_per_pixel) {
+	case FB_TYPE_PACKED_PIXELS:
+		switch (info->var.bits_per_pixel) {
 #ifdef FBCON_HAS_MFB
-		    case 1:
-			display->dispsw = &fbcon_mfb;
+		case 1:
+			// display->dispsw = &fbcon_mfb;
 			break;
 #endif
 #ifdef FBCON_HAS_CFB8
-		    case 8:
-			display->dispsw = &fbcon_cfb8;
+		case 8:
+			// display->dispsw = &fbcon_cfb8;
 			break;
 #endif
 #ifdef FBCON_HAS_CFB16
-		    case 16:
-			display->dispsw = &fbcon_cfb16;
-			display->dispsw_data = fbcon_cfb16_cmap;
+		case 16:
+			// display->dispsw = &fbcon_cfb16;
+			// display->dispsw_data = fbcon_cfb16_cmap;
 			break;
 #endif
 		}
@@ -2498,76 +2481,205 @@
 	}
 }
 
-static int
-atafb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
+static int atafb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+			   u_int transp, struct fb_info *info)
 {
-	int err,oldxres,oldyres,oldbpp,oldxres_virtual,
-	    oldyres_virtual,oldyoffset;
-	if ((err=do_fb_set_var(var, con==info->currcon)))
-		return err;
-	if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
-		oldxres=fb_display[con].var.xres;
-		oldyres=fb_display[con].var.yres;
-		oldxres_virtual=fb_display[con].var.xres_virtual;
-		oldyres_virtual=fb_display[con].var.yres_virtual;
-		oldbpp=fb_display[con].var.bits_per_pixel;
-		oldyoffset=fb_display[con].var.yoffset;
-		fb_display[con].var=*var;
-		if (oldxres != var->xres || oldyres != var->yres 
-		    || oldxres_virtual != var->xres_virtual
-		    || oldyres_virtual != var->yres_virtual
-		    || oldbpp != var->bits_per_pixel
-		    || oldyoffset != var->yoffset) {
-			atafb_set_disp(con, info);
-			(*fb_info.changevar)(con);
-			fb_alloc_cmap(&fb_display[con].cmap, 0, 0);
-			do_install_cmap(con, info);
-		}
-	}
-	var->activate=0;
-	return 0;
-}
+	red >>= 8;
+	green >>= 8;
+	blue >>= 8;
 
-
-
-static int
-atafb_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info)
-{
-	if (con == info->currcon) /* current console ? */
-		return fb_get_cmap(cmap, kspc, fbhw->getcolreg, info);
-	else
-		if (fb_display[con].cmap.len) /* non default colormap ? */
-			fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
-		else
-			fb_copy_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
-				     cmap, kspc ? 0 : 2);
-	return 0;
+	return info->fbops->fb_setcolreg(regno, red, green, blue, transp, info);
 }
 
 static int
-atafb_pan_display(struct fb_var_screeninfo *var, int con, struct fb_info *info)
+atafb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
 {
 	int xoffset = var->xoffset;
 	int yoffset = var->yoffset;
 	int err;
 
-	if (   xoffset < 0 || xoffset + fb_display[con].var.xres > fb_display[con].var.xres_virtual
-	    || yoffset < 0 || yoffset + fb_display[con].var.yres > fb_display[con].var.yres_virtual)
-		return -EINVAL;
-
-	if (con == info->currcon) {
-		if (fbhw->pan_display) {
-			if ((err = fbhw->pan_display(var, &current_par)))
-				return err;
-		}
-		else
+	if (var->vmode & FB_VMODE_YWRAP) {
+		if (yoffset < 0 || yoffset >= info->var.yres_virtual || xoffset)
+			return -EINVAL;
+	} else {
+		if (xoffset + info->var.xres > info->var.xres_virtual ||
+		    yoffset + info->var.yres > info->var.yres_virtual)
 			return -EINVAL;
 	}
-	fb_display[con].var.xoffset = var->xoffset;
-	fb_display[con].var.yoffset = var->yoffset;
+
+	if (fbhw->pan_display) {
+		err = fbhw->pan_display(var, info);
+		if (err)
+			return err;
+	} else
+		return -EINVAL;
+
+	info->var.xoffset = xoffset;
+	info->var.yoffset = yoffset;
+
+	if (var->vmode & FB_VMODE_YWRAP)
+		info->var.vmode |= FB_VMODE_YWRAP;
+	else
+		info->var.vmode &= ~FB_VMODE_YWRAP;
+
 	return 0;
 }
 
+/*
+ * generic drawing routines; imageblit needs updating for image depth > 1
+ */
+
+#if BITS_PER_LONG == 32
+#define BYTES_PER_LONG	4
+#define SHIFT_PER_LONG	5
+#elif BITS_PER_LONG == 64
+#define BYTES_PER_LONG	8
+#define SHIFT_PER_LONG	6
+#else
+#define Please update me
+#endif
+
+
+static void atafb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
+{
+	struct atafb_par *par = (struct atafb_par *)info->par;
+	int x2, y2;
+	u32 width, height;
+
+	if (!rect->width || !rect->height)
+		return;
+
+	/*
+	 * We could use hardware clipping but on many cards you get around
+	 * hardware clipping by writing to framebuffer directly.
+	 * */
+	x2 = rect->dx + rect->width;
+	y2 = rect->dy + rect->height;
+	x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
+	y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
+	width = x2 - rect->dx;
+	height = y2 - rect->dy;
+
+	if (info->var.bits_per_pixel == 1)
+		atafb_mfb_fillrect(info, par->next_line, rect->color,
+				   rect->dy, rect->dx, height, width);
+	else if (info->var.bits_per_pixel == 2)
+		atafb_iplan2p2_fillrect(info, par->next_line, rect->color,
+					rect->dy, rect->dx, height, width);
+	else if (info->var.bits_per_pixel == 4)
+		atafb_iplan2p4_fillrect(info, par->next_line, rect->color,
+					rect->dy, rect->dx, height, width);
+	else
+		atafb_iplan2p8_fillrect(info, par->next_line, rect->color,
+					rect->dy, rect->dx, height, width);
+
+	return;
+}
+
+static void atafb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
+{
+	struct atafb_par *par = (struct atafb_par *)info->par;
+	int x2, y2;
+	u32 dx, dy, sx, sy, width, height;
+	int rev_copy = 0;
+
+	/* clip the destination */
+	x2 = area->dx + area->width;
+	y2 = area->dy + area->height;
+	dx = area->dx > 0 ? area->dx : 0;
+	dy = area->dy > 0 ? area->dy : 0;
+	x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
+	y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
+	width = x2 - dx;
+	height = y2 - dy;
+
+	/* update sx,sy */
+	sx = area->sx + (dx - area->dx);
+	sy = area->sy + (dy - area->dy);
+
+	/* the source must be completely inside the virtual screen */
+	if (sx < 0 || sy < 0 || (sx + width) > info->var.xres_virtual ||
+	    (sy + height) > info->var.yres_virtual)
+		return;
+
+	if (dy > sy || (dy == sy && dx > sx)) {
+		dy += height;
+		sy += height;
+		rev_copy = 1;
+	}
+
+	if (info->var.bits_per_pixel == 1)
+		atafb_mfb_copyarea(info, par->next_line, sy, sx, dy, dx, height, width);
+	else if (info->var.bits_per_pixel == 2)
+		atafb_iplan2p2_copyarea(info, par->next_line, sy, sx, dy, dx, height, width);
+	else if (info->var.bits_per_pixel == 4)
+		atafb_iplan2p4_copyarea(info, par->next_line, sy, sx, dy, dx, height, width);
+	else
+		atafb_iplan2p8_copyarea(info, par->next_line, sy, sx, dy, dx, height, width);
+
+	return;
+}
+
+static void atafb_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+	struct atafb_par *par = (struct atafb_par *)info->par;
+	int x2, y2;
+	unsigned long *dst;
+	int dst_idx;
+	const char *src;
+	u32 dx, dy, width, height, pitch;
+
+	/*
+	 * We could use hardware clipping but on many cards you get around
+	 * hardware clipping by writing to framebuffer directly like we are
+	 * doing here.
+	 */
+	x2 = image->dx + image->width;
+	y2 = image->dy + image->height;
+	dx = image->dx;
+	dy = image->dy;
+	x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
+	y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
+	width = x2 - dx;
+	height = y2 - dy;
+
+	if (image->depth == 1) {
+		// used for font data
+		dst = (unsigned long *)
+			((unsigned long)info->screen_base & ~(BYTES_PER_LONG - 1));
+		dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG - 1)) * 8;
+		dst_idx += dy * par->next_line * 8 + dx;
+		src = image->data;
+		pitch = (image->width + 7) / 8;
+		while (height--) {
+
+			if (info->var.bits_per_pixel == 1)
+				atafb_mfb_linefill(info, par->next_line,
+						   dy, dx, width, src,
+						   image->bg_color, image->fg_color);
+			else if (info->var.bits_per_pixel == 2)
+				atafb_iplan2p2_linefill(info, par->next_line,
+							dy, dx, width, src,
+							image->bg_color, image->fg_color);
+			else if (info->var.bits_per_pixel == 4)
+				atafb_iplan2p4_linefill(info, par->next_line,
+							dy, dx, width, src,
+							image->bg_color, image->fg_color);
+			else
+				atafb_iplan2p8_linefill(info, par->next_line,
+							dy, dx, width, src,
+							image->bg_color, image->fg_color);
+			dy++;
+			src += pitch;
+		}
+	} else {
+		// only used for logo; broken
+		c2p(info->screen_base, image->data, dx, dy, width, height,
+		    par->next_line, par->next_plane, image->width,
+		    info->var.bits_per_pixel);
+	}
+}
+
 static int
 atafb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
 {
@@ -2584,7 +2696,7 @@
 		if (copy_from_user((void *)&current_par, (void *)arg,
 				   sizeof(struct atafb_par)))
 			return -EFAULT;
-		atafb_set_par(&current_par);
+		ata_set_par(&current_par);
 		return 0;
 #endif
 	}
@@ -2598,42 +2710,82 @@
  * 3 = suspend hsync
  * 4 = off
  */
-static int 
-atafb_blank(int blank, struct fb_info *info)
+static int atafb_blank(int blank, struct fb_info *info)
 {
 	unsigned short black[16];
 	struct fb_cmap cmap;
 	if (fbhw->blank && !fbhw->blank(blank))
 		return 1;
 	if (blank) {
-		memset(black, 0, 16*sizeof(unsigned short));
-		cmap.red=black;
-		cmap.green=black;
-		cmap.blue=black;
-		cmap.transp=NULL;
-		cmap.start=0;
-		cmap.len=16;
-		fb_set_cmap(&cmap, 1, info);
+		memset(black, 0, 16 * sizeof(unsigned short));
+		cmap.red = black;
+		cmap.green = black;
+		cmap.blue = black;
+		cmap.transp = NULL;
+		cmap.start = 0;
+		cmap.len = 16;
+		fb_set_cmap(&cmap, info);
 	}
+#if 0
 	else
-		do_install_cmap(info->currcon, info);
+		do_install_cmap(info);
+#endif
 	return 0;
 }
 
+	/*
+	 * New fbcon interface ...
+	 */
+
+	 /* check var by decoding var into hw par, rounding if necessary,
+	  * then encoding hw par back into new, validated var */
+static int atafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	int err;
+	struct atafb_par par;
+
+	/* Validate wanted screen parameters */
+	// if ((err = ata_decode_var(var, &par)))
+	err = fbhw->decode_var(var, &par);
+	if (err)
+		return err;
+
+	/* Encode (possibly rounded) screen parameters */
+	fbhw->encode_var(var, &par);
+	return 0;
+}
+
+	/* actually set hw par by decoding var, then setting hardware from
+	 * hw par just decoded */
+static int atafb_set_par(struct fb_info *info)
+{
+	struct atafb_par *par = (struct atafb_par *)info->par;
+
+	/* Decode wanted screen parameters */
+	fbhw->decode_var(&info->var, par);
+	fbhw->encode_fix(&info->fix, par);
+
+	/* Set new videomode */
+	ata_set_par(par);
+
+	return 0;
+}
+
+
 static struct fb_ops atafb_ops = {
 	.owner =	THIS_MODULE,
-	.fb_get_fix =	atafb_get_fix,
-	.fb_get_var =	atafb_get_var,
-	.fb_set_var =	atafb_set_var,
-	.fb_get_cmap =	atafb_get_cmap,
-	.fb_set_cmap =	gen_set_cmap,
-	.fb_pan_display =atafb_pan_display,
+	.fb_check_var	= atafb_check_var,
+	.fb_set_par	= atafb_set_par,
+	.fb_setcolreg	= atafb_setcolreg,
 	.fb_blank =	atafb_blank,
+	.fb_pan_display	= atafb_pan_display,
+	.fb_fillrect	= atafb_fillrect,
+	.fb_copyarea	= atafb_copyarea,
+	.fb_imageblit	= atafb_imageblit,
 	.fb_ioctl =	atafb_ioctl,
 };
 
-static void
-check_default_par( int detected_mode )
+static void check_default_par(int detected_mode)
 {
 	char default_name[10];
 	int i;
@@ -2642,199 +2794,41 @@
 
 	/* First try the user supplied mode */
 	if (default_par) {
-		var=atafb_predefined[default_par-1];
+		var = atafb_predefined[default_par - 1];
 		var.activate = FB_ACTIVATE_TEST;
-		if (do_fb_set_var(&var,1))
-			default_par=0;		/* failed */
+		if (do_fb_set_var(&var, 1))
+			default_par = 0;	/* failed */
 	}
 	/* Next is the autodetected one */
-	if (! default_par) {
-		var=atafb_predefined[detected_mode-1]; /* autodetect */
+	if (!default_par) {
+		var = atafb_predefined[detected_mode - 1]; /* autodetect */
 		var.activate = FB_ACTIVATE_TEST;
-		if (!do_fb_set_var(&var,1))
-			default_par=detected_mode;
+		if (!do_fb_set_var(&var, 1))
+			default_par = detected_mode;
 	}
 	/* If that also failed, try some default modes... */
-	if (! default_par) {
+	if (!default_par) {
 		/* try default1, default2... */
-		for (i=1 ; i < 10 ; i++) {
-			sprintf(default_name,"default%d",i);
-			default_par=get_video_mode(default_name);
-			if (! default_par)
+		for (i = 1; i < 10; i++) {
+			sprintf(default_name,"default%d", i);
+			default_par = get_video_mode(default_name);
+			if (!default_par)
 				panic("can't set default video mode");
-			var=atafb_predefined[default_par-1];
+			var = atafb_predefined[default_par - 1];
 			var.activate = FB_ACTIVATE_TEST;
-			if (! do_fb_set_var(&var,1))
+			if (!do_fb_set_var(&var,1))
 				break;	/* ok */
 		}
 	}
-	min_mem=var.xres_virtual * var.yres_virtual * var.bits_per_pixel/8;
+	min_mem = var.xres_virtual * var.yres_virtual * var.bits_per_pixel / 8;
 	if (default_mem_req < min_mem)
-		default_mem_req=min_mem;
+		default_mem_req = min_mem;
 }
 
-static int
-atafb_switch(int con, struct fb_info *info)
-{
-	/* Do we have to save the colormap ? */
-	if (fb_display[info->currcon].cmap.len)
-		fb_get_cmap(&fb_display[info->currcon].cmap, 1, fbhw->getcolreg,
-			    info);
-	do_fb_set_var(&fb_display[con].var,1);
-	info->currcon=con;
-	/* Install new colormap */
-	do_install_cmap(con, info);
-	return 0;
-}
-
-int __init atafb_init(void)
-{
-	int pad;
-	int detected_mode;
-	unsigned long mem_req;
-
-	if (!MACH_IS_ATARI)
-	        return -ENXIO;
-
-	do {
-#ifdef ATAFB_EXT
-		if (external_addr) {
-			fbhw = &ext_switch;
-			atafb_ops.fb_setcolreg = &ext_setcolreg;
-			break;
-		}
-#endif
-#ifdef ATAFB_TT
-		if (ATARIHW_PRESENT(TT_SHIFTER)) {
-			fbhw = &tt_switch;
-			atafb_ops.fb_setcolreg = &tt_setcolreg;
-			break;
-		}
-#endif
-#ifdef ATAFB_FALCON
-		if (ATARIHW_PRESENT(VIDEL_SHIFTER)) {
-			fbhw = &falcon_switch;
-			atafb_ops.fb_setcolreg = &falcon_setcolreg;
-			request_irq(IRQ_AUTO_4, falcon_vbl_switcher, IRQ_TYPE_PRIO,
-			            "framebuffer/modeswitch", falcon_vbl_switcher);
-			break;
-		}
-#endif
-#ifdef ATAFB_STE
-		if (ATARIHW_PRESENT(STND_SHIFTER) ||
-		    ATARIHW_PRESENT(EXTD_SHIFTER)) {
-			fbhw = &st_switch;
-			atafb_ops.fb_setcolreg = &stste_setcolreg;
-			break;
-		}
-		fbhw = &st_switch;
-		atafb_ops.fb_setcolreg = &stste_setcolreg;
-		printk("Cannot determine video hardware; defaulting to ST(e)\n");
-#else /* ATAFB_STE */
-		/* no default driver included */
-		/* Nobody will ever see this message :-) */
-		panic("Cannot initialize video hardware");
-#endif
-	} while (0);
-
-	/* Multisync monitor capabilities */
-	/* Atari-TOS defaults if no boot option present */
-	if (fb_info.monspecs.hfmin == 0) {
-	    fb_info.monspecs.hfmin = 31000;
-	    fb_info.monspecs.hfmax = 32000;
-	    fb_info.monspecs.vfmin = 58;
-	    fb_info.monspecs.vfmax = 62;
-	}
-
-	detected_mode = fbhw->detect();
-	check_default_par(detected_mode);
-#ifdef ATAFB_EXT
-	if (!external_addr) {
-#endif /* ATAFB_EXT */
-		mem_req = default_mem_req + ovsc_offset + ovsc_addlen;
-		mem_req = PAGE_ALIGN(mem_req) + PAGE_SIZE;
-		screen_base = atari_stram_alloc(mem_req, "atafb");
-		if (!screen_base)
-			panic("Cannot allocate screen memory");
-		memset(screen_base, 0, mem_req);
-		pad = -(unsigned long)screen_base & (PAGE_SIZE-1);
-		screen_base+=pad;
-		real_screen_base=screen_base+ovsc_offset;
-		screen_len = (mem_req - pad - ovsc_offset) & PAGE_MASK;
-		st_ovsc_switch();
-		if (CPU_IS_040_OR_060) {
-			/* On a '040+, the cache mode of video RAM must be set to
-			 * write-through also for internal video hardware! */
-			cache_push(virt_to_phys(screen_base), screen_len);
-			kernel_set_cachemode(screen_base, screen_len,
-					     IOMAP_WRITETHROUGH);
-		}
-#ifdef ATAFB_EXT
-	}
-	else {
-		/* Map the video memory (physical address given) to somewhere
-		 * in the kernel address space.
-		 */
-		external_addr =
-		  ioremap_writethrough((unsigned long)external_addr,
-				       external_len);
-		if (external_vgaiobase)
-			external_vgaiobase =
-			  (unsigned long)ioremap(external_vgaiobase, 0x10000);
-		screen_base      =
-		real_screen_base = external_addr;
-		screen_len       = external_len & PAGE_MASK;
-		memset (screen_base, 0, external_len);
-	}
-#endif /* ATAFB_EXT */
-
-	strcpy(fb_info.modename, "Atari Builtin ");
-	fb_info.changevar = NULL;
-	fb_info.fbops = &atafb_ops;
-	fb_info.disp = &disp;
-	fb_info.currcon = -1;
-	fb_info.switch_con = &atafb_switch;
-	fb_info.updatevar = &fb_update_var;
-	fb_info.flags = FBINFO_FLAG_DEFAULT;
-	do_fb_set_var(&atafb_predefined[default_par-1], 1);
-	strcat(fb_info.modename, fb_var_names[default_par-1][0]);
-
-	atafb_get_var(&disp.var, -1, &fb_info);
-	atafb_set_disp(-1, &fb_info);
-	do_install_cmap(0, &fb_info);
-
-	if (register_framebuffer(&fb_info) < 0) {
-#ifdef ATAFB_EXT
-		if (external_addr) {
-			iounmap(external_addr);
-			external_addr = NULL;
-		}
-		if (external_vgaiobase) {
-			iounmap((void*)external_vgaiobase);
-			external_vgaiobase = 0;
-		}
-#endif
-		return -EINVAL;
-	}
-
-	printk("Determined %dx%d, depth %d\n",
-	       disp.var.xres, disp.var.yres, disp.var.bits_per_pixel);
-	if ((disp.var.xres != disp.var.xres_virtual) ||
-	    (disp.var.yres != disp.var.yres_virtual))
-	   printk("   virtual %dx%d\n",
-			  disp.var.xres_virtual, disp.var.yres_virtual);
-	printk("fb%d: %s frame buffer device, using %dK of video memory\n",
-	       fb_info.node, fb_info.modename, screen_len>>10);
-
-	/* TODO: This driver cannot be unloaded yet */
-	return 0;
-}
-
-
 #ifdef ATAFB_EXT
 static void __init atafb_setup_ext(char *spec)
 {
-	int		xres, xres_virtual, yres, depth, planes;
+	int xres, xres_virtual, yres, depth, planes;
 	unsigned long addr, len;
 	char *p;
 
@@ -2848,27 +2842,31 @@
 	 *
 	 * Even xres_virtual is available, we neither support panning nor hw-scrolling!
 	 */
-	if (!(p = strsep(&spec, ";")) || !*p)
-	    return;
+	p = strsep(&spec, ";");
+	if (!p || !*p)
+		return;
 	xres_virtual = xres = simple_strtoul(p, NULL, 10);
 	if (xres <= 0)
-	    return;
+		return;
 
-	if (!(p = strsep(&spec, ";")) || !*p)
-	    return;
+	p = strsep(&spec, ";");
+	if (!p || !*p)
+		return;
 	yres = simple_strtoul(p, NULL, 10);
 	if (yres <= 0)
-	    return;
+		return;
 
-	if (!(p = strsep(&spec, ";")) || !*p)
-	    return;
+	p = strsep(&spec, ";");
+	if (!p || !*p)
+		return;
 	depth = simple_strtoul(p, NULL, 10);
 	if (depth != 1 && depth != 2 && depth != 4 && depth != 8 &&
-		depth != 16 && depth != 24)
-	    return;
+	    depth != 16 && depth != 24)
+		return;
 
-	if (!(p = strsep(&spec, ";")) || !*p)
-	    return;
+	p = strsep(&spec, ";");
+	if (!p || !*p)
+		return;
 	if (*p == 'i')
 		planes = FB_TYPE_INTERLEAVED_PLANES;
 	else if (*p == 'p')
@@ -2876,25 +2874,27 @@
 	else if (*p == 'n')
 		planes = FB_TYPE_PLANES;
 	else if (*p == 't')
-		planes = -1; /* true color */
+		planes = -1;		/* true color */
 	else
 		return;
 
-
-	if (!(p = strsep(&spec, ";")) || !*p)
+	p = strsep(&spec, ";");
+	if (!p || !*p)
 		return;
 	addr = simple_strtoul(p, NULL, 0);
 
-	if (!(p = strsep(&spec, ";")) || !*p)
-		len = xres*yres*depth/8;
+	p = strsep(&spec, ";");
+	if (!p || !*p)
+		len = xres * yres * depth / 8;
 	else
 		len = simple_strtoul(p, NULL, 0);
 
-	if ((p = strsep(&spec, ";")) && *p) {
-		external_vgaiobase=simple_strtoul(p, NULL, 0);
-	}
+	p = strsep(&spec, ";");
+	if (p && *p)
+		external_vgaiobase = simple_strtoul(p, NULL, 0);
 
-	if ((p = strsep(&spec, ";")) && *p) {
+	p = strsep(&spec, ";");
+	if (p && *p) {
 		external_bitspercol = simple_strtoul(p, NULL, 0);
 		if (external_bitspercol > 8)
 			external_bitspercol = 8;
@@ -2902,59 +2902,61 @@
 			external_bitspercol = 1;
 	}
 
-	if ((p = strsep(&spec, ";")) && *p) {
+	p = strsep(&spec, ";");
+	if (p && *p) {
 		if (!strcmp(p, "vga"))
 			external_card_type = IS_VGA;
 		if (!strcmp(p, "mv300"))
 			external_card_type = IS_MV300;
 	}
 
-	if ((p = strsep(&spec, ";")) && *p) {
+	p = strsep(&spec, ";");
+	if (p && *p) {
 		xres_virtual = simple_strtoul(p, NULL, 10);
 		if (xres_virtual < xres)
 			xres_virtual = xres;
-		if (xres_virtual*yres*depth/8 > len)
-			len=xres_virtual*yres*depth/8;
+		if (xres_virtual * yres * depth / 8 > len)
+			len = xres_virtual * yres * depth / 8;
 	}
 
-	external_xres  = xres;
-	external_xres_virtual  = xres_virtual;
-	external_yres  = yres;
+	external_xres = xres;
+	external_xres_virtual = xres_virtual;
+	external_yres = yres;
 	external_depth = depth;
 	external_pmode = planes;
-	external_addr  = (void *)addr;
-	external_len   = len;
+	external_addr = (void *)addr;
+	external_len = len;
 
-	if (external_card_type == IS_MV300)
-	  switch (external_depth) {
-	    case 1:
-	      MV300_reg = MV300_reg_1bit;
-	      break;
-	    case 4:
-	      MV300_reg = MV300_reg_4bit;
-	      break;
-	    case 8:
-	      MV300_reg = MV300_reg_8bit;
-	      break;
-	    }
+	if (external_card_type == IS_MV300) {
+		switch (external_depth) {
+		case 1:
+			MV300_reg = MV300_reg_1bit;
+			break;
+		case 4:
+			MV300_reg = MV300_reg_4bit;
+			break;
+		case 8:
+			MV300_reg = MV300_reg_8bit;
+			break;
+		}
+	}
 }
 #endif /* ATAFB_EXT */
 
-
 static void __init atafb_setup_int(char *spec)
 {
 	/* Format to config extended internal video hardware like OverScan:
-	"internal:<xres>;<yres>;<xres_max>;<yres_max>;<offset>"
-	Explanation:
-	<xres>: x-resolution 
-	<yres>: y-resolution
-	The following are only needed if you have an overscan which
-	needs a black border:
-	<xres_max>: max. length of a line in pixels your OverScan hardware would allow
-	<yres_max>: max. number of lines your OverScan hardware would allow
-	<offset>: Offset from physical beginning to visible beginning
-		  of screen in bytes
-	*/
+	 * "internal:<xres>;<yres>;<xres_max>;<yres_max>;<offset>"
+	 * Explanation:
+	 * <xres>: x-resolution
+	 * <yres>: y-resolution
+	 * The following are only needed if you have an overscan which
+	 * needs a black border:
+	 * <xres_max>: max. length of a line in pixels your OverScan hardware would allow
+	 * <yres_max>: max. number of lines your OverScan hardware would allow
+	 * <offset>: Offset from physical beginning to visible beginning
+	 *	  of screen in bytes
+	 */
 	int xres;
 	char *p;
 
@@ -2963,23 +2965,19 @@
 	xres = simple_strtoul(p, NULL, 10);
 	if (!(p = strsep(&spec, ";")) || !*p)
 		return;
-	sttt_xres=xres;
-	tt_yres=st_yres=simple_strtoul(p, NULL, 10);
-	if ((p=strsep(&spec, ";")) && *p) {
-		sttt_xres_virtual=simple_strtoul(p, NULL, 10);
-	}
-	if ((p=strsep(&spec, ";")) && *p) {
-		sttt_yres_virtual=simple_strtoul(p, NULL, 0);
-	}
-	if ((p=strsep(&spec, ";")) && *p) {
-		ovsc_offset=simple_strtoul(p, NULL, 0);
-	}
+	sttt_xres = xres;
+	tt_yres = st_yres = simple_strtoul(p, NULL, 10);
+	if ((p = strsep(&spec, ";")) && *p)
+		sttt_xres_virtual = simple_strtoul(p, NULL, 10);
+	if ((p = strsep(&spec, ";")) && *p)
+		sttt_yres_virtual = simple_strtoul(p, NULL, 0);
+	if ((p = strsep(&spec, ";")) && *p)
+		ovsc_offset = simple_strtoul(p, NULL, 0);
 
 	if (ovsc_offset || (sttt_yres_virtual != st_yres))
-		use_hwscroll=0;
+		use_hwscroll = 0;
 }
 
-
 #ifdef ATAFB_FALCON
 static void __init atafb_setup_mcap(char *spec)
 {
@@ -3018,7 +3016,6 @@
 }
 #endif /* ATAFB_FALCON */
 
-
 static void __init atafb_setup_user(char *spec)
 {
 	/* Format of user defined video mode is: <xres>;<yres>;<depth>
@@ -3026,81 +3023,257 @@
 	char *p;
 	int xres, yres, depth, temp;
 
-	if (!(p = strsep(&spec, ";")) || !*p)
+	p = strsep(&spec, ";");
+	if (!p || !*p)
 		return;
 	xres = simple_strtoul(p, NULL, 10);
-	if (!(p = strsep(&spec, ";")) || !*p)
+	p = strsep(&spec, ";");
+	if (!p || !*p)
 		return;
 	yres = simple_strtoul(p, NULL, 10);
-	if (!(p = strsep(&spec, "")) || !*p)
+	p = strsep(&spec, "");
+	if (!p || !*p)
 		return;
 	depth = simple_strtoul(p, NULL, 10);
-	if ((temp=get_video_mode("user0"))) {
-		default_par=temp;
-		atafb_predefined[default_par-1].xres = xres;
-		atafb_predefined[default_par-1].yres = yres;
-		atafb_predefined[default_par-1].bits_per_pixel = depth;
+	temp = get_video_mode("user0");
+	if (temp) {
+		default_par = temp;
+		atafb_predefined[default_par - 1].xres = xres;
+		atafb_predefined[default_par - 1].yres = yres;
+		atafb_predefined[default_par - 1].bits_per_pixel = depth;
 	}
 }
 
-int __init atafb_setup( char *options )
+int __init atafb_setup(char *options)
 {
-    char *this_opt;
-    int temp;
+	char *this_opt;
+	int temp;
 
-    fb_info.fontname[0] = '\0';
-
-    if (!options || !*options)
+	if (!options || !*options)
 		return 0;
-    
-    while ((this_opt = strsep(&options, ",")) != NULL) {	 
-	if (!*this_opt) continue;
-	if ((temp=get_video_mode(this_opt)))
-		default_par=temp;
-	else if (! strcmp(this_opt, "inverse"))
-		inverse=1;
-	else if (!strncmp(this_opt, "font:", 5))
-	   strcpy(fb_info.fontname, this_opt+5);
-	else if (! strncmp(this_opt, "hwscroll_",9)) {
-		hwscroll=simple_strtoul(this_opt+9, NULL, 10);
-		if (hwscroll < 0)
-			hwscroll = 0;
-		if (hwscroll > 200)
-			hwscroll = 200;
-	}
+
+	while ((this_opt = strsep(&options, ",")) != NULL) {
+		if (!*this_opt)
+			continue;
+		if ((temp = get_video_mode(this_opt))) {
+			default_par = temp;
+			mode_option = this_opt;
+		} else if (!strcmp(this_opt, "inverse"))
+			inverse = 1;
+		else if (!strncmp(this_opt, "hwscroll_", 9)) {
+			hwscroll = simple_strtoul(this_opt + 9, NULL, 10);
+			if (hwscroll < 0)
+				hwscroll = 0;
+			if (hwscroll > 200)
+				hwscroll = 200;
+		}
 #ifdef ATAFB_EXT
-	else if (!strcmp(this_opt,"mv300")) {
-		external_bitspercol = 8;
-		external_card_type = IS_MV300;
-	}
-	else if (!strncmp(this_opt,"external:",9))
-		atafb_setup_ext(this_opt+9);
+		else if (!strcmp(this_opt, "mv300")) {
+			external_bitspercol = 8;
+			external_card_type = IS_MV300;
+		} else if (!strncmp(this_opt, "external:", 9))
+			atafb_setup_ext(this_opt + 9);
 #endif
-	else if (!strncmp(this_opt,"internal:",9))
-		atafb_setup_int(this_opt+9);
+		else if (!strncmp(this_opt, "internal:", 9))
+			atafb_setup_int(this_opt + 9);
 #ifdef ATAFB_FALCON
-	else if (!strncmp(this_opt, "eclock:", 7)) {
-		fext.f = simple_strtoul(this_opt+7, NULL, 10);
-		/* external pixelclock in kHz --> ps */
-		fext.t = 1000000000/fext.f;
-		fext.f *= 1000;
-	}
-	else if (!strncmp(this_opt, "monitorcap:", 11))
-		atafb_setup_mcap(this_opt+11);
+		else if (!strncmp(this_opt, "eclock:", 7)) {
+			fext.f = simple_strtoul(this_opt + 7, NULL, 10);
+			/* external pixelclock in kHz --> ps */
+			fext.t = 1000000000 / fext.f;
+			fext.f *= 1000;
+		} else if (!strncmp(this_opt, "monitorcap:", 11))
+			atafb_setup_mcap(this_opt + 11);
 #endif
-	else if (!strcmp(this_opt, "keep"))
-		DontCalcRes = 1;
-	else if (!strncmp(this_opt, "R", 1))
-		atafb_setup_user(this_opt+1);
-    }
-    return 0;
+		else if (!strcmp(this_opt, "keep"))
+			DontCalcRes = 1;
+		else if (!strncmp(this_opt, "R", 1))
+			atafb_setup_user(this_opt + 1);
+	}
+	return 0;
 }
 
+int __init atafb_init(void)
+{
+	int pad;
+	int detected_mode;
+	unsigned int defmode = 0;
+	unsigned long mem_req;
+
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("atafb", &option))
+		return -ENODEV;
+	atafb_setup(option);
+#endif
+	printk("atafb_init: start\n");
+
+	if (!MACH_IS_ATARI)
+		return -ENXIO;
+
+	do {
+#ifdef ATAFB_EXT
+		if (external_addr) {
+			printk("atafb_init: initializing external hw\n");
+			fbhw = &ext_switch;
+			atafb_ops.fb_setcolreg = &ext_setcolreg;
+			defmode = DEFMODE_EXT;
+			break;
+		}
+#endif
+#ifdef ATAFB_TT
+		if (ATARIHW_PRESENT(TT_SHIFTER)) {
+			printk("atafb_init: initializing TT hw\n");
+			fbhw = &tt_switch;
+			atafb_ops.fb_setcolreg = &tt_setcolreg;
+			defmode = DEFMODE_TT;
+			break;
+		}
+#endif
+#ifdef ATAFB_FALCON
+		if (ATARIHW_PRESENT(VIDEL_SHIFTER)) {
+			printk("atafb_init: initializing Falcon hw\n");
+			fbhw = &falcon_switch;
+			atafb_ops.fb_setcolreg = &falcon_setcolreg;
+			request_irq(IRQ_AUTO_4, falcon_vbl_switcher, IRQ_TYPE_PRIO,
+			            "framebuffer/modeswitch", falcon_vbl_switcher);
+			defmode = DEFMODE_F30;
+			break;
+		}
+#endif
+#ifdef ATAFB_STE
+		if (ATARIHW_PRESENT(STND_SHIFTER) ||
+		    ATARIHW_PRESENT(EXTD_SHIFTER)) {
+			printk("atafb_init: initializing ST/E hw\n");
+			fbhw = &st_switch;
+			atafb_ops.fb_setcolreg = &stste_setcolreg;
+			defmode = DEFMODE_STE;
+			break;
+		}
+		fbhw = &st_switch;
+		atafb_ops.fb_setcolreg = &stste_setcolreg;
+		printk("Cannot determine video hardware; defaulting to ST(e)\n");
+#else /* ATAFB_STE */
+		/* no default driver included */
+		/* Nobody will ever see this message :-) */
+		panic("Cannot initialize video hardware");
+#endif
+	} while (0);
+
+	/* Multisync monitor capabilities */
+	/* Atari-TOS defaults if no boot option present */
+	if (fb_info.monspecs.hfmin == 0) {
+		fb_info.monspecs.hfmin = 31000;
+		fb_info.monspecs.hfmax = 32000;
+		fb_info.monspecs.vfmin = 58;
+		fb_info.monspecs.vfmax = 62;
+	}
+
+	detected_mode = fbhw->detect();
+	check_default_par(detected_mode);
+#ifdef ATAFB_EXT
+	if (!external_addr) {
+#endif /* ATAFB_EXT */
+		mem_req = default_mem_req + ovsc_offset + ovsc_addlen;
+		mem_req = PAGE_ALIGN(mem_req) + PAGE_SIZE;
+		screen_base = atari_stram_alloc(mem_req, "atafb");
+		if (!screen_base)
+			panic("Cannot allocate screen memory");
+		memset(screen_base, 0, mem_req);
+		pad = -(unsigned long)screen_base & (PAGE_SIZE - 1);
+		screen_base += pad;
+		real_screen_base = screen_base + ovsc_offset;
+		screen_len = (mem_req - pad - ovsc_offset) & PAGE_MASK;
+		st_ovsc_switch();
+		if (CPU_IS_040_OR_060) {
+			/* On a '040+, the cache mode of video RAM must be set to
+			 * write-through also for internal video hardware! */
+			cache_push(virt_to_phys(screen_base), screen_len);
+			kernel_set_cachemode(screen_base, screen_len,
+					     IOMAP_WRITETHROUGH);
+		}
+		printk("atafb: screen_base %p real_screen_base %p screen_len %d\n",
+			screen_base, real_screen_base, screen_len);
+#ifdef ATAFB_EXT
+	} else {
+		/* Map the video memory (physical address given) to somewhere
+		 * in the kernel address space.
+		 */
+		external_addr = ioremap_writethrough((unsigned long)external_addr,
+						     external_len);
+		if (external_vgaiobase)
+			external_vgaiobase =
+			  (unsigned long)ioremap(external_vgaiobase, 0x10000);
+		screen_base =
+		real_screen_base = external_addr;
+		screen_len = external_len & PAGE_MASK;
+		memset (screen_base, 0, external_len);
+	}
+#endif /* ATAFB_EXT */
+
+//	strcpy(fb_info.mode->name, "Atari Builtin ");
+	fb_info.fbops = &atafb_ops;
+	// try to set default (detected; requested) var
+	do_fb_set_var(&atafb_predefined[default_par - 1], 1);
+	// reads hw state into current par, which may not be sane yet
+	ata_get_par(&current_par);
+	fb_info.par = &current_par;
+	// tries to read from HW which may not be initialized yet
+	// so set sane var first, then call atafb_set_par
+	atafb_get_var(&fb_info.var, &fb_info);
+	fb_info.flags = FBINFO_FLAG_DEFAULT;
+
+	if (!fb_find_mode(&fb_info.var, &fb_info, mode_option, atafb_modedb,
+			  NUM_TOTAL_MODES, &atafb_modedb[defmode],
+			  fb_info.var.bits_per_pixel)) {
+		return -EINVAL;
+	}
+
+	atafb_set_disp(&fb_info);
+
+	fb_alloc_cmap(&(fb_info.cmap), 1 << fb_info.var.bits_per_pixel, 0);
+
+
+	printk("Determined %dx%d, depth %d\n",
+	       fb_info.var.xres, fb_info.var.yres, fb_info.var.bits_per_pixel);
+	if ((fb_info.var.xres != fb_info.var.xres_virtual) ||
+	    (fb_info.var.yres != fb_info.var.yres_virtual))
+		printk("   virtual %dx%d\n", fb_info.var.xres_virtual,
+		       fb_info.var.yres_virtual);
+
+	if (register_framebuffer(&fb_info) < 0) {
+#ifdef ATAFB_EXT
+		if (external_addr) {
+			iounmap(external_addr);
+			external_addr = NULL;
+		}
+		if (external_vgaiobase) {
+			iounmap((void*)external_vgaiobase);
+			external_vgaiobase = 0;
+		}
+#endif
+		return -EINVAL;
+	}
+
+	// FIXME: mode needs setting!
+	//printk("fb%d: %s frame buffer device, using %dK of video memory\n",
+	//       fb_info.node, fb_info.mode->name, screen_len>>10);
+	printk("fb%d: frame buffer device, using %dK of video memory\n",
+	       fb_info.node, screen_len >> 10);
+
+	/* TODO: This driver cannot be unloaded yet */
+	return 0;
+}
+
+module_init(atafb_init);
+
 #ifdef MODULE
 MODULE_LICENSE("GPL");
 
-int init_module(void)
+int cleanup_module(void)
 {
-	return atafb_init();
+	unregister_framebuffer(&fb_info);
+	return atafb_deinit();
 }
 #endif /* MODULE */
diff --git a/drivers/video/atafb.h b/drivers/video/atafb.h
new file mode 100644
index 0000000..014e059
--- /dev/null
+++ b/drivers/video/atafb.h
@@ -0,0 +1,36 @@
+#ifndef _VIDEO_ATAFB_H
+#define _VIDEO_ATAFB_H
+
+void atafb_mfb_copyarea(struct fb_info *info, u_long next_line, int sy, int sx, int dy,
+			int dx, int height, int width);
+void atafb_mfb_fillrect(struct fb_info *info, u_long next_line, u32 color,
+			int sy, int sx, int height, int width);
+void atafb_mfb_linefill(struct fb_info *info, u_long next_line,
+			int dy, int dx, u32 width,
+			const u8 *data, u32 bgcolor, u32 fgcolor);
+
+void atafb_iplan2p2_copyarea(struct fb_info *info, u_long next_line, int sy, int sx, int dy,
+			     int dx, int height, int width);
+void atafb_iplan2p2_fillrect(struct fb_info *info, u_long next_line, u32 color,
+			     int sy, int sx, int height, int width);
+void atafb_iplan2p2_linefill(struct fb_info *info, u_long next_line,
+			     int dy, int dx, u32 width,
+			     const u8 *data, u32 bgcolor, u32 fgcolor);
+
+void atafb_iplan2p4_copyarea(struct fb_info *info, u_long next_line, int sy, int sx, int dy,
+			     int dx, int height, int width);
+void atafb_iplan2p4_fillrect(struct fb_info *info, u_long next_line, u32 color,
+			     int sy, int sx, int height, int width);
+void atafb_iplan2p4_linefill(struct fb_info *info, u_long next_line,
+			     int dy, int dx, u32 width,
+			     const u8 *data, u32 bgcolor, u32 fgcolor);
+
+void atafb_iplan2p8_copyarea(struct fb_info *info, u_long next_line, int sy, int sx, int dy,
+			     int dx, int height, int width);
+void atafb_iplan2p8_fillrect(struct fb_info *info, u_long next_line, u32 color,
+			     int sy, int sx, int height, int width);
+void atafb_iplan2p8_linefill(struct fb_info *info, u_long next_line,
+			     int dy, int dx, u32 width,
+			     const u8 *data, u32 bgcolor, u32 fgcolor);
+
+#endif /* _VIDEO_ATAFB_H */
diff --git a/drivers/video/atafb_iplan2p2.c b/drivers/video/atafb_iplan2p2.c
new file mode 100644
index 0000000..8cc9c50
--- /dev/null
+++ b/drivers/video/atafb_iplan2p2.c
@@ -0,0 +1,293 @@
+/*
+ *  linux/drivers/video/iplan2p2.c -- Low level frame buffer operations for
+ *				      interleaved bitplanes à la Atari (2
+ *				      planes, 2 bytes interleave)
+ *
+ *	Created 5 Apr 1997 by Geert Uytterhoeven
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License.  See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/fb.h>
+
+#include <asm/setup.h>
+
+#include "atafb.h"
+
+#define BPL	2
+#include "atafb_utils.h"
+
+void atafb_iplan2p2_copyarea(struct fb_info *info, u_long next_line,
+			     int sy, int sx, int dy, int dx,
+			     int height, int width)
+{
+	/*  bmove() has to distinguish two major cases: If both, source and
+	 *  destination, start at even addresses or both are at odd
+	 *  addresses, just the first odd and last even column (if present)
+	 *  require special treatment (memmove_col()). The rest between
+	 *  then can be copied by normal operations, because all adjacent
+	 *  bytes are affected and are to be stored in the same order.
+	 *    The pathological case is when the move should go from an odd
+	 *  address to an even or vice versa. Since the bytes in the plane
+	 *  words must be assembled in new order, it seems wisest to make
+	 *  all movements by memmove_col().
+	 */
+
+	u8 *src, *dst;
+	u32 *s, *d;
+	int w, l , i, j;
+	u_int colsize;
+	u_int upwards = (dy < sy) || (dy == sy && dx < sx);
+
+	colsize = height;
+	if (!((sx ^ dx) & 15)) {
+		/* odd->odd or even->even */
+
+		if (upwards) {
+			src = (u8 *)info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL);
+			dst = (u8 *)info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL);
+			if (sx & 15) {
+				memmove32_col(dst, src, 0xff00ff, height, next_line - BPL * 2);
+				src += BPL * 2;
+				dst += BPL * 2;
+				width -= 8;
+			}
+			w = width >> 4;
+			if (w) {
+				s = (u32 *)src;
+				d = (u32 *)dst;
+				w *= BPL / 2;
+				l = next_line - w * 4;
+				for (j = height; j > 0; j--) {
+					for (i = w; i > 0; i--)
+						*d++ = *s++;
+					s = (u32 *)((u8 *)s + l);
+					d = (u32 *)((u8 *)d + l);
+				}
+			}
+			if (width & 15)
+				memmove32_col(dst + width / (8 / BPL), src + width / (8 / BPL),
+					      0xff00ff00, height, next_line - BPL * 2);
+		} else {
+			src = (u8 *)info->screen_base + (sy - 1) * next_line + ((sx + width + 8) & ~15) / (8 / BPL);
+			dst = (u8 *)info->screen_base + (dy - 1) * next_line + ((dx + width + 8) & ~15) / (8 / BPL);
+
+			if ((sx + width) & 15) {
+				src -= BPL * 2;
+				dst -= BPL * 2;
+				memmove32_col(dst, src, 0xff00ff00, colsize, -next_line - BPL * 2);
+				width -= 8;
+			}
+			w = width >> 4;
+			if (w) {
+				s = (u32 *)src;
+				d = (u32 *)dst;
+				w *= BPL / 2;
+				l = next_line - w * 4;
+				for (j = height; j > 0; j--) {
+					for (i = w; i > 0; i--)
+						*--d = *--s;
+					s = (u32 *)((u8 *)s - l);
+					d = (u32 *)((u8 *)d - l);
+				}
+			}
+			if (sx & 15)
+				memmove32_col(dst - (width - 16) / (8 / BPL),
+					      src - (width - 16) / (8 / BPL),
+					      0xff00ff, colsize, -next_line - BPL * 2);
+		}
+	} else {
+		/* odd->even or even->odd */
+		if (upwards) {
+			u32 *src32, *dst32;
+			u32 pval[4], v, v1, mask;
+			int i, j, w, f;
+
+			src = (u8 *)info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL);
+			dst = (u8 *)info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL);
+
+			mask = 0xff00ff00;
+			f = 0;
+			w = width;
+			if (sx & 15) {
+				f = 1;
+				w += 8;
+			}
+			if ((sx + width) & 15)
+				f |= 2;
+			w >>= 4;
+			for (i = height; i; i--) {
+				src32 = (u32 *)src;
+				dst32 = (u32 *)dst;
+
+				if (f & 1) {
+					pval[0] = (*src32++ << 8) & mask;
+				} else {
+					pval[0] = dst32[0] & mask;
+				}
+
+				for (j = w; j > 0; j--) {
+					v = *src32++;
+					v1 = v & mask;
+					*dst32++ = pval[0] | (v1 >> 8);
+					pval[0] = (v ^ v1) << 8;
+				}
+
+				if (f & 2) {
+					dst32[0] = (dst32[0] & mask) | pval[0];
+				}
+
+				src += next_line;
+				dst += next_line;
+			}
+		} else {
+			u32 *src32, *dst32;
+			u32 pval[4], v, v1, mask;
+			int i, j, w, f;
+
+			src = (u8 *)info->screen_base + (sy - 1) * next_line + ((sx + width + 8) & ~15) / (8 / BPL);
+			dst = (u8 *)info->screen_base + (dy - 1) * next_line + ((dx + width + 8) & ~15) / (8 / BPL);
+
+			mask = 0xff00ff;
+			f = 0;
+			w = width;
+			if ((dx + width) & 15)
+				f = 1;
+			if (sx & 15) {
+				f |= 2;
+				w += 8;
+			}
+			w >>= 4;
+			for (i = height; i; i--) {
+				src32 = (u32 *)src;
+				dst32 = (u32 *)dst;
+
+				if (f & 1) {
+					pval[0] = dst32[-1] & mask;
+				} else {
+					pval[0] = (*--src32 >> 8) & mask;
+				}
+
+				for (j = w; j > 0; j--) {
+					v = *--src32;
+					v1 = v & mask;
+					*--dst32 = pval[0] | (v1 << 8);
+					pval[0] = (v ^ v1) >> 8;
+				}
+
+				if (!(f & 2)) {
+					dst32[-1] = (dst32[-1] & mask) | pval[0];
+				}
+
+				src -= next_line;
+				dst -= next_line;
+			}
+		}
+	}
+}
+
+void atafb_iplan2p2_fillrect(struct fb_info *info, u_long next_line, u32 color,
+                             int sy, int sx, int height, int width)
+{
+	u32 *dest;
+	int rows, i;
+	u32 cval[4];
+
+	dest = (u32 *)(info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL));
+	if (sx & 15) {
+		u8 *dest8 = (u8 *)dest + 1;
+
+		expand8_col2mask(color, cval);
+
+		for (i = height; i; i--) {
+			fill8_col(dest8, cval);
+			dest8 += next_line;
+		}
+		dest += BPL / 2;
+		width -= 8;
+	}
+
+	expand16_col2mask(color, cval);
+	rows = width >> 4;
+	if (rows) {
+		u32 *d = dest;
+		u32 off = next_line - rows * BPL * 2;
+		for (i = height; i; i--) {
+			d = fill16_col(d, rows, cval);
+			d = (u32 *)((long)d + off);
+		}
+		dest += rows * BPL / 2;
+		width &= 15;
+	}
+
+	if (width) {
+		u8 *dest8 = (u8 *)dest;
+
+		expand8_col2mask(color, cval);
+
+		for (i = height; i; i--) {
+			fill8_col(dest8, cval);
+			dest8 += next_line;
+		}
+	}
+}
+
+void atafb_iplan2p2_linefill(struct fb_info *info, u_long next_line,
+                             int dy, int dx, u32 width,
+                             const u8 *data, u32 bgcolor, u32 fgcolor)
+{
+	u32 *dest;
+	const u16 *data16;
+	int rows;
+	u32 fgm[4], bgm[4], m;
+
+	dest = (u32 *)(info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL));
+	if (dx & 15) {
+		fill8_2col((u8 *)dest + 1, fgcolor, bgcolor, *data++);
+		dest += BPL / 2;
+		width -= 8;
+	}
+
+	if (width >= 16) {
+		data16 = (const u16 *)data;
+		expand16_2col2mask(fgcolor, bgcolor, fgm, bgm);
+
+		for (rows = width / 16; rows; rows--) {
+			u16 d = *data16++;
+			m = d | ((u32)d << 16);
+			*dest++ = (m & fgm[0]) ^ bgm[0];
+		}
+
+		data = (const u8 *)data16;
+		width &= 15;
+	}
+
+	if (width)
+		fill8_2col((u8 *)dest, fgcolor, bgcolor, *data);
+}
+
+#ifdef MODULE
+MODULE_LICENSE("GPL");
+
+int init_module(void)
+{
+	return 0;
+}
+
+void cleanup_module(void)
+{
+}
+#endif /* MODULE */
+
+
+    /*
+     *  Visible symbols for modules
+     */
+
+EXPORT_SYMBOL(atafb_iplan2p2_copyarea);
+EXPORT_SYMBOL(atafb_iplan2p2_fillrect);
+EXPORT_SYMBOL(atafb_iplan2p2_linefill);
diff --git a/drivers/video/atafb_iplan2p4.c b/drivers/video/atafb_iplan2p4.c
new file mode 100644
index 0000000..bee0d89
--- /dev/null
+++ b/drivers/video/atafb_iplan2p4.c
@@ -0,0 +1,308 @@
+/*
+ *  linux/drivers/video/iplan2p4.c -- Low level frame buffer operations for
+ *				      interleaved bitplanes à la Atari (4
+ *				      planes, 2 bytes interleave)
+ *
+ *	Created 5 Apr 1997 by Geert Uytterhoeven
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License.  See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/fb.h>
+
+#include <asm/setup.h>
+
+#include "atafb.h"
+
+#define BPL	4
+#include "atafb_utils.h"
+
+void atafb_iplan2p4_copyarea(struct fb_info *info, u_long next_line,
+			     int sy, int sx, int dy, int dx,
+			     int height, int width)
+{
+	/*  bmove() has to distinguish two major cases: If both, source and
+	 *  destination, start at even addresses or both are at odd
+	 *  addresses, just the first odd and last even column (if present)
+	 *  require special treatment (memmove_col()). The rest between
+	 *  then can be copied by normal operations, because all adjacent
+	 *  bytes are affected and are to be stored in the same order.
+	 *    The pathological case is when the move should go from an odd
+	 *  address to an even or vice versa. Since the bytes in the plane
+	 *  words must be assembled in new order, it seems wisest to make
+	 *  all movements by memmove_col().
+	 */
+
+	u8 *src, *dst;
+	u32 *s, *d;
+	int w, l , i, j;
+	u_int colsize;
+	u_int upwards = (dy < sy) || (dy == sy && dx < sx);
+
+	colsize = height;
+	if (!((sx ^ dx) & 15)) {
+		/* odd->odd or even->even */
+
+		if (upwards) {
+			src = (u8 *)info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL);
+			dst = (u8 *)info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL);
+			if (sx & 15) {
+				memmove32_col(dst, src, 0xff00ff, height, next_line - BPL * 2);
+				src += BPL * 2;
+				dst += BPL * 2;
+				width -= 8;
+			}
+			w = width >> 4;
+			if (w) {
+				s = (u32 *)src;
+				d = (u32 *)dst;
+				w *= BPL / 2;
+				l = next_line - w * 4;
+				for (j = height; j > 0; j--) {
+					for (i = w; i > 0; i--)
+						*d++ = *s++;
+					s = (u32 *)((u8 *)s + l);
+					d = (u32 *)((u8 *)d + l);
+				}
+			}
+			if (width & 15)
+				memmove32_col(dst + width / (8 / BPL), src + width / (8 / BPL),
+					      0xff00ff00, height, next_line - BPL * 2);
+		} else {
+			src = (u8 *)info->screen_base + (sy - 1) * next_line + ((sx + width + 8) & ~15) / (8 / BPL);
+			dst = (u8 *)info->screen_base + (dy - 1) * next_line + ((dx + width + 8) & ~15) / (8 / BPL);
+
+			if ((sx + width) & 15) {
+				src -= BPL * 2;
+				dst -= BPL * 2;
+				memmove32_col(dst, src, 0xff00ff00, colsize, -next_line - BPL * 2);
+				width -= 8;
+			}
+			w = width >> 4;
+			if (w) {
+				s = (u32 *)src;
+				d = (u32 *)dst;
+				w *= BPL / 2;
+				l = next_line - w * 4;
+				for (j = height; j > 0; j--) {
+					for (i = w; i > 0; i--)
+						*--d = *--s;
+					s = (u32 *)((u8 *)s - l);
+					d = (u32 *)((u8 *)d - l);
+				}
+			}
+			if (sx & 15)
+				memmove32_col(dst - (width - 16) / (8 / BPL),
+					      src - (width - 16) / (8 / BPL),
+					      0xff00ff, colsize, -next_line - BPL * 2);
+		}
+	} else {
+		/* odd->even or even->odd */
+		if (upwards) {
+			u32 *src32, *dst32;
+			u32 pval[4], v, v1, mask;
+			int i, j, w, f;
+
+			src = (u8 *)info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL);
+			dst = (u8 *)info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL);
+
+			mask = 0xff00ff00;
+			f = 0;
+			w = width;
+			if (sx & 15) {
+				f = 1;
+				w += 8;
+			}
+			if ((sx + width) & 15)
+				f |= 2;
+			w >>= 4;
+			for (i = height; i; i--) {
+				src32 = (u32 *)src;
+				dst32 = (u32 *)dst;
+
+				if (f & 1) {
+					pval[0] = (*src32++ << 8) & mask;
+					pval[1] = (*src32++ << 8) & mask;
+				} else {
+					pval[0] = dst32[0] & mask;
+					pval[1] = dst32[1] & mask;
+				}
+
+				for (j = w; j > 0; j--) {
+					v = *src32++;
+					v1 = v & mask;
+					*dst32++ = pval[0] | (v1 >> 8);
+					pval[0] = (v ^ v1) << 8;
+					v = *src32++;
+					v1 = v & mask;
+					*dst32++ = pval[1] | (v1 >> 8);
+					pval[1] = (v ^ v1) << 8;
+				}
+
+				if (f & 2) {
+					dst32[0] = (dst32[0] & mask) | pval[0];
+					dst32[1] = (dst32[1] & mask) | pval[1];
+				}
+
+				src += next_line;
+				dst += next_line;
+			}
+		} else {
+			u32 *src32, *dst32;
+			u32 pval[4], v, v1, mask;
+			int i, j, w, f;
+
+			src = (u8 *)info->screen_base + (sy - 1) * next_line + ((sx + width + 8) & ~15) / (8 / BPL);
+			dst = (u8 *)info->screen_base + (dy - 1) * next_line + ((dx + width + 8) & ~15) / (8 / BPL);
+
+			mask = 0xff00ff;
+			f = 0;
+			w = width;
+			if ((dx + width) & 15)
+				f = 1;
+			if (sx & 15) {
+				f |= 2;
+				w += 8;
+			}
+			w >>= 4;
+			for (i = height; i; i--) {
+				src32 = (u32 *)src;
+				dst32 = (u32 *)dst;
+
+				if (f & 1) {
+					pval[0] = dst32[-1] & mask;
+					pval[1] = dst32[-2] & mask;
+				} else {
+					pval[0] = (*--src32 >> 8) & mask;
+					pval[1] = (*--src32 >> 8) & mask;
+				}
+
+				for (j = w; j > 0; j--) {
+					v = *--src32;
+					v1 = v & mask;
+					*--dst32 = pval[0] | (v1 << 8);
+					pval[0] = (v ^ v1) >> 8;
+					v = *--src32;
+					v1 = v & mask;
+					*--dst32 = pval[1] | (v1 << 8);
+					pval[1] = (v ^ v1) >> 8;
+				}
+
+				if (!(f & 2)) {
+					dst32[-1] = (dst32[-1] & mask) | pval[0];
+					dst32[-2] = (dst32[-2] & mask) | pval[1];
+				}
+
+				src -= next_line;
+				dst -= next_line;
+			}
+		}
+	}
+}
+
+void atafb_iplan2p4_fillrect(struct fb_info *info, u_long next_line, u32 color,
+                             int sy, int sx, int height, int width)
+{
+	u32 *dest;
+	int rows, i;
+	u32 cval[4];
+
+	dest = (u32 *)(info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL));
+	if (sx & 15) {
+		u8 *dest8 = (u8 *)dest + 1;
+
+		expand8_col2mask(color, cval);
+
+		for (i = height; i; i--) {
+			fill8_col(dest8, cval);
+			dest8 += next_line;
+		}
+		dest += BPL / 2;
+		width -= 8;
+	}
+
+	expand16_col2mask(color, cval);
+	rows = width >> 4;
+	if (rows) {
+		u32 *d = dest;
+		u32 off = next_line - rows * BPL * 2;
+		for (i = height; i; i--) {
+			d = fill16_col(d, rows, cval);
+			d = (u32 *)((long)d + off);
+		}
+		dest += rows * BPL / 2;
+		width &= 15;
+	}
+
+	if (width) {
+		u8 *dest8 = (u8 *)dest;
+
+		expand8_col2mask(color, cval);
+
+		for (i = height; i; i--) {
+			fill8_col(dest8, cval);
+			dest8 += next_line;
+		}
+	}
+}
+
+void atafb_iplan2p4_linefill(struct fb_info *info, u_long next_line,
+                             int dy, int dx, u32 width,
+                             const u8 *data, u32 bgcolor, u32 fgcolor)
+{
+	u32 *dest;
+	const u16 *data16;
+	int rows;
+	u32 fgm[4], bgm[4], m;
+
+	dest = (u32 *)(info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL));
+	if (dx & 15) {
+		fill8_2col((u8 *)dest + 1, fgcolor, bgcolor, *data++);
+		dest += BPL / 2;
+		width -= 8;
+	}
+
+	if (width >= 16) {
+		data16 = (const u16 *)data;
+		expand16_2col2mask(fgcolor, bgcolor, fgm, bgm);
+
+		for (rows = width / 16; rows; rows--) {
+			u16 d = *data16++;
+			m = d | ((u32)d << 16);
+			*dest++ = (m & fgm[0]) ^ bgm[0];
+			*dest++ = (m & fgm[1]) ^ bgm[1];
+		}
+
+		data = (const u8 *)data16;
+		width &= 15;
+	}
+
+	if (width)
+		fill8_2col((u8 *)dest, fgcolor, bgcolor, *data);
+}
+
+#ifdef MODULE
+MODULE_LICENSE("GPL");
+
+int init_module(void)
+{
+	return 0;
+}
+
+void cleanup_module(void)
+{
+}
+#endif /* MODULE */
+
+
+    /*
+     *  Visible symbols for modules
+     */
+
+EXPORT_SYMBOL(atafb_iplan2p4_copyarea);
+EXPORT_SYMBOL(atafb_iplan2p4_fillrect);
+EXPORT_SYMBOL(atafb_iplan2p4_linefill);
diff --git a/drivers/video/atafb_iplan2p8.c b/drivers/video/atafb_iplan2p8.c
new file mode 100644
index 0000000..356fb52
--- /dev/null
+++ b/drivers/video/atafb_iplan2p8.c
@@ -0,0 +1,345 @@
+/*
+ *  linux/drivers/video/iplan2p8.c -- Low level frame buffer operations for
+ *				      interleaved bitplanes à la Atari (8
+ *				      planes, 2 bytes interleave)
+ *
+ *	Created 5 Apr 1997 by Geert Uytterhoeven
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License.  See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/fb.h>
+
+#include <asm/setup.h>
+
+#include "atafb.h"
+
+#define BPL	8
+#include "atafb_utils.h"
+
+
+/* Copies a 8 plane column from 's', height 'h', to 'd'. */
+
+/* This expands a 8 bit color into two longs for two movepl (8 plane)
+ * operations.
+ */
+
+void atafb_iplan2p8_copyarea(struct fb_info *info, u_long next_line,
+			     int sy, int sx, int dy, int dx,
+			     int height, int width)
+{
+	/*  bmove() has to distinguish two major cases: If both, source and
+	 *  destination, start at even addresses or both are at odd
+	 *  addresses, just the first odd and last even column (if present)
+	 *  require special treatment (memmove_col()). The rest between
+	 *  then can be copied by normal operations, because all adjacent
+	 *  bytes are affected and are to be stored in the same order.
+	 *    The pathological case is when the move should go from an odd
+	 *  address to an even or vice versa. Since the bytes in the plane
+	 *  words must be assembled in new order, it seems wisest to make
+	 *  all movements by memmove_col().
+	 */
+
+	u8 *src, *dst;
+	u32 *s, *d;
+	int w, l , i, j;
+	u_int colsize;
+	u_int upwards = (dy < sy) || (dy == sy && dx < sx);
+
+	colsize = height;
+	if (!((sx ^ dx) & 15)) {
+		/* odd->odd or even->even */
+
+		if (upwards) {
+			src = (u8 *)info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL);
+			dst = (u8 *)info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL);
+			if (sx & 15) {
+				memmove32_col(dst, src, 0xff00ff, height, next_line - BPL * 2);
+				src += BPL * 2;
+				dst += BPL * 2;
+				width -= 8;
+			}
+			w = width >> 4;
+			if (w) {
+				s = (u32 *)src;
+				d = (u32 *)dst;
+				w *= BPL / 2;
+				l = next_line - w * 4;
+				for (j = height; j > 0; j--) {
+					for (i = w; i > 0; i--)
+						*d++ = *s++;
+					s = (u32 *)((u8 *)s + l);
+					d = (u32 *)((u8 *)d + l);
+				}
+			}
+			if (width & 15)
+				memmove32_col(dst + width / (8 / BPL), src + width / (8 / BPL),
+					      0xff00ff00, height, next_line - BPL * 2);
+		} else {
+			src = (u8 *)info->screen_base + (sy - 1) * next_line + ((sx + width + 8) & ~15) / (8 / BPL);
+			dst = (u8 *)info->screen_base + (dy - 1) * next_line + ((dx + width + 8) & ~15) / (8 / BPL);
+
+			if ((sx + width) & 15) {
+				src -= BPL * 2;
+				dst -= BPL * 2;
+				memmove32_col(dst, src, 0xff00ff00, colsize, -next_line - BPL * 2);
+				width -= 8;
+			}
+			w = width >> 4;
+			if (w) {
+				s = (u32 *)src;
+				d = (u32 *)dst;
+				w *= BPL / 2;
+				l = next_line - w * 4;
+				for (j = height; j > 0; j--) {
+					for (i = w; i > 0; i--)
+						*--d = *--s;
+					s = (u32 *)((u8 *)s - l);
+					d = (u32 *)((u8 *)d - l);
+				}
+			}
+			if (sx & 15)
+				memmove32_col(dst - (width - 16) / (8 / BPL),
+					      src - (width - 16) / (8 / BPL),
+					      0xff00ff, colsize, -next_line - BPL * 2);
+		}
+	} else {
+		/* odd->even or even->odd */
+		if (upwards) {
+			u32 *src32, *dst32;
+			u32 pval[4], v, v1, mask;
+			int i, j, w, f;
+
+			src = (u8 *)info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL);
+			dst = (u8 *)info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL);
+
+			mask = 0xff00ff00;
+			f = 0;
+			w = width;
+			if (sx & 15) {
+				f = 1;
+				w += 8;
+			}
+			if ((sx + width) & 15)
+				f |= 2;
+			w >>= 4;
+			for (i = height; i; i--) {
+				src32 = (u32 *)src;
+				dst32 = (u32 *)dst;
+
+				if (f & 1) {
+					pval[0] = (*src32++ << 8) & mask;
+					pval[1] = (*src32++ << 8) & mask;
+					pval[2] = (*src32++ << 8) & mask;
+					pval[3] = (*src32++ << 8) & mask;
+				} else {
+					pval[0] = dst32[0] & mask;
+					pval[1] = dst32[1] & mask;
+					pval[2] = dst32[2] & mask;
+					pval[3] = dst32[3] & mask;
+				}
+
+				for (j = w; j > 0; j--) {
+					v = *src32++;
+					v1 = v & mask;
+					*dst32++ = pval[0] | (v1 >> 8);
+					pval[0] = (v ^ v1) << 8;
+					v = *src32++;
+					v1 = v & mask;
+					*dst32++ = pval[1] | (v1 >> 8);
+					pval[1] = (v ^ v1) << 8;
+					v = *src32++;
+					v1 = v & mask;
+					*dst32++ = pval[2] | (v1 >> 8);
+					pval[2] = (v ^ v1) << 8;
+					v = *src32++;
+					v1 = v & mask;
+					*dst32++ = pval[3] | (v1 >> 8);
+					pval[3] = (v ^ v1) << 8;
+				}
+
+				if (f & 2) {
+					dst32[0] = (dst32[0] & mask) | pval[0];
+					dst32[1] = (dst32[1] & mask) | pval[1];
+					dst32[2] = (dst32[2] & mask) | pval[2];
+					dst32[3] = (dst32[3] & mask) | pval[3];
+				}
+
+				src += next_line;
+				dst += next_line;
+			}
+		} else {
+			u32 *src32, *dst32;
+			u32 pval[4], v, v1, mask;
+			int i, j, w, f;
+
+			src = (u8 *)info->screen_base + (sy - 1) * next_line + ((sx + width + 8) & ~15) / (8 / BPL);
+			dst = (u8 *)info->screen_base + (dy - 1) * next_line + ((dx + width + 8) & ~15) / (8 / BPL);
+
+			mask = 0xff00ff;
+			f = 0;
+			w = width;
+			if ((dx + width) & 15)
+				f = 1;
+			if (sx & 15) {
+				f |= 2;
+				w += 8;
+			}
+			w >>= 4;
+			for (i = height; i; i--) {
+				src32 = (u32 *)src;
+				dst32 = (u32 *)dst;
+
+				if (f & 1) {
+					pval[0] = dst32[-1] & mask;
+					pval[1] = dst32[-2] & mask;
+					pval[2] = dst32[-3] & mask;
+					pval[3] = dst32[-4] & mask;
+				} else {
+					pval[0] = (*--src32 >> 8) & mask;
+					pval[1] = (*--src32 >> 8) & mask;
+					pval[2] = (*--src32 >> 8) & mask;
+					pval[3] = (*--src32 >> 8) & mask;
+				}
+
+				for (j = w; j > 0; j--) {
+					v = *--src32;
+					v1 = v & mask;
+					*--dst32 = pval[0] | (v1 << 8);
+					pval[0] = (v ^ v1) >> 8;
+					v = *--src32;
+					v1 = v & mask;
+					*--dst32 = pval[1] | (v1 << 8);
+					pval[1] = (v ^ v1) >> 8;
+					v = *--src32;
+					v1 = v & mask;
+					*--dst32 = pval[2] | (v1 << 8);
+					pval[2] = (v ^ v1) >> 8;
+					v = *--src32;
+					v1 = v & mask;
+					*--dst32 = pval[3] | (v1 << 8);
+					pval[3] = (v ^ v1) >> 8;
+				}
+
+				if (!(f & 2)) {
+					dst32[-1] = (dst32[-1] & mask) | pval[0];
+					dst32[-2] = (dst32[-2] & mask) | pval[1];
+					dst32[-3] = (dst32[-3] & mask) | pval[2];
+					dst32[-4] = (dst32[-4] & mask) | pval[3];
+				}
+
+				src -= next_line;
+				dst -= next_line;
+			}
+		}
+	}
+}
+
+void atafb_iplan2p8_fillrect(struct fb_info *info, u_long next_line, u32 color,
+                             int sy, int sx, int height, int width)
+{
+	u32 *dest;
+	int rows, i;
+	u32 cval[4];
+
+	dest = (u32 *)(info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL));
+	if (sx & 15) {
+		u8 *dest8 = (u8 *)dest + 1;
+
+		expand8_col2mask(color, cval);
+
+		for (i = height; i; i--) {
+			fill8_col(dest8, cval);
+			dest8 += next_line;
+		}
+		dest += BPL / 2;
+		width -= 8;
+	}
+
+	expand16_col2mask(color, cval);
+	rows = width >> 4;
+	if (rows) {
+		u32 *d = dest;
+		u32 off = next_line - rows * BPL * 2;
+		for (i = height; i; i--) {
+			d = fill16_col(d, rows, cval);
+			d = (u32 *)((long)d + off);
+		}
+		dest += rows * BPL / 2;
+		width &= 15;
+	}
+
+	if (width) {
+		u8 *dest8 = (u8 *)dest;
+
+		expand8_col2mask(color, cval);
+
+		for (i = height; i; i--) {
+			fill8_col(dest8, cval);
+			dest8 += next_line;
+		}
+	}
+}
+
+void atafb_iplan2p8_linefill(struct fb_info *info, u_long next_line,
+			     int dy, int dx, u32 width,
+			     const u8 *data, u32 bgcolor, u32 fgcolor)
+{
+	u32 *dest;
+	const u16 *data16;
+	int rows;
+	u32 fgm[4], bgm[4], m;
+
+	dest = (u32 *)(info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL));
+	if (dx & 15) {
+		fill8_2col((u8 *)dest + 1, fgcolor, bgcolor, *data++);
+		dest += BPL / 2;
+		width -= 8;
+	}
+
+	if (width >= 16) {
+		data16 = (const u16 *)data;
+		expand16_2col2mask(fgcolor, bgcolor, fgm, bgm);
+
+		for (rows = width / 16; rows; rows--) {
+			u16 d = *data16++;
+			m = d | ((u32)d << 16);
+			*dest++ = (m & fgm[0]) ^ bgm[0];
+			*dest++ = (m & fgm[1]) ^ bgm[1];
+			*dest++ = (m & fgm[2]) ^ bgm[2];
+			*dest++ = (m & fgm[3]) ^ bgm[3];
+		}
+
+		data = (const u8 *)data16;
+		width &= 15;
+	}
+
+	if (width)
+		fill8_2col((u8 *)dest, fgcolor, bgcolor, *data);
+}
+
+#ifdef MODULE
+MODULE_LICENSE("GPL");
+
+int init_module(void)
+{
+	return 0;
+}
+
+void cleanup_module(void)
+{
+}
+#endif /* MODULE */
+
+
+    /*
+     *  Visible symbols for modules
+     */
+
+EXPORT_SYMBOL(atafb_iplan2p8_copyarea);
+EXPORT_SYMBOL(atafb_iplan2p8_fillrect);
+EXPORT_SYMBOL(atafb_iplan2p8_linefill);
diff --git a/drivers/video/atafb_mfb.c b/drivers/video/atafb_mfb.c
new file mode 100644
index 0000000..6a352d6
--- /dev/null
+++ b/drivers/video/atafb_mfb.c
@@ -0,0 +1,112 @@
+/*
+ *  linux/drivers/video/mfb.c -- Low level frame buffer operations for
+ *				 monochrome
+ *
+ *	Created 5 Apr 1997 by Geert Uytterhoeven
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License.  See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/fb.h>
+
+#include "atafb.h"
+#include "atafb_utils.h"
+
+
+    /*
+     *  Monochrome
+     */
+
+void atafb_mfb_copyarea(struct fb_info *info, u_long next_line,
+			int sy, int sx, int dy, int dx,
+			int height, int width)
+{
+	u8 *src, *dest;
+	u_int rows;
+
+	if (sx == 0 && dx == 0 && width == next_line) {
+		src = (u8 *)info->screen_base + sy * (width >> 3);
+		dest = (u8 *)info->screen_base + dy * (width >> 3);
+		fb_memmove(dest, src, height * (width >> 3));
+	} else if (dy <= sy) {
+		src = (u8 *)info->screen_base + sy * next_line + (sx >> 3);
+		dest = (u8 *)info->screen_base + dy * next_line + (dx >> 3);
+		for (rows = height; rows--;) {
+			fb_memmove(dest, src, width >> 3);
+			src += next_line;
+			dest += next_line;
+		}
+	} else {
+		src = (u8 *)info->screen_base + (sy + height - 1) * next_line + (sx >> 3);
+		dest = (u8 *)info->screen_base + (dy + height - 1) * next_line + (dx >> 3);
+		for (rows = height; rows--;) {
+			fb_memmove(dest, src, width >> 3);
+			src -= next_line;
+			dest -= next_line;
+		}
+	}
+}
+
+void atafb_mfb_fillrect(struct fb_info *info, u_long next_line, u32 color,
+			int sy, int sx, int height, int width)
+{
+	u8 *dest;
+	u_int rows;
+
+	dest = (u8 *)info->screen_base + sy * next_line + (sx >> 3);
+
+	if (sx == 0 && width == next_line) {
+		if (color)
+			fb_memset255(dest, height * (width >> 3));
+		else
+			fb_memclear(dest, height * (width >> 3));
+	} else {
+		for (rows = height; rows--; dest += next_line) {
+			if (color)
+				fb_memset255(dest, width >> 3);
+			else
+				fb_memclear_small(dest, width >> 3);
+		}
+	}
+}
+
+void atafb_mfb_linefill(struct fb_info *info, u_long next_line,
+			int dy, int dx, u32 width,
+			const u8 *data, u32 bgcolor, u32 fgcolor)
+{
+	u8 *dest;
+	u_int rows;
+
+	dest = (u8 *)info->screen_base + dy * next_line + (dx >> 3);
+
+	for (rows = width / 8; rows--; /* check margins */ ) {
+		// use fast_memmove or fb_memmove
+		*dest++ = *data++;
+	}
+}
+
+#ifdef MODULE
+MODULE_LICENSE("GPL");
+
+int init_module(void)
+{
+	return 0;
+}
+
+void cleanup_module(void)
+{
+}
+#endif /* MODULE */
+
+
+    /*
+     *  Visible symbols for modules
+     */
+
+EXPORT_SYMBOL(atafb_mfb_copyarea);
+EXPORT_SYMBOL(atafb_mfb_fillrect);
+EXPORT_SYMBOL(atafb_mfb_linefill);
diff --git a/drivers/video/atafb_utils.h b/drivers/video/atafb_utils.h
new file mode 100644
index 0000000..ac9e19d
--- /dev/null
+++ b/drivers/video/atafb_utils.h
@@ -0,0 +1,400 @@
+#ifndef _VIDEO_ATAFB_UTILS_H
+#define _VIDEO_ATAFB_UTILS_H
+
+/* ================================================================= */
+/*                      Utility Assembler Functions                  */
+/* ================================================================= */
+
+/* ====================================================================== */
+
+/* Those of a delicate disposition might like to skip the next couple of
+ * pages.
+ *
+ * These functions are drop in replacements for memmove and
+ * memset(_, 0, _). However their five instances add at least a kilobyte
+ * to the object file. You have been warned.
+ *
+ * Not a great fan of assembler for the sake of it, but I think
+ * that these routines are at least 10 times faster than their C
+ * equivalents for large blits, and that's important to the lowest level of
+ * a graphics driver. Question is whether some scheme with the blitter
+ * would be faster. I suspect not for simple text system - not much
+ * asynchrony.
+ *
+ * Code is very simple, just gruesome expansion. Basic strategy is to
+ * increase data moved/cleared at each step to 16 bytes to reduce
+ * instruction per data move overhead. movem might be faster still
+ * For more than 15 bytes, we try to align the write direction on a
+ * longword boundary to get maximum speed. This is even more gruesome.
+ * Unaligned read/write used requires 68020+ - think this is a problem?
+ *
+ * Sorry!
+ */
+
+
+/* ++roman: I've optimized Robert's original versions in some minor
+ * aspects, e.g. moveq instead of movel, let gcc choose the registers,
+ * use movem in some places...
+ * For other modes than 1 plane, lots of more such assembler functions
+ * were needed (e.g. the ones using movep or expanding color values).
+ */
+
+/* ++andreas: more optimizations:
+   subl #65536,d0 replaced by clrw d0; subql #1,d0 for dbcc
+   addal is faster than addaw
+   movep is rather expensive compared to ordinary move's
+   some functions rewritten in C for clarity, no speed loss */
+
+static inline void *fb_memclear_small(void *s, size_t count)
+{
+	if (!count)
+		return 0;
+
+	asm volatile ("\n"
+		"	lsr.l	#1,%1 ; jcc 1f ; move.b %2,-(%0)\n"
+		"1:	lsr.l	#1,%1 ; jcc 1f ; move.w %2,-(%0)\n"
+		"1:	lsr.l	#1,%1 ; jcc 1f ; move.l %2,-(%0)\n"
+		"1:	lsr.l	#1,%1 ; jcc 1f ; move.l %2,-(%0) ; move.l %2,-(%0)\n"
+		"1:"
+		: "=a" (s), "=d" (count)
+		: "d" (0), "0" ((char *)s + count), "1" (count));
+	asm volatile ("\n"
+		"	subq.l  #1,%1\n"
+		"	jcs	3f\n"
+		"	move.l	%2,%%d4; move.l %2,%%d5; move.l %2,%%d6\n"
+		"2:	movem.l	%2/%%d4/%%d5/%%d6,-(%0)\n"
+		"	dbra	%1,2b\n"
+		"3:"
+		: "=a" (s), "=d" (count)
+		: "d" (0), "0" (s), "1" (count)
+		: "d4", "d5", "d6"
+		);
+
+	return 0;
+}
+
+
+static inline void *fb_memclear(void *s, size_t count)
+{
+	if (!count)
+		return 0;
+
+	if (count < 16) {
+		asm volatile ("\n"
+			"	lsr.l	#1,%1 ; jcc 1f ; clr.b (%0)+\n"
+			"1:	lsr.l	#1,%1 ; jcc 1f ; clr.w (%0)+\n"
+			"1:	lsr.l	#1,%1 ; jcc 1f ; clr.l (%0)+\n"
+			"1:	lsr.l	#1,%1 ; jcc 1f ; clr.l (%0)+ ; clr.l (%0)+\n"
+			"1:"
+			: "=a" (s), "=d" (count)
+			: "0" (s), "1" (count));
+	} else {
+		long tmp;
+		asm volatile ("\n"
+			"	move.l	%1,%2\n"
+			"	lsr.l	#1,%2 ; jcc 1f ; clr.b (%0)+ ; subq.w #1,%1\n"
+			"	lsr.l	#1,%2 ; jcs 2f\n"  /* %0 increased=>bit 2 switched*/
+			"	clr.w	(%0)+  ; subq.w  #2,%1 ; jra 2f\n"
+			"1:	lsr.l	#1,%2 ; jcc 2f\n"
+			"	clr.w	(%0)+  ; subq.w  #2,%1\n"
+			"2:	move.w	%1,%2; lsr.l #2,%1 ; jeq 6f\n"
+			"	lsr.l	#1,%1 ; jcc 3f ; clr.l (%0)+\n"
+			"3:	lsr.l	#1,%1 ; jcc 4f ; clr.l (%0)+ ; clr.l (%0)+\n"
+			"4:	subq.l	#1,%1 ; jcs 6f\n"
+			"5:	clr.l	(%0)+; clr.l (%0)+ ; clr.l (%0)+ ; clr.l (%0)+\n"
+			"	dbra	%1,5b ; clr.w %1; subq.l #1,%1; jcc 5b\n"
+			"6:	move.w	%2,%1; btst #1,%1 ; jeq 7f ; clr.w (%0)+\n"
+			"7:	btst	#0,%1 ; jeq 8f ; clr.b (%0)+\n"
+			"8:"
+			: "=a" (s), "=d" (count), "=d" (tmp)
+			: "0" (s), "1" (count));
+	}
+
+	return 0;
+}
+
+
+static inline void *fb_memset255(void *s, size_t count)
+{
+	if (!count)
+		return 0;
+
+	asm volatile ("\n"
+		"	lsr.l	#1,%1 ; jcc 1f ; move.b %2,-(%0)\n"
+		"1:	lsr.l	#1,%1 ; jcc 1f ; move.w %2,-(%0)\n"
+		"1:	lsr.l	#1,%1 ; jcc 1f ; move.l %2,-(%0)\n"
+		"1:	lsr.l	#1,%1 ; jcc 1f ; move.l %2,-(%0) ; move.l %2,-(%0)\n"
+		"1:"
+		: "=a" (s), "=d" (count)
+		: "d" (-1), "0" ((char *)s+count), "1" (count));
+	asm volatile ("\n"
+		"	subq.l	#1,%1 ; jcs 3f\n"
+		"	move.l	%2,%%d4; move.l %2,%%d5; move.l %2,%%d6\n"
+		"2:	movem.l	%2/%%d4/%%d5/%%d6,-(%0)\n"
+		"	dbra	%1,2b\n"
+		"3:"
+		: "=a" (s), "=d" (count)
+		: "d" (-1), "0" (s), "1" (count)
+		: "d4", "d5", "d6");
+
+	return 0;
+}
+
+
+static inline void *fb_memmove(void *d, const void *s, size_t count)
+{
+	if (d < s) {
+		if (count < 16) {
+			asm volatile ("\n"
+				"	lsr.l	#1,%2 ; jcc 1f ; move.b (%1)+,(%0)+\n"
+				"1:	lsr.l	#1,%2 ; jcc 1f ; move.w (%1)+,(%0)+\n"
+				"1:	lsr.l	#1,%2 ; jcc 1f ; move.l (%1)+,(%0)+\n"
+				"1:	lsr.l	#1,%2 ; jcc 1f ; move.l (%1)+,(%0)+ ; move.l (%1)+,(%0)+\n"
+				"1:"
+				: "=a" (d), "=a" (s), "=d" (count)
+				: "0" (d), "1" (s), "2" (count));
+		} else {
+			long tmp;
+			asm volatile ("\n"
+				"	move.l	%0,%3\n"
+				"	lsr.l	#1,%3 ; jcc 1f ; move.b (%1)+,(%0)+ ; subqw #1,%2\n"
+				"	lsr.l	#1,%3 ; jcs 2f\n"  /* %0 increased=>bit 2 switched*/
+				"	move.w	(%1)+,(%0)+  ; subqw  #2,%2 ; jra 2f\n"
+				"1:	lsr.l   #1,%3 ; jcc 2f\n"
+				"	move.w	(%1)+,(%0)+  ; subqw  #2,%2\n"
+				"2:	move.w	%2,%-; lsr.l #2,%2 ; jeq 6f\n"
+				"	lsr.l	#1,%2 ; jcc 3f ; move.l (%1)+,(%0)+\n"
+				"3:	lsr.l	#1,%2 ; jcc 4f ; move.l (%1)+,(%0)+ ; move.l (%1)+,(%0)+\n"
+				"4:	subq.l	#1,%2 ; jcs 6f\n"
+				"5:	move.l	(%1)+,(%0)+; move.l (%1)+,(%0)+\n"
+				"	move.l	(%1)+,(%0)+; move.l (%1)+,(%0)+\n"
+				"	dbra	%2,5b ; clr.w %2; subq.l #1,%2; jcc 5b\n"
+				"6:	move.w	%+,%2; btst #1,%2 ; jeq 7f ; move.w (%1)+,(%0)+\n"
+				"7:	btst	#0,%2 ; jeq 8f ; move.b (%1)+,(%0)+\n"
+				"8:"
+				: "=a" (d), "=a" (s), "=d" (count), "=d" (tmp)
+				: "0" (d), "1" (s), "2" (count));
+		}
+	} else {
+		if (count < 16) {
+			asm volatile ("\n"
+				"	lsr.l	#1,%2 ; jcc 1f ; move.b -(%1),-(%0)\n"
+				"1:	lsr.l	#1,%2 ; jcc 1f ; move.w -(%1),-(%0)\n"
+				"1:	lsr.l	#1,%2 ; jcc 1f ; move.l -(%1),-(%0)\n"
+				"1:	lsr.l	#1,%2 ; jcc 1f ; move.l -(%1),-(%0) ; move.l -(%1),-(%0)\n"
+				"1:"
+				: "=a" (d), "=a" (s), "=d" (count)
+				: "0" ((char *) d + count), "1" ((char *) s + count), "2" (count));
+		} else {
+			long tmp;
+
+			asm volatile ("\n"
+				"	move.l	%0,%3\n"
+				"	lsr.l	#1,%3 ; jcc 1f ; move.b -(%1),-(%0) ; subqw #1,%2\n"
+				"	lsr.l	#1,%3 ; jcs 2f\n"  /* %0 increased=>bit 2 switched*/
+				"	move.w	-(%1),-(%0) ; subqw  #2,%2 ; jra 2f\n"
+				"1:	lsr.l	#1,%3 ; jcc 2f\n"
+				"	move.w	-(%1),-(%0) ; subqw  #2,%2\n"
+				"2:	move.w	%2,%-; lsr.l #2,%2 ; jeq 6f\n"
+				"	lsr.l	#1,%2 ; jcc 3f ; move.l -(%1),-(%0)\n"
+				"3:	lsr.l	#1,%2 ; jcc 4f ; move.l -(%1),-(%0) ; move.l -(%1),-(%0)\n"
+				"4:	subq.l	#1,%2 ; jcs 6f\n"
+				"5:	move.l	-(%1),-(%0); move.l -(%1),-(%0)\n"
+				"	move.l	-(%1),-(%0); move.l -(%1),-(%0)\n"
+				"	dbra	%2,5b ; clr.w %2; subq.l #1,%2; jcc 5b\n"
+				"6:	move.w	%+,%2; btst #1,%2 ; jeq 7f ; move.w -(%1),-(%0)\n"
+				"7:	btst	#0,%2 ; jeq 8f ; move.b -(%1),-(%0)\n"
+				"8:"
+				: "=a" (d), "=a" (s), "=d" (count), "=d" (tmp)
+				: "0" ((char *) d + count), "1" ((char *) s + count), "2" (count));
+		}
+	}
+
+	return 0;
+}
+
+
+/* ++andreas: Simple and fast version of memmove, assumes size is
+   divisible by 16, suitable for moving the whole screen bitplane */
+static inline void fast_memmove(char *dst, const char *src, size_t size)
+{
+	if (!size)
+		return;
+	if (dst < src)
+		asm volatile ("\n"
+			"1:	movem.l	(%0)+,%%d0/%%d1/%%a0/%%a1\n"
+			"	movem.l	%%d0/%%d1/%%a0/%%a1,%1@\n"
+			"	addq.l	#8,%1; addq.l #8,%1\n"
+			"	dbra	%2,1b\n"
+			"	clr.w	%2; subq.l #1,%2\n"
+			"	jcc	1b"
+			: "=a" (src), "=a" (dst), "=d" (size)
+			: "0" (src), "1" (dst), "2" (size / 16 - 1)
+			: "d0", "d1", "a0", "a1", "memory");
+	else
+		asm volatile ("\n"
+			"1:	subq.l	#8,%0; subq.l #8,%0\n"
+			"	movem.l	%0@,%%d0/%%d1/%%a0/%%a1\n"
+			"	movem.l	%%d0/%%d1/%%a0/%%a1,-(%1)\n"
+			"	dbra	%2,1b\n"
+			"	clr.w	%2; subq.l #1,%2\n"
+			"	jcc 1b"
+			: "=a" (src), "=a" (dst), "=d" (size)
+			: "0" (src + size), "1" (dst + size), "2" (size / 16 - 1)
+			: "d0", "d1", "a0", "a1", "memory");
+}
+
+#ifdef BPL
+
+/*
+ * This expands a up to 8 bit color into two longs
+ * for movel operations.
+ */
+static const u32 four2long[] = {
+	0x00000000, 0x000000ff, 0x0000ff00, 0x0000ffff,
+	0x00ff0000, 0x00ff00ff, 0x00ffff00, 0x00ffffff,
+	0xff000000, 0xff0000ff, 0xff00ff00, 0xff00ffff,
+	0xffff0000, 0xffff00ff, 0xffffff00, 0xffffffff,
+};
+
+static inline void expand8_col2mask(u8 c, u32 m[])
+{
+	m[0] = four2long[c & 15];
+#if BPL > 4
+	m[1] = four2long[c >> 4];
+#endif
+}
+
+static inline void expand8_2col2mask(u8 fg, u8 bg, u32 fgm[], u32 bgm[])
+{
+	fgm[0] = four2long[fg & 15] ^ (bgm[0] = four2long[bg & 15]);
+#if BPL > 4
+	fgm[1] = four2long[fg >> 4] ^ (bgm[1] = four2long[bg >> 4]);
+#endif
+}
+
+/*
+ * set an 8bit value to a color
+ */
+static inline void fill8_col(u8 *dst, u32 m[])
+{
+	u32 tmp = m[0];
+	dst[0] = tmp;
+	dst[2] = (tmp >>= 8);
+#if BPL > 2
+	dst[4] = (tmp >>= 8);
+	dst[6] = tmp >> 8;
+#endif
+#if BPL > 4
+	tmp = m[1];
+	dst[8] = tmp;
+	dst[10] = (tmp >>= 8);
+	dst[12] = (tmp >>= 8);
+	dst[14] = tmp >> 8;
+#endif
+}
+
+/*
+ * set an 8bit value according to foreground/background color
+ */
+static inline void fill8_2col(u8 *dst, u8 fg, u8 bg, u32 mask)
+{
+	u32 fgm[2], bgm[2], tmp;
+
+	expand8_2col2mask(fg, bg, fgm, bgm);
+
+	mask |= mask << 8;
+#if BPL > 2
+	mask |= mask << 16;
+#endif
+	tmp = (mask & fgm[0]) ^ bgm[0];
+	dst[0] = tmp;
+	dst[2] = (tmp >>= 8);
+#if BPL > 2
+	dst[4] = (tmp >>= 8);
+	dst[6] = tmp >> 8;
+#endif
+#if BPL > 4
+	tmp = (mask & fgm[1]) ^ bgm[1];
+	dst[8] = tmp;
+	dst[10] = (tmp >>= 8);
+	dst[12] = (tmp >>= 8);
+	dst[14] = tmp >> 8;
+#endif
+}
+
+static const u32 two2word[] = {
+	0x00000000, 0xffff0000, 0x0000ffff, 0xffffffff
+};
+
+static inline void expand16_col2mask(u8 c, u32 m[])
+{
+	m[0] = two2word[c & 3];
+#if BPL > 2
+	m[1] = two2word[(c >> 2) & 3];
+#endif
+#if BPL > 4
+	m[2] = two2word[(c >> 4) & 3];
+	m[3] = two2word[c >> 6];
+#endif
+}
+
+static inline void expand16_2col2mask(u8 fg, u8 bg, u32 fgm[], u32 bgm[])
+{
+	bgm[0] = two2word[bg & 3];
+	fgm[0] = two2word[fg & 3] ^ bgm[0];
+#if BPL > 2
+	bgm[1] = two2word[(bg >> 2) & 3];
+	fgm[1] = two2word[(fg >> 2) & 3] ^ bgm[1];
+#endif
+#if BPL > 4
+	bgm[2] = two2word[(bg >> 4) & 3];
+	fgm[2] = two2word[(fg >> 4) & 3] ^ bgm[2];
+	bgm[3] = two2word[bg >> 6];
+	fgm[3] = two2word[fg >> 6] ^ bgm[3];
+#endif
+}
+
+static inline u32 *fill16_col(u32 *dst, int rows, u32 m[])
+{
+	while (rows) {
+		*dst++ = m[0];
+#if BPL > 2
+		*dst++ = m[1];
+#endif
+#if BPL > 4
+		*dst++ = m[2];
+		*dst++ = m[3];
+#endif
+		rows--;
+	}
+	return dst;
+}
+
+static inline void memmove32_col(void *dst, void *src, u32 mask, u32 h, u32 bytes)
+{
+	u32 *s, *d, v;
+
+        s = src;
+        d = dst;
+        do {
+                v = (*s++ & mask) | (*d  & ~mask);
+                *d++ = v;
+#if BPL > 2
+                v = (*s++ & mask) | (*d  & ~mask);
+                *d++ = v;
+#endif
+#if BPL > 4
+                v = (*s++ & mask) | (*d  & ~mask);
+                *d++ = v;
+                v = (*s++ & mask) | (*d  & ~mask);
+                *d++ = v;
+#endif
+                d = (u32 *)((u8 *)d + bytes);
+                s = (u32 *)((u8 *)s + bytes);
+        } while (--h);
+}
+
+#endif
+
+#endif /* _VIDEO_ATAFB_UTILS_H */
diff --git a/drivers/video/aty/radeon_i2c.c b/drivers/video/aty/radeon_i2c.c
index 5084799..7db9de6 100644
--- a/drivers/video/aty/radeon_i2c.c
+++ b/drivers/video/aty/radeon_i2c.c
@@ -1,7 +1,6 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/delay.h>
-#include <linux/pci.h>
 #include <linux/fb.h>
 
 
diff --git a/drivers/video/g364fb.c b/drivers/video/g364fb.c
index ca93a75..b7655c0 100644
--- a/drivers/video/g364fb.c
+++ b/drivers/video/g364fb.c
@@ -26,7 +26,6 @@
 #include <linux/interrupt.h>
 #include <linux/fb.h>
 #include <linux/init.h>
-#include <linux/pci.h>
 #include <asm/io.h>
 #include <asm/jazz.h>
 
diff --git a/drivers/video/intelfb/intelfb_i2c.c b/drivers/video/intelfb/intelfb_i2c.c
index f4ede5f..61e4c87 100644
--- a/drivers/video/intelfb/intelfb_i2c.c
+++ b/drivers/video/intelfb/intelfb_i2c.c
@@ -104,7 +104,8 @@
 
 	chan->dinfo					= dinfo;
 	chan->reg					= reg;
-	snprintf(chan->adapter.name, I2C_NAME_SIZE, "intelfb %s", name);
+	snprintf(chan->adapter.name, sizeof(chan->adapter.name),
+		 "intelfb %s", name);
 	chan->adapter.owner			= THIS_MODULE;
 	chan->adapter.id			= I2C_HW_B_INTELFB;
 	chan->adapter.algo_data		= &chan->algo;
diff --git a/drivers/video/matrox/i2c-matroxfb.c b/drivers/video/matrox/i2c-matroxfb.c
index 5ec718a..4baab7b 100644
--- a/drivers/video/matrox/i2c-matroxfb.c
+++ b/drivers/video/matrox/i2c-matroxfb.c
@@ -111,7 +111,7 @@
 	b->mask.data = data;
 	b->mask.clock = clock;
 	b->adapter = matrox_i2c_adapter_template;
-	snprintf(b->adapter.name, I2C_NAME_SIZE, name,
+	snprintf(b->adapter.name, sizeof(b->adapter.name), name,
 		minfo->fbcon.node);
 	i2c_set_adapdata(&b->adapter, b);
 	b->adapter.algo_data = &b->bac;
diff --git a/drivers/video/platinumfb.c b/drivers/video/platinumfb.c
index 2338716..e64f8b5 100644
--- a/drivers/video/platinumfb.c
+++ b/drivers/video/platinumfb.c
@@ -28,7 +28,6 @@
 #include <linux/interrupt.h>
 #include <linux/fb.h>
 #include <linux/init.h>
-#include <linux/pci.h>
 #include <linux/nvram.h>
 #include <asm/io.h>
 #include <asm/prom.h>
diff --git a/drivers/video/ps3fb.c b/drivers/video/ps3fb.c
index 81e43cd..07d1979 100644
--- a/drivers/video/ps3fb.c
+++ b/drivers/video/ps3fb.c
@@ -32,6 +32,8 @@
 #include <linux/ioctl.h>
 #include <linux/notifier.h>
 #include <linux/reboot.h>
+#include <linux/kthread.h>
+#include <linux/freezer.h>
 
 #include <asm/uaccess.h>
 #include <linux/fb.h>
@@ -45,7 +47,7 @@
 #include <asm/ps3.h>
 
 #ifdef PS3FB_DEBUG
-#define DPRINTK(fmt, args...) printk("%s: " fmt, __FUNCTION__ , ##args)
+#define DPRINTK(fmt, args...) printk("%s: " fmt, __func__ , ##args)
 #else
 #define DPRINTK(fmt, args...)
 #endif
@@ -129,7 +131,6 @@
 	u64 context_handle, memory_handle;
 	void *xdr_ea;
 	struct gpu_driver_info *dinfo;
-	struct semaphore sem;
 	u32 res_index;
 
 	u64 vblank_count;	/* frame count */
@@ -139,6 +140,8 @@
 	atomic_t ext_flip;	/* on/off flip with vsync */
 	atomic_t f_count;	/* fb_open count */
 	int is_blanked;
+	int is_kicked;
+	struct task_struct *task;
 };
 static struct ps3fb_priv ps3fb;
 
@@ -294,10 +297,10 @@
 #define VP_OFF(i)	(WIDTH(i) * Y_OFF(i) * BPP + X_OFF(i) * BPP)
 #define FB_OFF(i)	(GPU_OFFSET - VP_OFF(i) % GPU_OFFSET)
 
-static int ps3fb_mode = 0;
+static int ps3fb_mode;
 module_param(ps3fb_mode, bool, 0);
 
-static char *mode_option __initdata = NULL;
+static char *mode_option __initdata;
 
 
 static int ps3fb_get_res_table(u32 xres, u32 yres)
@@ -393,7 +396,7 @@
 
 	if (frame > ps3fb.num_frames - 1) {
 		printk(KERN_WARNING "%s: invalid frame number (%u)\n",
-		       __FUNCTION__, frame);
+		       __func__, frame);
 		return -EINVAL;
 	}
 	offset = xres * yres * BPP * frame;
@@ -406,23 +409,26 @@
 					   (xres << 16) | yres,
 					   xres * BPP);	/* line_length */
 	if (status)
-		printk(KERN_ERR "%s: lv1_gpu_context_attribute FB_BLIT failed: %d\n",
-		       __FUNCTION__, status);
+		printk(KERN_ERR
+		       "%s: lv1_gpu_context_attribute FB_BLIT failed: %d\n",
+		       __func__, status);
 #ifdef HEAD_A
 	status = lv1_gpu_context_attribute(ps3fb.context_handle,
 					   L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_FLIP,
 					   0, offset, 0, 0);
 	if (status)
-		printk(KERN_ERR "%s: lv1_gpu_context_attribute FLIP failed: %d\n",
-		       __FUNCTION__, status);
+		printk(KERN_ERR
+		       "%s: lv1_gpu_context_attribute FLIP failed: %d\n",
+		       __func__, status);
 #endif
 #ifdef HEAD_B
 	status = lv1_gpu_context_attribute(ps3fb.context_handle,
 					   L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_FLIP,
 					   1, offset, 0, 0);
 	if (status)
-		printk(KERN_ERR "%s: lv1_gpu_context_attribute FLIP failed: %d\n",
-		       __FUNCTION__, status);
+		printk(KERN_ERR
+		       "%s: lv1_gpu_context_attribute FLIP failed: %d\n",
+		       __func__, status);
 #endif
 	return 0;
 }
@@ -631,7 +637,7 @@
 {
 	int retval;
 
-	DPRINTK("%s: blank:%d\n", __FUNCTION__, blank);
+	DPRINTK("%s: blank:%d\n", __func__, blank);
 	switch (blank) {
 	case FB_BLANK_POWERDOWN:
 	case FB_BLANK_HSYNC_SUSPEND:
@@ -677,13 +683,10 @@
 
 void ps3fb_flip_ctl(int on)
 {
-	if (on) {
-		if (atomic_read(&ps3fb.ext_flip) > 0) {
-			atomic_dec(&ps3fb.ext_flip);
-		}
-	} else {
+	if (on)
+		atomic_dec_if_positive(&ps3fb.ext_flip);
+	else
 		atomic_inc(&ps3fb.ext_flip);
-	}
 }
 
 EXPORT_SYMBOL_GPL(ps3fb_flip_ctl);
@@ -732,6 +735,11 @@
 			if (copy_from_user(&val, argp, sizeof(val)))
 				break;
 
+			if (!(val & PS3AV_MODE_MASK)) {
+				u32 id = ps3av_get_auto_mode(0);
+				if (id > 0)
+					val = (val & ~PS3AV_MODE_MASK) | id;
+			}
 			DPRINTK("PS3FB_IOCTL_SETMODE:%x\n", val);
 			retval = -EINVAL;
 			old_mode = ps3fb_mode;
@@ -783,8 +791,7 @@
 
 	case PS3FB_IOCTL_OFF:
 		DPRINTK("PS3FB_IOCTL_OFF:\n");
-		if (atomic_read(&ps3fb.ext_flip) > 0)
-			atomic_dec(&ps3fb.ext_flip);
+		atomic_dec_if_positive(&ps3fb.ext_flip);
 		retval = 0;
 		break;
 
@@ -805,11 +812,14 @@
 
 static int ps3fbd(void *arg)
 {
-	daemonize("ps3fbd");
-	for (;;) {
-		down(&ps3fb.sem);
-		if (atomic_read(&ps3fb.ext_flip) == 0)
+	while (!kthread_should_stop()) {
+		try_to_freeze();
+		set_current_state(TASK_INTERRUPTIBLE);
+		if (ps3fb.is_kicked) {
+			ps3fb.is_kicked = 0;
 			ps3fb_sync(0);	/* single buffer */
+		}
+		schedule();
 	}
 	return 0;
 }
@@ -823,15 +833,18 @@
 	status = lv1_gpu_context_intr(ps3fb.context_handle, &v1);
 	if (status) {
 		printk(KERN_ERR "%s: lv1_gpu_context_intr failed: %d\n",
-		       __FUNCTION__, status);
+		       __func__, status);
 		return IRQ_NONE;
 	}
 
 	if (v1 & (1 << GPU_INTR_STATUS_VSYNC_1)) {
 		/* VSYNC */
 		ps3fb.vblank_count = head->vblank_count;
-		if (!ps3fb.is_blanked)
-			up(&ps3fb.sem);
+		if (ps3fb.task && !ps3fb.is_blanked &&
+		    !atomic_read(&ps3fb.ext_flip)) {
+			ps3fb.is_kicked = 1;
+			wake_up_process(ps3fb.task);
+		}
 		wake_up_interruptible(&ps3fb.wait_vsync);
 	}
 
@@ -879,7 +892,7 @@
 		dinfo->nvcore_frequency/1000000, dinfo->memory_frequency/1000000);
 
 	if (dinfo->version_driver != GPU_DRIVER_INFO_VERSION) {
-		printk(KERN_ERR "%s: version_driver err:%x\n", __FUNCTION__,
+		printk(KERN_ERR "%s: version_driver err:%x\n", __func__,
 		       dinfo->version_driver);
 		return -EINVAL;
 	}
@@ -888,7 +901,7 @@
 	error = ps3_alloc_irq(PS3_BINDING_CPU_ANY, dinfo->irq.irq_outlet,
 			      &ps3fb.irq_no);
 	if (error) {
-		printk(KERN_ERR "%s: ps3_alloc_irq failed %d\n", __FUNCTION__,
+		printk(KERN_ERR "%s: ps3_alloc_irq failed %d\n", __func__,
 		       error);
 		return error;
 	}
@@ -896,7 +909,7 @@
 	error = request_irq(ps3fb.irq_no, ps3fb_vsync_interrupt, IRQF_DISABLED,
 			    "ps3fb vsync", ps3fb.dev);
 	if (error) {
-		printk(KERN_ERR "%s: request_irq failed %d\n", __FUNCTION__,
+		printk(KERN_ERR "%s: request_irq failed %d\n", __func__,
 		       error);
 		ps3_free_irq(ps3fb.irq_no);
 		return error;
@@ -915,7 +928,7 @@
 				       xdr_lpar, ps3fb_videomemory.size, 0);
 	if (status) {
 		printk(KERN_ERR "%s: lv1_gpu_context_iomap failed: %d\n",
-		       __FUNCTION__, status);
+		       __func__, status);
 		return -ENXIO;
 	}
 	DPRINTK("video:%p xdr_ea:%p ioif:%lx lpar:%lx phys:%lx size:%lx\n",
@@ -927,8 +940,9 @@
 					   xdr_lpar, ps3fb_videomemory.size,
 					   GPU_IOIF, 0);
 	if (status) {
-		printk(KERN_ERR "%s: lv1_gpu_context_attribute FB_SETUP failed: %d\n",
-		       __FUNCTION__, status);
+		printk(KERN_ERR
+		       "%s: lv1_gpu_context_attribute FB_SETUP failed: %d\n",
+		       __func__, status);
 		return -ENXIO;
 	}
 	return 0;
@@ -968,13 +982,14 @@
 	u64 xdr_lpar;
 	int status;
 	unsigned long offset;
+	struct task_struct *task;
 
 	/* get gpu context handle */
 	status = lv1_gpu_memory_allocate(DDR_SIZE, 0, 0, 0, 0,
 					 &ps3fb.memory_handle, &ddr_lpar);
 	if (status) {
 		printk(KERN_ERR "%s: lv1_gpu_memory_allocate failed: %d\n",
-		       __FUNCTION__, status);
+		       __func__, status);
 		goto err;
 	}
 	DPRINTK("ddr:lpar:0x%lx\n", ddr_lpar);
@@ -985,14 +1000,14 @@
 					  &lpar_reports, &lpar_reports_size);
 	if (status) {
 		printk(KERN_ERR "%s: lv1_gpu_context_attribute failed: %d\n",
-		       __FUNCTION__, status);
+		       __func__, status);
 		goto err_gpu_memory_free;
 	}
 
 	/* vsync interrupt */
 	ps3fb.dinfo = ioremap(lpar_driver_info, 128 * 1024);
 	if (!ps3fb.dinfo) {
-		printk(KERN_ERR "%s: ioremap failed\n", __FUNCTION__);
+		printk(KERN_ERR "%s: ioremap failed\n", __func__);
 		goto err_gpu_context_free;
 	}
 
@@ -1050,9 +1065,18 @@
 	       "fb%d: PS3 frame buffer device, using %ld KiB of video memory\n",
 	       info->node, ps3fb_videomemory.size >> 10);
 
-	kernel_thread(ps3fbd, info, CLONE_KERNEL);
+	task = kthread_run(ps3fbd, info, "ps3fbd");
+	if (IS_ERR(task)) {
+		retval = PTR_ERR(task);
+		goto err_unregister_framebuffer;
+	}
+
+	ps3fb.task = task;
+
 	return 0;
 
+err_unregister_framebuffer:
+	unregister_framebuffer(info);
 err_fb_dealloc:
 	fb_dealloc_cmap(&info->cmap);
 err_framebuffer_release:
@@ -1083,6 +1107,11 @@
 {
 	int status;
 
+	if (ps3fb.task) {
+		struct task_struct *task = ps3fb.task;
+		ps3fb.task = NULL;
+		kthread_stop(task);
+	}
 	if (ps3fb.irq_no) {
 		free_irq(ps3fb.irq_no, ps3fb.dev);
 		ps3_free_irq(ps3fb.irq_no);
@@ -1137,8 +1166,9 @@
 					   L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC,
 					   0, L1GPU_DISPLAY_SYNC_VSYNC, 0, 0);
 	if (status) {
-		printk(KERN_ERR "%s: lv1_gpu_context_attribute DISPLAY_SYNC failed: %d\n",
-		       __FUNCTION__, status);
+		printk(KERN_ERR
+		       "%s: lv1_gpu_context_attribute DISPLAY_SYNC failed: %d\n",
+		       __func__, status);
 		return -1;
 	}
 #endif
@@ -1148,8 +1178,9 @@
 					   1, L1GPU_DISPLAY_SYNC_VSYNC, 0, 0);
 
 	if (status) {
-		printk(KERN_ERR "%s: lv1_gpu_context_attribute DISPLAY_MODE failed: %d\n",
-		       __FUNCTION__, status);
+		printk(KERN_ERR
+		       "%s: lv1_gpu_context_attribute DISPLAY_MODE failed: %d\n",
+		       __func__, status);
 		return -1;
 	}
 #endif
@@ -1174,7 +1205,7 @@
 
 	error = ps3av_dev_open();
 	if (error) {
-		printk(KERN_ERR "%s: ps3av_dev_open failed\n", __FUNCTION__);
+		printk(KERN_ERR "%s: ps3av_dev_open failed\n", __func__);
 		goto err;
 	}
 
@@ -1195,7 +1226,6 @@
 
 	atomic_set(&ps3fb.f_count, -1);	/* fbcon opens ps3fb */
 	atomic_set(&ps3fb.ext_flip, 0);	/* for flip with vsync */
-	init_MUTEX(&ps3fb.sem);
 	init_waitqueue_head(&ps3fb.wait_vsync);
 	ps3fb.num_frames = 1;
 
diff --git a/drivers/video/stifb.c b/drivers/video/stifb.c
index 69f3b26..c97709e 100644
--- a/drivers/video/stifb.c
+++ b/drivers/video/stifb.c
@@ -64,7 +64,6 @@
 #include <linux/fb.h>
 #include <linux/init.h>
 #include <linux/ioport.h>
-#include <linux/pci.h>
 
 #include <asm/grfioctl.h>	/* for HP-UX compatibility */
 #include <asm/uaccess.h>
diff --git a/drivers/video/valkyriefb.c b/drivers/video/valkyriefb.c
index 06fc19a..ad66f07 100644
--- a/drivers/video/valkyriefb.c
+++ b/drivers/video/valkyriefb.c
@@ -51,7 +51,6 @@
 #include <linux/fb.h>
 #include <linux/selection.h>
 #include <linux/init.h>
-#include <linux/pci.h>
 #include <linux/nvram.h>
 #include <linux/adb.h>
 #include <linux/cuda.h>
diff --git a/drivers/zorro/proc.c b/drivers/zorro/proc.c
index b3ce885..2ce4ceb 100644
--- a/drivers/zorro/proc.c
+++ b/drivers/zorro/proc.c
@@ -90,8 +90,9 @@
 	for (slot = cnt = 0; slot < zorro_num_autocon && count > cnt; slot++) {
 		struct zorro_dev *z = &zorro_autocon[slot];
 		len = sprintf(buf, "%02x\t%08x\t%08lx\t%08lx\t%02x\n", slot,
-			      z->id, zorro_resource_start(z),
-			      zorro_resource_len(z), z->rom.er_Type);
+			      z->id, (unsigned long)zorro_resource_start(z),
+			      (unsigned long)zorro_resource_len(z),
+			      z->rom.er_Type);
 		at += len;
 		if (at >= pos) {
 			if (!*start) {
diff --git a/drivers/zorro/zorro-sysfs.c b/drivers/zorro/zorro-sysfs.c
index 87c29d7..c3ba0ec 100644
--- a/drivers/zorro/zorro-sysfs.c
+++ b/drivers/zorro/zorro-sysfs.c
@@ -42,7 +42,8 @@
 	struct zorro_dev *z = to_zorro_dev(dev);
 
 	return sprintf(buf, "0x%08lx 0x%08lx 0x%08lx\n",
-		       zorro_resource_start(z), zorro_resource_end(z),
+		       (unsigned long)zorro_resource_start(z),
+		       (unsigned long)zorro_resource_end(z),
 		       zorro_resource_flags(z));
 }
 
diff --git a/drivers/zorro/zorro.c b/drivers/zorro/zorro.c
index 0f2b406..4cc42b6 100644
--- a/drivers/zorro/zorro.c
+++ b/drivers/zorro/zorro.c
@@ -164,7 +164,8 @@
 	if (request_resource(zorro_find_parent_resource(z), &z->resource))
 	    printk(KERN_ERR "Zorro: Address space collision on device %s "
 		   "[%lx:%lx]\n",
-		   z->name, zorro_resource_start(z), zorro_resource_end(z));
+		   z->name, (unsigned long)zorro_resource_start(z),
+		   (unsigned long)zorro_resource_end(z));
 	sprintf(z->dev.bus_id, "%02x", i);
 	z->dev.parent = &zorro_bus.dev;
 	z->dev.bus = &zorro_bus_type;
diff --git a/fs/Kconfig b/fs/Kconfig
index a42f767..8ea7b04 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -1734,6 +1734,18 @@
 config SUNRPC_GSS
 	tristate
 
+config SUNRPC_BIND34
+	bool "Support for rpcbind versions 3 & 4 (EXPERIMENTAL)"
+	depends on SUNRPC && EXPERIMENTAL
+	help
+	  Provides kernel support for querying rpcbind servers via versions 3
+	  and 4 of the rpcbind protocol.  The kernel automatically falls back
+	  to version 2 if a remote rpcbind service does not support versions
+	  3 or 4.
+
+	  If unsure, say N to get traditional behavior (version 2 rpcbind
+	  requests only).
+
 config RPCSEC_GSS_KRB5
 	tristate "Secure RPC: Kerberos V mechanism (EXPERIMENTAL)"
 	depends on SUNRPC && EXPERIMENTAL
@@ -2020,7 +2032,6 @@
 	tristate "Andrew File System support (AFS) (EXPERIMENTAL)"
 	depends on INET && EXPERIMENTAL
 	select AF_RXRPC
-	select KEYS
 	help
 	  If you say Y here, you will get an experimental Andrew File System
 	  driver. It currently only supports unsecured read-only AFS access.
diff --git a/fs/afs/Makefile b/fs/afs/Makefile
index 01545eb..cf83e5d 100644
--- a/fs/afs/Makefile
+++ b/fs/afs/Makefile
@@ -18,7 +18,7 @@
 	security.o \
 	server.o \
 	super.o \
-	use-rtnetlink.o \
+	netdevices.o \
 	vlclient.o \
 	vlocation.o \
 	vnode.o \
diff --git a/fs/afs/callback.c b/fs/afs/callback.c
index 639399f..9bdbf36 100644
--- a/fs/afs/callback.c
+++ b/fs/afs/callback.c
@@ -468,7 +468,7 @@
 /*
  * shut down the callback update process
  */
-void __exit afs_callback_update_kill(void)
+void afs_callback_update_kill(void)
 {
 	destroy_workqueue(afs_callback_update_worker);
 }
diff --git a/fs/afs/cmservice.c b/fs/afs/cmservice.c
index 6685f4c..d5b2ad6 100644
--- a/fs/afs/cmservice.c
+++ b/fs/afs/cmservice.c
@@ -443,6 +443,7 @@
 			reply.ia.netmask[loop] = ifs[loop].netmask.s_addr;
 			reply.ia.mtu[loop] = htonl(ifs[loop].mtu);
 		}
+		kfree(ifs);
 	}
 
 	reply.cap.capcount = htonl(1);
diff --git a/fs/afs/fsclient.c b/fs/afs/fsclient.c
index 2393d2a..e54e6c2 100644
--- a/fs/afs/fsclient.c
+++ b/fs/afs/fsclient.c
@@ -266,7 +266,8 @@
 		call->unmarshall++;
 
 		if (call->count < PAGE_SIZE) {
-			buffer = kmap_atomic(call->reply3, KM_USER0);
+			page = call->reply3;
+			buffer = kmap_atomic(page, KM_USER0);
 			memset(buffer + PAGE_SIZE - call->count, 0,
 			       call->count);
 			kunmap_atomic(buffer, KM_USER0);
diff --git a/fs/afs/internal.h b/fs/afs/internal.h
index 34665f7..d90c158 100644
--- a/fs/afs/internal.h
+++ b/fs/afs/internal.h
@@ -349,7 +349,6 @@
  * record of one of a system's set of network interfaces
  */
 struct afs_interface {
-	unsigned	index;		/* interface index */
 	struct in_addr	address;	/* IPv4 address bound to interface */
 	struct in_addr	netmask;	/* netmask applied to address */
 	unsigned	mtu;		/* MTU of interface */
@@ -392,7 +391,7 @@
 extern void afs_dispatch_give_up_callbacks(struct work_struct *);
 extern void afs_flush_callback_breaks(struct afs_server *);
 extern int __init afs_callback_update_init(void);
-extern void __exit afs_callback_update_kill(void);
+extern void afs_callback_update_kill(void);
 
 /*
  * cell.c
@@ -564,7 +563,7 @@
  * use-rtnetlink.c
  */
 extern int afs_get_ipv4_interfaces(struct afs_interface *, size_t, bool);
-extern int afs_get_MAC_address(u8 [6]);
+extern int afs_get_MAC_address(u8 *, size_t);
 
 /*
  * vlclient.c
@@ -591,7 +590,7 @@
 						  struct key *,
 						  const char *, size_t);
 extern void afs_put_vlocation(struct afs_vlocation *);
-extern void __exit afs_vlocation_purge(void);
+extern void afs_vlocation_purge(void);
 
 /*
  * vnode.c
diff --git a/fs/afs/main.c b/fs/afs/main.c
index 40c2704..80ec6fd 100644
--- a/fs/afs/main.c
+++ b/fs/afs/main.c
@@ -54,7 +54,7 @@
 
 	/* read the MAC address of one of the external interfaces and construct
 	 * a UUID from it */
-	ret = afs_get_MAC_address(afs_uuid.node);
+	ret = afs_get_MAC_address(afs_uuid.node, sizeof(afs_uuid.node));
 	if (ret < 0)
 		return ret;
 
diff --git a/fs/afs/netdevices.c b/fs/afs/netdevices.c
new file mode 100644
index 0000000..fc27d4b
--- /dev/null
+++ b/fs/afs/netdevices.c
@@ -0,0 +1,68 @@
+/* AFS network device helpers
+ *
+ * Copyright (c) 2007 Patrick McHardy <kaber@trash.net>
+ */
+
+#include <linux/string.h>
+#include <linux/rtnetlink.h>
+#include <linux/inetdevice.h>
+#include <linux/netdevice.h>
+#include <linux/if_arp.h>
+#include "internal.h"
+
+/*
+ * get a MAC address from a random ethernet interface that has a real one
+ * - the buffer will normally be 6 bytes in size
+ */
+int afs_get_MAC_address(u8 *mac, size_t maclen)
+{
+	struct net_device *dev;
+	int ret = -ENODEV;
+
+	if (maclen != ETH_ALEN)
+		BUG();
+
+	rtnl_lock();
+	dev = __dev_getfirstbyhwtype(ARPHRD_ETHER);
+	if (dev) {
+		memcpy(mac, dev->dev_addr, maclen);
+		ret = 0;
+	}
+	rtnl_unlock();
+	return ret;
+}
+
+/*
+ * get a list of this system's interface IPv4 addresses, netmasks and MTUs
+ * - maxbufs must be at least 1
+ * - returns the number of interface records in the buffer
+ */
+int afs_get_ipv4_interfaces(struct afs_interface *bufs, size_t maxbufs,
+			    bool wantloopback)
+{
+	struct net_device *dev;
+	struct in_device *idev;
+	int n = 0;
+
+	ASSERT(maxbufs > 0);
+
+	rtnl_lock();
+	for_each_netdev(dev) {
+		if (dev->type == ARPHRD_LOOPBACK && !wantloopback)
+			continue;
+		idev = __in_dev_get_rtnl(dev);
+		if (!idev)
+			continue;
+		for_primary_ifa(idev) {
+			bufs[n].address.s_addr = ifa->ifa_address;
+			bufs[n].netmask.s_addr = ifa->ifa_mask;
+			bufs[n].mtu = dev->mtu;
+			n++;
+			if (n >= maxbufs)
+				goto out;
+		} endfor_ifa(idev);
+	}
+out:
+	rtnl_unlock();
+	return n;
+}
diff --git a/fs/afs/super.c b/fs/afs/super.c
index cebd03c..41173f8 100644
--- a/fs/afs/super.c
+++ b/fs/afs/super.c
@@ -20,6 +20,7 @@
 #include <linux/slab.h>
 #include <linux/fs.h>
 #include <linux/pagemap.h>
+#include <linux/parser.h>
 #include "internal.h"
 
 #define AFS_FS_MAGIC 0x6B414653 /* 'kAFS' */
@@ -42,7 +43,7 @@
 	.name		= "afs",
 	.get_sb		= afs_get_sb,
 	.kill_sb	= kill_anon_super,
-	.fs_flags	= FS_BINARY_MOUNTDATA,
+	.fs_flags	= 0,
 };
 
 static const struct super_operations afs_super_ops = {
@@ -58,6 +59,20 @@
 static struct kmem_cache *afs_inode_cachep;
 static atomic_t afs_count_active_inodes;
 
+enum {
+	afs_no_opt,
+	afs_opt_cell,
+	afs_opt_rwpath,
+	afs_opt_vol,
+};
+
+static const match_table_t afs_options_list = {
+	{ afs_opt_cell,		"cell=%s"	},
+	{ afs_opt_rwpath,	"rwpath"	},
+	{ afs_opt_vol,		"vol=%s"	},
+	{ afs_no_opt,		NULL		},
+};
+
 /*
  * initialise the filesystem
  */
@@ -115,31 +130,6 @@
 }
 
 /*
- * check that an argument has a value
- */
-static int want_arg(char **_value, const char *option)
-{
-	if (!_value || !*_value || !**_value) {
-		printk(KERN_NOTICE "kAFS: %s: argument missing\n", option);
-		return 0;
-	}
-	return 1;
-}
-
-/*
- * check that there's no subsequent value
- */
-static int want_no_value(char *const *_value, const char *option)
-{
-	if (*_value && **_value) {
-		printk(KERN_NOTICE "kAFS: %s: Invalid argument: %s\n",
-		       option, *_value);
-		return 0;
-	}
-	return 1;
-}
-
-/*
  * parse the mount options
  * - this function has been shamelessly adapted from the ext3 fs which
  *   shamelessly adapted it from the msdos fs
@@ -148,48 +138,46 @@
 			     char *options, const char **devname)
 {
 	struct afs_cell *cell;
-	char *key, *value;
-	int ret;
+	substring_t args[MAX_OPT_ARGS];
+	char *p;
+	int token;
 
 	_enter("%s", options);
 
 	options[PAGE_SIZE - 1] = 0;
 
-	ret = 0;
-	while ((key = strsep(&options, ","))) {
-		value = strchr(key, '=');
-		if (value)
-			*value++ = 0;
+	while ((p = strsep(&options, ","))) {
+		if (!*p)
+			continue;
 
-		_debug("kAFS: KEY: %s, VAL:%s", key, value ?: "-");
-
-		if (strcmp(key, "rwpath") == 0) {
-			if (!want_no_value(&value, "rwpath"))
-				return -EINVAL;
-			params->rwpath = 1;
-		} else if (strcmp(key, "vol") == 0) {
-			if (!want_arg(&value, "vol"))
-				return -EINVAL;
-			*devname = value;
-		} else if (strcmp(key, "cell") == 0) {
-			if (!want_arg(&value, "cell"))
-				return -EINVAL;
-			cell = afs_cell_lookup(value, strlen(value));
+		token = match_token(p, afs_options_list, args);
+		switch (token) {
+		case afs_opt_cell:
+			cell = afs_cell_lookup(args[0].from,
+					       args[0].to - args[0].from);
 			if (IS_ERR(cell))
 				return PTR_ERR(cell);
 			afs_put_cell(params->cell);
 			params->cell = cell;
-		} else {
-			printk("kAFS: Unknown mount option: '%s'\n",  key);
-			ret = -EINVAL;
-			goto error;
+			break;
+
+		case afs_opt_rwpath:
+			params->rwpath = 1;
+			break;
+
+		case afs_opt_vol:
+			*devname = args[0].from;
+			break;
+
+		default:
+			printk(KERN_ERR "kAFS:"
+			       " Unknown or invalid mount option: '%s'\n", p);
+			return -EINVAL;
 		}
 	}
 
-	ret = 0;
-error:
-	_leave(" = %d", ret);
-	return ret;
+	_leave(" = 0");
+	return 0;
 }
 
 /*
@@ -361,7 +349,6 @@
 
 /*
  * get an AFS superblock
- * - TODO: don't use get_sb_nodev(), but rather call sget() directly
  */
 static int afs_get_sb(struct file_system_type *fs_type,
 		      int flags,
@@ -386,7 +373,6 @@
 			goto error;
 	}
 
-
 	ret = afs_parse_device_name(&params, dev_name);
 	if (ret < 0)
 		goto error;
diff --git a/fs/afs/use-rtnetlink.c b/fs/afs/use-rtnetlink.c
deleted file mode 100644
index f8991c7..0000000
--- a/fs/afs/use-rtnetlink.c
+++ /dev/null
@@ -1,473 +0,0 @@
-/* RTNETLINK client
- *
- * Copyright (C) 2007 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/netlink.h>
-#include <linux/rtnetlink.h>
-#include <linux/if_addr.h>
-#include <linux/if_arp.h>
-#include <linux/inetdevice.h>
-#include <net/netlink.h>
-#include "internal.h"
-
-struct afs_rtm_desc {
-	struct socket		*nlsock;
-	struct afs_interface	*bufs;
-	u8			*mac;
-	size_t			nbufs;
-	size_t			maxbufs;
-	void			*data;
-	ssize_t			datalen;
-	size_t			datamax;
-	int			msg_seq;
-	unsigned		mac_index;
-	bool			wantloopback;
-	int (*parse)(struct afs_rtm_desc *, struct nlmsghdr *);
-};
-
-/*
- * parse an RTM_GETADDR response
- */
-static int afs_rtm_getaddr_parse(struct afs_rtm_desc *desc,
-				 struct nlmsghdr *nlhdr)
-{
-	struct afs_interface *this;
-	struct ifaddrmsg *ifa;
-	struct rtattr *rtattr;
-	const char *name;
-	size_t len;
-
-	ifa = (struct ifaddrmsg *) NLMSG_DATA(nlhdr);
-
-	_enter("{ix=%d,af=%d}", ifa->ifa_index, ifa->ifa_family);
-
-	if (ifa->ifa_family != AF_INET) {
-		_leave(" = 0 [family %d]", ifa->ifa_family);
-		return 0;
-	}
-	if (desc->nbufs >= desc->maxbufs) {
-		_leave(" = 0 [max %zu/%zu]", desc->nbufs, desc->maxbufs);
-		return 0;
-	}
-
-	this = &desc->bufs[desc->nbufs];
-
-	this->index = ifa->ifa_index;
-	this->netmask.s_addr = inet_make_mask(ifa->ifa_prefixlen);
-	this->mtu = 0;
-
-	rtattr = NLMSG_DATA(nlhdr) + NLMSG_ALIGN(sizeof(struct ifaddrmsg));
-	len = NLMSG_PAYLOAD(nlhdr, sizeof(struct ifaddrmsg));
-
-	name = "unknown";
-	for (; RTA_OK(rtattr, len); rtattr = RTA_NEXT(rtattr, len)) {
-		switch (rtattr->rta_type) {
-		case IFA_ADDRESS:
-			memcpy(&this->address, RTA_DATA(rtattr), 4);
-			break;
-		case IFA_LABEL:
-			name = RTA_DATA(rtattr);
-			break;
-		}
-	}
-
-	_debug("%s: "NIPQUAD_FMT"/"NIPQUAD_FMT,
-	       name, NIPQUAD(this->address), NIPQUAD(this->netmask));
-
-	desc->nbufs++;
-	_leave(" = 0");
-	return 0;
-}
-
-/*
- * parse an RTM_GETLINK response for MTUs
- */
-static int afs_rtm_getlink_if_parse(struct afs_rtm_desc *desc,
-				    struct nlmsghdr *nlhdr)
-{
-	struct afs_interface *this;
-	struct ifinfomsg *ifi;
-	struct rtattr *rtattr;
-	const char *name;
-	size_t len, loop;
-
-	ifi = (struct ifinfomsg *) NLMSG_DATA(nlhdr);
-
-	_enter("{ix=%d}", ifi->ifi_index);
-
-	for (loop = 0; loop < desc->nbufs; loop++) {
-		this = &desc->bufs[loop];
-		if (this->index == ifi->ifi_index)
-			goto found;
-	}
-
-	_leave(" = 0 [no match]");
-	return 0;
-
-found:
-	if (ifi->ifi_type == ARPHRD_LOOPBACK && !desc->wantloopback) {
-		_leave(" = 0 [loopback]");
-		return 0;
-	}
-
-	rtattr = NLMSG_DATA(nlhdr) + NLMSG_ALIGN(sizeof(struct ifinfomsg));
-	len = NLMSG_PAYLOAD(nlhdr, sizeof(struct ifinfomsg));
-
-	name = "unknown";
-	for (; RTA_OK(rtattr, len); rtattr = RTA_NEXT(rtattr, len)) {
-		switch (rtattr->rta_type) {
-		case IFLA_MTU:
-			memcpy(&this->mtu, RTA_DATA(rtattr), 4);
-			break;
-		case IFLA_IFNAME:
-			name = RTA_DATA(rtattr);
-			break;
-		}
-	}
-
-	_debug("%s: "NIPQUAD_FMT"/"NIPQUAD_FMT" mtu %u",
-	       name, NIPQUAD(this->address), NIPQUAD(this->netmask),
-	       this->mtu);
-
-	_leave(" = 0");
-	return 0;
-}
-
-/*
- * parse an RTM_GETLINK response for the MAC address belonging to the lowest
- * non-internal interface
- */
-static int afs_rtm_getlink_mac_parse(struct afs_rtm_desc *desc,
-				     struct nlmsghdr *nlhdr)
-{
-	struct ifinfomsg *ifi;
-	struct rtattr *rtattr;
-	const char *name;
-	size_t remain, len;
-	bool set;
-
-	ifi = (struct ifinfomsg *) NLMSG_DATA(nlhdr);
-
-	_enter("{ix=%d}", ifi->ifi_index);
-
-	if (ifi->ifi_index >= desc->mac_index) {
-		_leave(" = 0 [high]");
-		return 0;
-	}
-	if (ifi->ifi_type == ARPHRD_LOOPBACK) {
-		_leave(" = 0 [loopback]");
-		return 0;
-	}
-
-	rtattr = NLMSG_DATA(nlhdr) + NLMSG_ALIGN(sizeof(struct ifinfomsg));
-	remain = NLMSG_PAYLOAD(nlhdr, sizeof(struct ifinfomsg));
-
-	name = "unknown";
-	set = false;
-	for (; RTA_OK(rtattr, remain); rtattr = RTA_NEXT(rtattr, remain)) {
-		switch (rtattr->rta_type) {
-		case IFLA_ADDRESS:
-			len = RTA_PAYLOAD(rtattr);
-			memcpy(desc->mac, RTA_DATA(rtattr),
-			       min_t(size_t, len, 6));
-			desc->mac_index = ifi->ifi_index;
-			set = true;
-			break;
-		case IFLA_IFNAME:
-			name = RTA_DATA(rtattr);
-			break;
-		}
-	}
-
-	if (set)
-		_debug("%s: %02x:%02x:%02x:%02x:%02x:%02x",
-		       name,
-		       desc->mac[0], desc->mac[1], desc->mac[2],
-		       desc->mac[3], desc->mac[4], desc->mac[5]);
-
-	_leave(" = 0");
-	return 0;
-}
-
-/*
- * read the rtnetlink response and pass to parsing routine
- */
-static int afs_read_rtm(struct afs_rtm_desc *desc)
-{
-	struct nlmsghdr *nlhdr, tmphdr;
-	struct msghdr msg;
-	struct kvec iov[1];
-	void *data;
-	bool last = false;
-	int len, ret, remain;
-
-	_enter("");
-
-	do {
-		/* first of all peek to see how big the packet is */
-		memset(&msg, 0, sizeof(msg));
-		iov[0].iov_base = &tmphdr;
-		iov[0].iov_len = sizeof(tmphdr);
-		len = kernel_recvmsg(desc->nlsock, &msg, iov, 1,
-				     sizeof(tmphdr), MSG_PEEK | MSG_TRUNC);
-		if (len < 0) {
-			_leave(" = %d [peek]", len);
-			return len;
-		}
-		if (len == 0)
-			continue;
-		if (len < sizeof(tmphdr) || len < NLMSG_PAYLOAD(&tmphdr, 0)) {
-			_leave(" = -EMSGSIZE");
-			return -EMSGSIZE;
-		}
-
-		if (desc->datamax < len) {
-			kfree(desc->data);
-			desc->data = NULL;
-			data = kmalloc(len, GFP_KERNEL);
-			if (!data)
-				return -ENOMEM;
-			desc->data = data;
-		}
-		desc->datamax = len;
-
-		/* read all the data from this packet */
-		iov[0].iov_base = desc->data;
-		iov[0].iov_len = desc->datamax;
-		desc->datalen = kernel_recvmsg(desc->nlsock, &msg, iov, 1,
-					       desc->datamax, 0);
-		if (desc->datalen < 0) {
-			_leave(" = %zd [recv]", desc->datalen);
-			return desc->datalen;
-		}
-
-		nlhdr = desc->data;
-
-		/* check if the header is valid */
-		if (!NLMSG_OK(nlhdr, desc->datalen) ||
-		    nlhdr->nlmsg_type == NLMSG_ERROR) {
-			_leave(" = -EIO");
-			return -EIO;
-		}
-
-		/* see if this is the last message */
-		if (nlhdr->nlmsg_type == NLMSG_DONE ||
-		    !(nlhdr->nlmsg_flags & NLM_F_MULTI))
-			last = true;
-
-		/* parse the bits we got this time */
-		nlmsg_for_each_msg(nlhdr, desc->data, desc->datalen, remain) {
-			ret = desc->parse(desc, nlhdr);
-			if (ret < 0) {
-				_leave(" = %d [parse]", ret);
-				return ret;
-			}
-		}
-
-	} while (!last);
-
-	_leave(" = 0");
-	return 0;
-}
-
-/*
- * list the interface bound addresses to get the address and netmask
- */
-static int afs_rtm_getaddr(struct afs_rtm_desc *desc)
-{
-	struct msghdr msg;
-	struct kvec iov[1];
-	int ret;
-
-	struct {
-		struct nlmsghdr nl_msg __attribute__((aligned(NLMSG_ALIGNTO)));
-		struct ifaddrmsg addr_msg __attribute__((aligned(NLMSG_ALIGNTO)));
-	} request;
-
-	_enter("");
-
-	memset(&request, 0, sizeof(request));
-
-	request.nl_msg.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
-	request.nl_msg.nlmsg_type = RTM_GETADDR;
-	request.nl_msg.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
-	request.nl_msg.nlmsg_seq = desc->msg_seq++;
-	request.nl_msg.nlmsg_pid = 0;
-
-	memset(&msg, 0, sizeof(msg));
-	iov[0].iov_base = &request;
-	iov[0].iov_len = sizeof(request);
-
-	ret = kernel_sendmsg(desc->nlsock, &msg, iov, 1, iov[0].iov_len);
-	_leave(" = %d", ret);
-	return ret;
-}
-
-/*
- * list the interface link statuses to get the MTUs
- */
-static int afs_rtm_getlink(struct afs_rtm_desc *desc)
-{
-	struct msghdr msg;
-	struct kvec iov[1];
-	int ret;
-
-	struct {
-		struct nlmsghdr nl_msg __attribute__((aligned(NLMSG_ALIGNTO)));
-		struct ifinfomsg link_msg __attribute__((aligned(NLMSG_ALIGNTO)));
-	} request;
-
-	_enter("");
-
-	memset(&request, 0, sizeof(request));
-
-	request.nl_msg.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
-	request.nl_msg.nlmsg_type = RTM_GETLINK;
-	request.nl_msg.nlmsg_flags = NLM_F_REQUEST | NLM_F_ROOT;
-	request.nl_msg.nlmsg_seq = desc->msg_seq++;
-	request.nl_msg.nlmsg_pid = 0;
-
-	memset(&msg, 0, sizeof(msg));
-	iov[0].iov_base = &request;
-	iov[0].iov_len = sizeof(request);
-
-	ret = kernel_sendmsg(desc->nlsock, &msg, iov, 1, iov[0].iov_len);
-	_leave(" = %d", ret);
-	return ret;
-}
-
-/*
- * cull any interface records for which there isn't an MTU value
- */
-static void afs_cull_interfaces(struct afs_rtm_desc *desc)
-{
-	struct afs_interface *bufs = desc->bufs;
-	size_t nbufs = desc->nbufs;
-	int loop, point = 0;
-
-	_enter("{%zu}", nbufs);
-
-	for (loop = 0; loop < nbufs; loop++) {
-		if (desc->bufs[loop].mtu != 0) {
-			if (loop != point) {
-				ASSERTCMP(loop, >, point);
-				bufs[point] = bufs[loop];
-			}
-			point++;
-		}
-	}
-
-	desc->nbufs = point;
-	_leave(" [%zu/%zu]", desc->nbufs, nbufs);
-}
-
-/*
- * get a list of this system's interface IPv4 addresses, netmasks and MTUs
- * - returns the number of interface records in the buffer
- */
-int afs_get_ipv4_interfaces(struct afs_interface *bufs, size_t maxbufs,
-			    bool wantloopback)
-{
-	struct afs_rtm_desc desc;
-	int ret, loop;
-
-	_enter("");
-
-	memset(&desc, 0, sizeof(desc));
-	desc.bufs = bufs;
-	desc.maxbufs = maxbufs;
-	desc.wantloopback = wantloopback;
-
-	ret = sock_create_kern(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE,
-			       &desc.nlsock);
-	if (ret < 0) {
-		_leave(" = %d [sock]", ret);
-		return ret;
-	}
-
-	/* issue RTM_GETADDR */
-	desc.parse = afs_rtm_getaddr_parse;
-	ret = afs_rtm_getaddr(&desc);
-	if (ret < 0)
-		goto error;
-	ret = afs_read_rtm(&desc);
-	if (ret < 0)
-		goto error;
-
-	/* issue RTM_GETLINK */
-	desc.parse = afs_rtm_getlink_if_parse;
-	ret = afs_rtm_getlink(&desc);
-	if (ret < 0)
-		goto error;
-	ret = afs_read_rtm(&desc);
-	if (ret < 0)
-		goto error;
-
-	afs_cull_interfaces(&desc);
-	ret = desc.nbufs;
-
-	for (loop = 0; loop < ret; loop++)
-		_debug("[%d] "NIPQUAD_FMT"/"NIPQUAD_FMT" mtu %u",
-		       bufs[loop].index,
-		       NIPQUAD(bufs[loop].address),
-		       NIPQUAD(bufs[loop].netmask),
-		       bufs[loop].mtu);
-
-error:
-	kfree(desc.data);
-	sock_release(desc.nlsock);
-	_leave(" = %d", ret);
-	return ret;
-}
-
-/*
- * get a MAC address from a random ethernet interface that has a real one
- * - the buffer should be 6 bytes in size
- */
-int afs_get_MAC_address(u8 mac[6])
-{
-	struct afs_rtm_desc desc;
-	int ret;
-
-	_enter("");
-
-	memset(&desc, 0, sizeof(desc));
-	desc.mac = mac;
-	desc.mac_index = UINT_MAX;
-
-	ret = sock_create_kern(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE,
-			       &desc.nlsock);
-	if (ret < 0) {
-		_leave(" = %d [sock]", ret);
-		return ret;
-	}
-
-	/* issue RTM_GETLINK */
-	desc.parse = afs_rtm_getlink_mac_parse;
-	ret = afs_rtm_getlink(&desc);
-	if (ret < 0)
-		goto error;
-	ret = afs_read_rtm(&desc);
-	if (ret < 0)
-		goto error;
-
-	if (desc.mac_index < UINT_MAX) {
-		/* got a MAC address */
-		_debug("[%d] %02x:%02x:%02x:%02x:%02x:%02x",
-		       desc.mac_index,
-		       mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
-	} else {
-		ret = -ENONET;
-	}
-
-error:
-	sock_release(desc.nlsock);
-	_leave(" = %d", ret);
-	return ret;
-}
diff --git a/fs/afs/vlocation.c b/fs/afs/vlocation.c
index 6c8e95a..3370cdb 100644
--- a/fs/afs/vlocation.c
+++ b/fs/afs/vlocation.c
@@ -602,7 +602,7 @@
 /*
  * discard all the volume location records for rmmod
  */
-void __exit afs_vlocation_purge(void)
+void afs_vlocation_purge(void)
 {
 	afs_vlocation_timeout = 0;
 
diff --git a/fs/configfs/mount.c b/fs/configfs/mount.c
index 6f57300..b00d962 100644
--- a/fs/configfs/mount.c
+++ b/fs/configfs/mount.c
@@ -140,7 +140,7 @@
 	if (!configfs_dir_cachep)
 		goto out;
 
-	kset_set_kset_s(&config_subsys, kernel_subsys);
+	kobj_set_kset_s(&config_subsys, kernel_subsys);
 	err = subsystem_register(&config_subsys);
 	if (err) {
 		kmem_cache_destroy(configfs_dir_cachep);
diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c
index 7b324cf..ec8896b 100644
--- a/fs/debugfs/inode.c
+++ b/fs/debugfs/inode.c
@@ -374,7 +374,7 @@
 {
 	int retval;
 
-	kset_set_kset_s(&debug_subsys, kernel_subsys);
+	kobj_set_kset_s(&debug_subsys, kernel_subsys);
 	retval = subsystem_register(&debug_subsys);
 	if (retval)
 		return retval;
diff --git a/fs/dlm/lockspace.c b/fs/dlm/lockspace.c
index f40817b..8e6ad76 100644
--- a/fs/dlm/lockspace.c
+++ b/fs/dlm/lockspace.c
@@ -167,7 +167,6 @@
 };
 
 static struct kset dlm_kset = {
-	.subsys = &kernel_subsys,
 	.kobj   = {.name = "dlm",},
 	.ktype  = &dlm_ktype,
 };
@@ -218,6 +217,7 @@
 	INIT_LIST_HEAD(&lslist);
 	spin_lock_init(&lslist_lock);
 
+	kobj_set_kset_s(&dlm_kset, kernel_subsys);
 	error = kset_register(&dlm_kset);
 	if (error)
 		printk("dlm_lockspace_init: cannot register kset %d\n", error);
diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c
index fc4a3a2..6acc8f4 100644
--- a/fs/ecryptfs/main.c
+++ b/fs/ecryptfs/main.c
@@ -793,7 +793,7 @@
 		       "Unable to register ecryptfs sysfs subsystem\n");
 		goto out;
 	}
-	rc = sysfs_create_file(&ecryptfs_subsys.kset.kobj,
+	rc = sysfs_create_file(&ecryptfs_subsys.kobj,
 			       &sysfs_attr_version.attr);
 	if (rc) {
 		printk(KERN_ERR
@@ -801,12 +801,12 @@
 		subsystem_unregister(&ecryptfs_subsys);
 		goto out;
 	}
-	rc = sysfs_create_file(&ecryptfs_subsys.kset.kobj,
+	rc = sysfs_create_file(&ecryptfs_subsys.kobj,
 			       &sysfs_attr_version_str.attr);
 	if (rc) {
 		printk(KERN_ERR
 		       "Unable to create ecryptfs version_str attribute\n");
-		sysfs_remove_file(&ecryptfs_subsys.kset.kobj,
+		sysfs_remove_file(&ecryptfs_subsys.kobj,
 				  &sysfs_attr_version.attr);
 		subsystem_unregister(&ecryptfs_subsys);
 		goto out;
@@ -841,7 +841,7 @@
 		ecryptfs_free_kmem_caches();
 		goto out;
 	}
-	kset_set_kset_s(&ecryptfs_subsys, fs_subsys);
+	kobj_set_kset_s(&ecryptfs_subsys, fs_subsys);
 	sysfs_attr_version.attr.owner = THIS_MODULE;
 	sysfs_attr_version_str.attr.owner = THIS_MODULE;
 	rc = do_sysfs_registration();
@@ -862,9 +862,9 @@
 
 static void __exit ecryptfs_exit(void)
 {
-	sysfs_remove_file(&ecryptfs_subsys.kset.kobj,
+	sysfs_remove_file(&ecryptfs_subsys.kobj,
 			  &sysfs_attr_version.attr);
-	sysfs_remove_file(&ecryptfs_subsys.kset.kobj,
+	sysfs_remove_file(&ecryptfs_subsys.kobj,
 			  &sysfs_attr_version_str.attr);
 	subsystem_unregister(&ecryptfs_subsys);
 	ecryptfs_release_messaging(ecryptfs_transport);
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index 608db81..bdffe0c 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -731,12 +731,12 @@
 {
 	int err;
 
-	kset_set_kset_s(&fuse_subsys, fs_subsys);
+	kobj_set_kset_s(&fuse_subsys, fs_subsys);
 	err = subsystem_register(&fuse_subsys);
 	if (err)
 		goto out_err;
 
-	kset_set_kset_s(&connections_subsys, fuse_subsys);
+	kobj_set_kset_s(&connections_subsys, fuse_subsys);
 	err = subsystem_register(&connections_subsys);
 	if (err)
 		goto out_fuse_unregister;
diff --git a/fs/gfs2/locking/dlm/sysfs.c b/fs/gfs2/locking/dlm/sysfs.c
index 4746b88..d9fe3ca 100644
--- a/fs/gfs2/locking/dlm/sysfs.c
+++ b/fs/gfs2/locking/dlm/sysfs.c
@@ -190,7 +190,6 @@
 };
 
 static struct kset gdlm_kset = {
-	.subsys = &kernel_subsys,
 	.kobj   = {.name = "lock_dlm",},
 	.ktype  = &gdlm_ktype,
 };
@@ -225,6 +224,7 @@
 {
 	int error;
 
+	kobj_set_kset_s(&gdlm_kset, kernel_subsys);
 	error = kset_register(&gdlm_kset);
 	if (error)
 		printk("lock_dlm: cannot register kset %d\n", error);
diff --git a/fs/gfs2/sys.c b/fs/gfs2/sys.c
index d01f9f0..c26c21b 100644
--- a/fs/gfs2/sys.c
+++ b/fs/gfs2/sys.c
@@ -222,7 +222,6 @@
 };
 
 static struct kset gfs2_kset = {
-	.subsys = &fs_subsys,
 	.kobj   = {.name = "gfs2"},
 	.ktype  = &gfs2_ktype,
 };
@@ -554,6 +553,7 @@
 {
 	gfs2_sys_margs = NULL;
 	spin_lock_init(&gfs2_sys_margs_lock);
+	kobj_set_kset_s(&gfs2_kset, fs_subsys);
 	return kset_register(&gfs2_kset);
 }
 
diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c
index eb243ed..2102e2d 100644
--- a/fs/lockd/mon.c
+++ b/fs/lockd/mon.c
@@ -225,16 +225,13 @@
 #define SM_monres_sz	2
 #define SM_unmonres_sz	1
 
-#ifndef MAX
-# define MAX(a, b)	(((a) > (b))? (a) : (b))
-#endif
-
 static struct rpc_procinfo	nsm_procedures[] = {
 [SM_MON] = {
 		.p_proc		= SM_MON,
 		.p_encode	= (kxdrproc_t) xdr_encode_mon,
 		.p_decode	= (kxdrproc_t) xdr_decode_stat_res,
-		.p_bufsiz	= MAX(SM_mon_sz, SM_monres_sz) << 2,
+		.p_arglen	= SM_mon_sz,
+		.p_replen	= SM_monres_sz,
 		.p_statidx	= SM_MON,
 		.p_name		= "MONITOR",
 	},
@@ -242,7 +239,8 @@
 		.p_proc		= SM_UNMON,
 		.p_encode	= (kxdrproc_t) xdr_encode_unmon,
 		.p_decode	= (kxdrproc_t) xdr_decode_stat,
-		.p_bufsiz	= MAX(SM_mon_id_sz, SM_unmonres_sz) << 2,
+		.p_arglen	= SM_mon_id_sz,
+		.p_replen	= SM_unmonres_sz,
 		.p_statidx	= SM_UNMON,
 		.p_name		= "UNMONITOR",
 	},
diff --git a/fs/lockd/xdr.c b/fs/lockd/xdr.c
index 34dae5d..9702956 100644
--- a/fs/lockd/xdr.c
+++ b/fs/lockd/xdr.c
@@ -510,17 +510,20 @@
 	return 0;
 }
 
+#if (NLMCLNT_OHSIZE > XDR_MAX_NETOBJ)
+#  error "NLM host name cannot be larger than XDR_MAX_NETOBJ!"
+#endif
+
 /*
  * Buffer requirements for NLM
  */
 #define NLM_void_sz		0
 #define NLM_cookie_sz		1+XDR_QUADLEN(NLM_MAXCOOKIELEN)
-#define NLM_caller_sz		1+XDR_QUADLEN(sizeof(utsname()->nodename))
-#define NLM_netobj_sz		1+XDR_QUADLEN(XDR_MAX_NETOBJ)
-/* #define NLM_owner_sz		1+XDR_QUADLEN(NLM_MAXOWNER) */
+#define NLM_caller_sz		1+XDR_QUADLEN(NLMCLNT_OHSIZE)
+#define NLM_owner_sz		1+XDR_QUADLEN(NLMCLNT_OHSIZE)
 #define NLM_fhandle_sz		1+XDR_QUADLEN(NFS2_FHSIZE)
-#define NLM_lock_sz		3+NLM_caller_sz+NLM_netobj_sz+NLM_fhandle_sz
-#define NLM_holder_sz		4+NLM_netobj_sz
+#define NLM_lock_sz		3+NLM_caller_sz+NLM_owner_sz+NLM_fhandle_sz
+#define NLM_holder_sz		4+NLM_owner_sz
 
 #define NLM_testargs_sz		NLM_cookie_sz+1+NLM_lock_sz
 #define NLM_lockargs_sz		NLM_cookie_sz+4+NLM_lock_sz
@@ -531,10 +534,6 @@
 #define NLM_res_sz		NLM_cookie_sz+1
 #define NLM_norep_sz		0
 
-#ifndef MAX
-# define MAX(a, b)		(((a) > (b))? (a) : (b))
-#endif
-
 /*
  * For NLM, a void procedure really returns nothing
  */
@@ -545,7 +544,8 @@
 	.p_proc      = NLMPROC_##proc,					\
 	.p_encode    = (kxdrproc_t) nlmclt_encode_##argtype,		\
 	.p_decode    = (kxdrproc_t) nlmclt_decode_##restype,		\
-	.p_bufsiz    = MAX(NLM_##argtype##_sz, NLM_##restype##_sz) << 2,	\
+	.p_arglen    = NLM_##argtype##_sz,				\
+	.p_replen    = NLM_##restype##_sz,				\
 	.p_statidx   = NLMPROC_##proc,					\
 	.p_name      = #proc,						\
 	}
diff --git a/fs/lockd/xdr4.c b/fs/lockd/xdr4.c
index a782405..ce1efdbe 100644
--- a/fs/lockd/xdr4.c
+++ b/fs/lockd/xdr4.c
@@ -516,17 +516,24 @@
 	return 0;
 }
 
+#if (NLMCLNT_OHSIZE > XDR_MAX_NETOBJ)
+#  error "NLM host name cannot be larger than XDR_MAX_NETOBJ!"
+#endif
+
+#if (NLMCLNT_OHSIZE > NLM_MAXSTRLEN)
+#  error "NLM host name cannot be larger than NLM's maximum string length!"
+#endif
+
 /*
  * Buffer requirements for NLM
  */
 #define NLM4_void_sz		0
 #define NLM4_cookie_sz		1+XDR_QUADLEN(NLM_MAXCOOKIELEN)
-#define NLM4_caller_sz		1+XDR_QUADLEN(NLM_MAXSTRLEN)
-#define NLM4_netobj_sz		1+XDR_QUADLEN(XDR_MAX_NETOBJ)
-/* #define NLM4_owner_sz		1+XDR_QUADLEN(NLM4_MAXOWNER) */
+#define NLM4_caller_sz		1+XDR_QUADLEN(NLMCLNT_OHSIZE)
+#define NLM4_owner_sz		1+XDR_QUADLEN(NLMCLNT_OHSIZE)
 #define NLM4_fhandle_sz		1+XDR_QUADLEN(NFS3_FHSIZE)
-#define NLM4_lock_sz		5+NLM4_caller_sz+NLM4_netobj_sz+NLM4_fhandle_sz
-#define NLM4_holder_sz		6+NLM4_netobj_sz
+#define NLM4_lock_sz		5+NLM4_caller_sz+NLM4_owner_sz+NLM4_fhandle_sz
+#define NLM4_holder_sz		6+NLM4_owner_sz
 
 #define NLM4_testargs_sz	NLM4_cookie_sz+1+NLM4_lock_sz
 #define NLM4_lockargs_sz	NLM4_cookie_sz+4+NLM4_lock_sz
@@ -537,10 +544,6 @@
 #define NLM4_res_sz		NLM4_cookie_sz+1
 #define NLM4_norep_sz		0
 
-#ifndef MAX
-# define MAX(a,b)		(((a) > (b))? (a) : (b))
-#endif
-
 /*
  * For NLM, a void procedure really returns nothing
  */
@@ -551,7 +554,8 @@
 	.p_proc      = NLMPROC_##proc,					\
 	.p_encode    = (kxdrproc_t) nlm4clt_encode_##argtype,		\
 	.p_decode    = (kxdrproc_t) nlm4clt_decode_##restype,		\
-	.p_bufsiz    = MAX(NLM4_##argtype##_sz, NLM4_##restype##_sz) << 2,	\
+	.p_arglen    = NLM4_##argtype##_sz,				\
+	.p_replen    = NLM4_##restype##_sz,				\
 	.p_statidx   = NLMPROC_##proc,					\
 	.p_name      = #proc,						\
 	}
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 2190e6c..5bd03b9 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -618,7 +618,8 @@
 	if (clp->cl_nfsversion == 3) {
 		if (server->namelen == 0 || server->namelen > NFS3_MAXNAMLEN)
 			server->namelen = NFS3_MAXNAMLEN;
-		server->caps |= NFS_CAP_READDIRPLUS;
+		if (!(data->flags & NFS_MOUNT_NORDIRPLUS))
+			server->caps |= NFS_CAP_READDIRPLUS;
 	} else {
 		if (server->namelen == 0 || server->namelen > NFS2_MAXNAMLEN)
 			server->namelen = NFS2_MAXNAMLEN;
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index cd34697..e59fd31 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -154,6 +154,8 @@
 	decode_dirent_t	decode;
 	int		plus;
 	int		error;
+	unsigned long	timestamp;
+	int		timestamp_valid;
 } nfs_readdir_descriptor_t;
 
 /* Now we cache directories properly, by stuffing the dirent
@@ -195,6 +197,8 @@
 		}
 		goto error;
 	}
+	desc->timestamp = timestamp;
+	desc->timestamp_valid = 1;
 	SetPageUptodate(page);
 	spin_lock(&inode->i_lock);
 	NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ATIME;
@@ -225,6 +229,10 @@
 	if (IS_ERR(p))
 		return PTR_ERR(p);
 	desc->ptr = p;
+	if (desc->timestamp_valid)
+		desc->entry->fattr->time_start = desc->timestamp;
+	else
+		desc->entry->fattr->valid &= ~NFS_ATTR_FATTR;
 	return 0;
 }
 
@@ -316,6 +324,10 @@
 			__FUNCTION__, desc->page_index,
 			(long long) *desc->dir_cookie);
 
+	/* If we find the page in the page_cache, we cannot be sure
+	 * how fresh the data is, so we will ignore readdir_plus attributes.
+	 */
+	desc->timestamp_valid = 0;
 	page = read_cache_page(inode->i_mapping, desc->page_index,
 			       (filler_t *)nfs_readdir_filler, desc);
 	if (IS_ERR(page)) {
@@ -468,6 +480,7 @@
 	struct rpc_cred	*cred = nfs_file_cred(file);
 	struct page	*page = NULL;
 	int		status;
+	unsigned long	timestamp;
 
 	dfprintk(DIRCACHE, "NFS: uncached_readdir() searching for cookie %Lu\n",
 			(unsigned long long)*desc->dir_cookie);
@@ -477,6 +490,7 @@
 		status = -ENOMEM;
 		goto out;
 	}
+	timestamp = jiffies;
 	desc->error = NFS_PROTO(inode)->readdir(file->f_path.dentry, cred, *desc->dir_cookie,
 						page,
 						NFS_SERVER(inode)->dtsize,
@@ -487,6 +501,8 @@
 	desc->page = page;
 	desc->ptr = kmap(page);		/* matching kunmap in nfs_do_filldir */
 	if (desc->error >= 0) {
+		desc->timestamp = timestamp;
+		desc->timestamp_valid = 1;
 		if ((status = dir_decode(desc)) == 0)
 			desc->entry->prev_cookie = *desc->dir_cookie;
 	} else
@@ -849,6 +865,10 @@
 static void nfs_dentry_iput(struct dentry *dentry, struct inode *inode)
 {
 	nfs_inode_return_delegation(inode);
+	if (S_ISDIR(inode->i_mode))
+		/* drop any readdir cache as it could easily be old */
+		NFS_I(inode)->cache_validity |= NFS_INO_INVALID_DATA;
+
 	if (dentry->d_flags & DCACHE_NFSFS_RENAMED) {
 		lock_kernel();
 		drop_nlink(inode);
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index 2877744c..889de60 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -54,6 +54,7 @@
 #include <asm/uaccess.h>
 #include <asm/atomic.h>
 
+#include "internal.h"
 #include "iostat.h"
 
 #define NFSDBG_FACILITY		NFSDBG_VFS
@@ -271,7 +272,7 @@
 		bytes = min(rsize,count);
 
 		result = -ENOMEM;
-		data = nfs_readdata_alloc(pgbase + bytes);
+		data = nfs_readdata_alloc(nfs_page_array_len(pgbase, bytes));
 		if (unlikely(!data))
 			break;
 
@@ -602,7 +603,7 @@
 		bytes = min(wsize,count);
 
 		result = -ENOMEM;
-		data = nfs_writedata_alloc(pgbase + bytes);
+		data = nfs_writedata_alloc(nfs_page_array_len(pgbase, bytes));
 		if (unlikely(!data))
 			break;
 
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index 6610f2b..ad2b40d 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -231,3 +231,15 @@
 	}
 	return 0;
 }
+
+/*
+ * Determine the number of pages in an array of length 'len' and
+ * with a base offset of 'base'
+ */
+static inline
+unsigned int nfs_page_array_len(unsigned int base, size_t len)
+{
+	return ((unsigned long)len + (unsigned long)base +
+		PAGE_SIZE - 1) >> PAGE_SHIFT;
+}
+
diff --git a/fs/nfs/mount_clnt.c b/fs/nfs/mount_clnt.c
index f75fe72..ca5a266 100644
--- a/fs/nfs/mount_clnt.c
+++ b/fs/nfs/mount_clnt.c
@@ -133,13 +133,15 @@
 
 #define MNT_dirpath_sz		(1 + 256)
 #define MNT_fhstatus_sz		(1 + 8)
+#define MNT_fhstatus3_sz	(1 + 16)
 
 static struct rpc_procinfo	mnt_procedures[] = {
 [MNTPROC_MNT] = {
 	  .p_proc		= MNTPROC_MNT,
 	  .p_encode		= (kxdrproc_t) xdr_encode_dirpath,	
 	  .p_decode		= (kxdrproc_t) xdr_decode_fhstatus,
-	  .p_bufsiz		= MNT_dirpath_sz << 2,
+	  .p_arglen		= MNT_dirpath_sz,
+	  .p_replen		= MNT_fhstatus_sz,
 	  .p_statidx		= MNTPROC_MNT,
 	  .p_name		= "MOUNT",
 	},
@@ -150,7 +152,8 @@
 	  .p_proc		= MOUNTPROC3_MNT,
 	  .p_encode		= (kxdrproc_t) xdr_encode_dirpath,
 	  .p_decode		= (kxdrproc_t) xdr_decode_fhstatus3,
-	  .p_bufsiz		= MNT_dirpath_sz << 2,
+	  .p_arglen		= MNT_dirpath_sz,
+	  .p_replen		= MNT_fhstatus3_sz,
 	  .p_statidx		= MOUNTPROC3_MNT,
 	  .p_name		= "MOUNT",
 	},
diff --git a/fs/nfs/nfs2xdr.c b/fs/nfs/nfs2xdr.c
index 3be4e72..abd9f8b 100644
--- a/fs/nfs/nfs2xdr.c
+++ b/fs/nfs/nfs2xdr.c
@@ -687,16 +687,13 @@
 	return nfs_errtbl[i].errno;
 }
 
-#ifndef MAX
-# define MAX(a, b)	(((a) > (b))? (a) : (b))
-#endif
-
 #define PROC(proc, argtype, restype, timer)				\
 [NFSPROC_##proc] = {							\
 	.p_proc	    =  NFSPROC_##proc,					\
 	.p_encode   =  (kxdrproc_t) nfs_xdr_##argtype,			\
 	.p_decode   =  (kxdrproc_t) nfs_xdr_##restype,			\
-	.p_bufsiz   =  MAX(NFS_##argtype##_sz,NFS_##restype##_sz) << 2,	\
+	.p_arglen   =  NFS_##argtype##_sz,				\
+	.p_replen   =  NFS_##restype##_sz,				\
 	.p_timer    =  timer,						\
 	.p_statidx  =  NFSPROC_##proc,					\
 	.p_name     =  #proc,						\
diff --git a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c
index 0ace092..b51df8eb 100644
--- a/fs/nfs/nfs3xdr.c
+++ b/fs/nfs/nfs3xdr.c
@@ -1102,16 +1102,13 @@
 }
 #endif  /* CONFIG_NFS_V3_ACL */
 
-#ifndef MAX
-# define MAX(a, b)	(((a) > (b))? (a) : (b))
-#endif
-
 #define PROC(proc, argtype, restype, timer)				\
 [NFS3PROC_##proc] = {							\
 	.p_proc      = NFS3PROC_##proc,					\
 	.p_encode    = (kxdrproc_t) nfs3_xdr_##argtype,			\
 	.p_decode    = (kxdrproc_t) nfs3_xdr_##restype,			\
-	.p_bufsiz    = MAX(NFS3_##argtype##_sz,NFS3_##restype##_sz) << 2,	\
+	.p_arglen    = NFS3_##argtype##_sz,				\
+	.p_replen    = NFS3_##restype##_sz,				\
 	.p_timer     = timer,						\
 	.p_statidx   = NFS3PROC_##proc,					\
 	.p_name      = #proc,						\
@@ -1153,7 +1150,8 @@
 		.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_arglen = ACL3_getaclargs_sz,
+		.p_replen = ACL3_getaclres_sz,
 		.p_timer = 1,
 		.p_name = "GETACL",
 	},
@@ -1161,7 +1159,8 @@
 		.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_arglen = ACL3_setaclargs_sz,
+		.p_replen = ACL3_setaclres_sz,
 		.p_timer = 0,
 		.p_name = "SETACL",
 	},
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index f52cf5c..3b5ca1b 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -2647,8 +2647,7 @@
 	nfs_inode_return_delegation(inode);
 	buf_to_pages(buf, buflen, arg.acl_pages, &arg.acl_pgbase);
 	ret = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
-	if (ret == 0)
-		nfs4_write_cached_acl(inode, buf, buflen);
+	nfs_zap_caches(inode);
 	return ret;
 }
 
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index f02d522..b8c28f2 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -4546,16 +4546,13 @@
 	return stat;
 }
 
-#ifndef MAX
-# define MAX(a, b)	(((a) > (b))? (a) : (b))
-#endif
-
 #define PROC(proc, argtype, restype)				\
 [NFSPROC4_CLNT_##proc] = {					\
 	.p_proc   = NFSPROC4_COMPOUND,				\
 	.p_encode = (kxdrproc_t) nfs4_xdr_##argtype,		\
 	.p_decode = (kxdrproc_t) nfs4_xdr_##restype,		\
-	.p_bufsiz = MAX(NFS4_##argtype##_sz,NFS4_##restype##_sz) << 2,	\
+	.p_arglen = NFS4_##argtype##_sz,			\
+	.p_replen = NFS4_##restype##_sz,			\
 	.p_statidx = NFSPROC4_CLNT_##proc,			\
 	.p_name   = #proc,					\
     }
diff --git a/fs/nfs/nfsroot.c b/fs/nfs/nfsroot.c
index 75f819d..49d1008 100644
--- a/fs/nfs/nfsroot.c
+++ b/fs/nfs/nfsroot.c
@@ -428,7 +428,7 @@
 	printk(KERN_NOTICE "Looking up port of RPC %d/%d on %u.%u.%u.%u\n",
 		program, version, NIPQUAD(servaddr));
 	set_sockaddr(&sin, servaddr, 0);
-	return rpc_getport_external(&sin, program, version, proto);
+	return rpcb_getport_external(&sin, program, version, proto);
 }
 
 
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c
index ca4b1d4..3889501 100644
--- a/fs/nfs/pagelist.c
+++ b/fs/nfs/pagelist.c
@@ -17,7 +17,8 @@
 #include <linux/nfs_page.h>
 #include <linux/nfs_fs.h>
 #include <linux/nfs_mount.h>
-#include <linux/writeback.h>
+
+#include "internal.h"
 
 #define NFS_PARANOIA 1
 
@@ -50,9 +51,7 @@
  * @count: number of bytes to read/write
  *
  * The page must be locked by the caller. This makes sure we never
- * create two different requests for the same page, and avoids
- * a possible deadlock when we reach the hard limit on the number
- * of dirty pages.
+ * create two different requests for the same page.
  * User should ensure it is safe to sleep in this function.
  */
 struct nfs_page *
@@ -63,16 +62,12 @@
 	struct nfs_server *server = NFS_SERVER(inode);
 	struct nfs_page		*req;
 
-	/* Deal with hard limits.  */
 	for (;;) {
 		/* try to allocate the request struct */
 		req = nfs_page_alloc();
 		if (req != NULL)
 			break;
 
-		/* Try to free up at least one request in order to stay
-		 * below the hard limit
-		 */
 		if (signalled() && (server->flags & NFS_MOUNT_INTR))
 			return ERR_PTR(-ERESTARTSYS);
 		yield();
@@ -223,124 +218,151 @@
 }
 
 /**
- * nfs_coalesce_requests - Split coalesced requests out from a list.
- * @head: source list
- * @dst: destination list
- * @nmax: maximum number of requests to coalesce
- *
- * Moves a maximum of 'nmax' elements from one list to another.
- * The elements are checked to ensure that they form a contiguous set
- * of pages, and that the RPC credentials are the same.
+ * nfs_pageio_init - initialise a page io descriptor
+ * @desc: pointer to descriptor
+ * @inode: pointer to inode
+ * @doio: pointer to io function
+ * @bsize: io block size
+ * @io_flags: extra parameters for the io function
  */
-int
-nfs_coalesce_requests(struct list_head *head, struct list_head *dst,
-		      unsigned int nmax)
+void nfs_pageio_init(struct nfs_pageio_descriptor *desc,
+		     struct inode *inode,
+		     int (*doio)(struct inode *, struct list_head *, unsigned int, size_t, int),
+		     size_t bsize,
+		     int io_flags)
 {
-	struct nfs_page		*req = NULL;
-	unsigned int		npages = 0;
+	INIT_LIST_HEAD(&desc->pg_list);
+	desc->pg_bytes_written = 0;
+	desc->pg_count = 0;
+	desc->pg_bsize = bsize;
+	desc->pg_base = 0;
+	desc->pg_inode = inode;
+	desc->pg_doio = doio;
+	desc->pg_ioflags = io_flags;
+	desc->pg_error = 0;
+}
 
-	while (!list_empty(head)) {
-		struct nfs_page	*prev = req;
+/**
+ * nfs_can_coalesce_requests - test two requests for compatibility
+ * @prev: pointer to nfs_page
+ * @req: pointer to nfs_page
+ *
+ * The nfs_page structures 'prev' and 'req' are compared to ensure that the
+ * page data area they describe is contiguous, and that their RPC
+ * credentials, NFSv4 open state, and lockowners are the same.
+ *
+ * Return 'true' if this is the case, else return 'false'.
+ */
+static int nfs_can_coalesce_requests(struct nfs_page *prev,
+				     struct nfs_page *req)
+{
+	if (req->wb_context->cred != prev->wb_context->cred)
+		return 0;
+	if (req->wb_context->lockowner != prev->wb_context->lockowner)
+		return 0;
+	if (req->wb_context->state != prev->wb_context->state)
+		return 0;
+	if (req->wb_index != (prev->wb_index + 1))
+		return 0;
+	if (req->wb_pgbase != 0)
+		return 0;
+	if (prev->wb_pgbase + prev->wb_bytes != PAGE_CACHE_SIZE)
+		return 0;
+	return 1;
+}
 
-		req = nfs_list_entry(head->next);
-		if (prev) {
-			if (req->wb_context->cred != prev->wb_context->cred)
-				break;
-			if (req->wb_context->lockowner != prev->wb_context->lockowner)
-				break;
-			if (req->wb_context->state != prev->wb_context->state)
-				break;
-			if (req->wb_index != (prev->wb_index + 1))
-				break;
+/**
+ * nfs_pageio_do_add_request - Attempt to coalesce a request into a page list.
+ * @desc: destination io descriptor
+ * @req: request
+ *
+ * Returns true if the request 'req' was successfully coalesced into the
+ * existing list of pages 'desc'.
+ */
+static int nfs_pageio_do_add_request(struct nfs_pageio_descriptor *desc,
+				     struct nfs_page *req)
+{
+	size_t newlen = req->wb_bytes;
 
-			if (req->wb_pgbase != 0)
-				break;
-		}
-		nfs_list_remove_request(req);
-		nfs_list_add_request(req, dst);
-		npages++;
-		if (req->wb_pgbase + req->wb_bytes != PAGE_CACHE_SIZE)
-			break;
-		if (npages >= nmax)
-			break;
+	if (desc->pg_count != 0) {
+		struct nfs_page *prev;
+
+		/*
+		 * FIXME: ideally we should be able to coalesce all requests
+		 * that are not block boundary aligned, but currently this
+		 * is problematic for the case of bsize < PAGE_CACHE_SIZE,
+		 * since nfs_flush_multi and nfs_pagein_multi assume you
+		 * can have only one struct nfs_page.
+		 */
+		if (desc->pg_bsize < PAGE_SIZE)
+			return 0;
+		newlen += desc->pg_count;
+		if (newlen > desc->pg_bsize)
+			return 0;
+		prev = nfs_list_entry(desc->pg_list.prev);
+		if (!nfs_can_coalesce_requests(prev, req))
+			return 0;
+	} else
+		desc->pg_base = req->wb_pgbase;
+	nfs_list_remove_request(req);
+	nfs_list_add_request(req, &desc->pg_list);
+	desc->pg_count = newlen;
+	return 1;
+}
+
+/*
+ * Helper for nfs_pageio_add_request and nfs_pageio_complete
+ */
+static void nfs_pageio_doio(struct nfs_pageio_descriptor *desc)
+{
+	if (!list_empty(&desc->pg_list)) {
+		int error = desc->pg_doio(desc->pg_inode,
+					  &desc->pg_list,
+					  nfs_page_array_len(desc->pg_base,
+							     desc->pg_count),
+					  desc->pg_count,
+					  desc->pg_ioflags);
+		if (error < 0)
+			desc->pg_error = error;
+		else
+			desc->pg_bytes_written += desc->pg_count;
 	}
-	return npages;
+	if (list_empty(&desc->pg_list)) {
+		desc->pg_count = 0;
+		desc->pg_base = 0;
+	}
+}
+
+/**
+ * nfs_pageio_add_request - Attempt to coalesce a request into a page list.
+ * @desc: destination io descriptor
+ * @req: request
+ *
+ * Returns true if the request 'req' was successfully coalesced into the
+ * existing list of pages 'desc'.
+ */
+int nfs_pageio_add_request(struct nfs_pageio_descriptor *desc,
+			   struct nfs_page *req)
+{
+	while (!nfs_pageio_do_add_request(desc, req)) {
+		nfs_pageio_doio(desc);
+		if (desc->pg_error < 0)
+			return 0;
+	}
+	return 1;
+}
+
+/**
+ * nfs_pageio_complete - Complete I/O on an nfs_pageio_descriptor
+ * @desc: pointer to io descriptor
+ */
+void nfs_pageio_complete(struct nfs_pageio_descriptor *desc)
+{
+	nfs_pageio_doio(desc);
 }
 
 #define NFS_SCAN_MAXENTRIES 16
 /**
- * nfs_scan_dirty - Scan the radix tree for dirty requests
- * @mapping: pointer to address space
- * @wbc: writeback_control structure
- * @dst: Destination list
- *
- * 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
- */
-long nfs_scan_dirty(struct address_space *mapping,
-			struct writeback_control *wbc,
-			struct list_head *dst)
-{
-	struct nfs_inode *nfsi = NFS_I(mapping->host);
-	struct nfs_page *pgvec[NFS_SCAN_MAXENTRIES];
-	struct nfs_page *req;
-	pgoff_t idx_start, idx_end;
-	long res = 0;
-	int found, i;
-
-	if (nfsi->ndirty == 0)
-		return 0;
-	if (wbc->range_cyclic) {
-		idx_start = 0;
-		idx_end = ULONG_MAX;
-	} else if (wbc->range_end == 0) {
-		idx_start = wbc->range_start >> PAGE_CACHE_SHIFT;
-		idx_end = ULONG_MAX;
-	} else {
-		idx_start = wbc->range_start >> PAGE_CACHE_SHIFT;
-		idx_end = wbc->range_end >> PAGE_CACHE_SHIFT;
-	}
-
-	for (;;) {
-		unsigned int toscan = NFS_SCAN_MAXENTRIES;
-
-		found = radix_tree_gang_lookup_tag(&nfsi->nfs_page_tree,
-				(void **)&pgvec[0], idx_start, toscan,
-				NFS_PAGE_TAG_DIRTY);
-
-		/* Did we make progress? */
-		if (found <= 0)
-			break;
-
-		for (i = 0; i < found; i++) {
-			req = pgvec[i];
-			if (!wbc->range_cyclic && req->wb_index > idx_end)
-				goto out;
-
-			/* Try to lock request and mark it for writeback */
-			if (!nfs_set_page_writeback_locked(req))
-				goto next;
-			radix_tree_tag_clear(&nfsi->nfs_page_tree,
-					req->wb_index, NFS_PAGE_TAG_DIRTY);
-			nfsi->ndirty--;
-			nfs_list_remove_request(req);
-			nfs_list_add_request(req, dst);
-			res++;
-			if (res == LONG_MAX)
-				goto out;
-next:
-			idx_start = req->wb_index + 1;
-		}
-	}
-out:
-	WARN_ON ((nfsi->ndirty == 0) != list_empty(&nfsi->dirty));
-	return res;
-}
-
-/**
  * nfs_scan_list - Scan a list for matching requests
  * @nfsi: NFS inode
  * @head: One of the NFS inode request lists
@@ -355,12 +377,12 @@
  * You must be holding the inode's req_lock when calling this function
  */
 int nfs_scan_list(struct nfs_inode *nfsi, struct list_head *head,
-		struct list_head *dst, unsigned long idx_start,
+		struct list_head *dst, pgoff_t idx_start,
 		unsigned int npages)
 {
 	struct nfs_page *pgvec[NFS_SCAN_MAXENTRIES];
 	struct nfs_page *req;
-	unsigned long idx_end;
+	pgoff_t idx_end;
 	int found, i;
 	int res;
 
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index 6ab4d5a..9a55807 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -27,7 +27,8 @@
 
 #define NFSDBG_FACILITY		NFSDBG_PAGECACHE
 
-static int nfs_pagein_one(struct list_head *, struct inode *);
+static int nfs_pagein_multi(struct inode *, struct list_head *, unsigned int, size_t, int);
+static int nfs_pagein_one(struct inode *, struct list_head *, unsigned int, size_t, int);
 static const struct rpc_call_ops nfs_read_partial_ops;
 static const struct rpc_call_ops nfs_read_full_ops;
 
@@ -36,9 +37,8 @@
 
 #define MIN_POOL_READ	(32)
 
-struct nfs_read_data *nfs_readdata_alloc(size_t len)
+struct nfs_read_data *nfs_readdata_alloc(unsigned int pagecount)
 {
-	unsigned int pagecount = (len + PAGE_SIZE - 1) >> PAGE_SHIFT;
 	struct nfs_read_data *p = mempool_alloc(nfs_rdata_mempool, GFP_NOFS);
 
 	if (p) {
@@ -133,7 +133,10 @@
 		memclear_highpage_flush(page, len, PAGE_CACHE_SIZE - len);
 
 	nfs_list_add_request(new, &one_request);
-	nfs_pagein_one(&one_request, inode);
+	if (NFS_SERVER(inode)->rsize < PAGE_CACHE_SIZE)
+		nfs_pagein_multi(inode, &one_request, 1, len, 0);
+	else
+		nfs_pagein_one(inode, &one_request, 1, len, 0);
 	return 0;
 }
 
@@ -230,7 +233,7 @@
  * won't see the new data until our attribute cache is updated.  This is more
  * or less conventional NFS client behavior.
  */
-static int nfs_pagein_multi(struct list_head *head, struct inode *inode)
+static int nfs_pagein_multi(struct inode *inode, struct list_head *head, unsigned int npages, size_t count, int flags)
 {
 	struct nfs_page *req = nfs_list_entry(head->next);
 	struct page *page = req->wb_page;
@@ -242,11 +245,11 @@
 
 	nfs_list_remove_request(req);
 
-	nbytes = req->wb_bytes;
+	nbytes = count;
 	do {
 		size_t len = min(nbytes,rsize);
 
-		data = nfs_readdata_alloc(len);
+		data = nfs_readdata_alloc(1);
 		if (!data)
 			goto out_bad;
 		INIT_LIST_HEAD(&data->pages);
@@ -258,23 +261,19 @@
 
 	ClearPageError(page);
 	offset = 0;
-	nbytes = req->wb_bytes;
+	nbytes = count;
 	do {
 		data = list_entry(list.next, struct nfs_read_data, pages);
 		list_del_init(&data->pages);
 
 		data->pagevec[0] = page;
 
-		if (nbytes > rsize) {
-			nfs_read_rpcsetup(req, data, &nfs_read_partial_ops,
-					rsize, offset);
-			offset += rsize;
-			nbytes -= rsize;
-		} else {
-			nfs_read_rpcsetup(req, data, &nfs_read_partial_ops,
-					nbytes, offset);
-			nbytes = 0;
-		}
+		if (nbytes < rsize)
+			rsize = nbytes;
+		nfs_read_rpcsetup(req, data, &nfs_read_partial_ops,
+				  rsize, offset);
+		offset += rsize;
+		nbytes -= rsize;
 		nfs_execute_read(data);
 	} while (nbytes != 0);
 
@@ -291,30 +290,24 @@
 	return -ENOMEM;
 }
 
-static int nfs_pagein_one(struct list_head *head, struct inode *inode)
+static int nfs_pagein_one(struct inode *inode, struct list_head *head, unsigned int npages, size_t count, int flags)
 {
 	struct nfs_page		*req;
 	struct page		**pages;
 	struct nfs_read_data	*data;
-	unsigned int		count;
 
-	if (NFS_SERVER(inode)->rsize < PAGE_CACHE_SIZE)
-		return nfs_pagein_multi(head, inode);
-
-	data = nfs_readdata_alloc(NFS_SERVER(inode)->rsize);
+	data = nfs_readdata_alloc(npages);
 	if (!data)
 		goto out_bad;
 
 	INIT_LIST_HEAD(&data->pages);
 	pages = data->pagevec;
-	count = 0;
 	while (!list_empty(head)) {
 		req = nfs_list_entry(head->next);
 		nfs_list_remove_request(req);
 		nfs_list_add_request(req, &data->pages);
 		ClearPageError(req->wb_page);
 		*pages++ = req->wb_page;
-		count += req->wb_bytes;
 	}
 	req = nfs_list_entry(data->pages.next);
 
@@ -327,28 +320,6 @@
 	return -ENOMEM;
 }
 
-static int
-nfs_pagein_list(struct list_head *head, int rpages)
-{
-	LIST_HEAD(one_request);
-	struct nfs_page		*req;
-	int			error = 0;
-	unsigned int		pages = 0;
-
-	while (!list_empty(head)) {
-		pages += nfs_coalesce_requests(head, &one_request, rpages);
-		req = nfs_list_entry(one_request.next);
-		error = nfs_pagein_one(&one_request, req->wb_context->dentry->d_inode);
-		if (error < 0)
-			break;
-	}
-	if (error >= 0)
-		return pages;
-
-	nfs_async_read_error(head);
-	return error;
-}
-
 /*
  * This is the callback from RPC telling us whether a reply was
  * received or some error occurred (timeout or socket shutdown).
@@ -538,7 +509,7 @@
 }
 
 struct nfs_readdesc {
-	struct list_head *head;
+	struct nfs_pageio_descriptor *pgio;
 	struct nfs_open_context *ctx;
 };
 
@@ -562,19 +533,21 @@
 	}
 	if (len < PAGE_CACHE_SIZE)
 		memclear_highpage_flush(page, len, PAGE_CACHE_SIZE - len);
-	nfs_list_add_request(new, desc->head);
+	nfs_pageio_add_request(desc->pgio, new);
 	return 0;
 }
 
 int nfs_readpages(struct file *filp, struct address_space *mapping,
 		struct list_head *pages, unsigned nr_pages)
 {
-	LIST_HEAD(head);
+	struct nfs_pageio_descriptor pgio;
 	struct nfs_readdesc desc = {
-		.head		= &head,
+		.pgio = &pgio,
 	};
 	struct inode *inode = mapping->host;
 	struct nfs_server *server = NFS_SERVER(inode);
+	size_t rsize = server->rsize;
+	unsigned long npages;
 	int ret = -ESTALE;
 
 	dprintk("NFS: nfs_readpages (%s/%Ld %d)\n",
@@ -593,13 +566,16 @@
 	} else
 		desc.ctx = get_nfs_open_context((struct nfs_open_context *)
 				filp->private_data);
+	if (rsize < PAGE_CACHE_SIZE)
+		nfs_pageio_init(&pgio, inode, nfs_pagein_multi, rsize, 0);
+	else
+		nfs_pageio_init(&pgio, inode, nfs_pagein_one, rsize, 0);
+
 	ret = read_cache_pages(mapping, pages, readpage_async_filler, &desc);
-	if (!list_empty(&head)) {
-		int err = nfs_pagein_list(&head, server->rpages);
-		if (!ret)
-			nfs_add_stats(inode, NFSIOS_READPAGES, err);
-			ret = err;
-	}
+
+	nfs_pageio_complete(&pgio);
+	npages = (pgio.pg_bytes_written + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
+	nfs_add_stats(inode, NFSIOS_READPAGES, npages);
 	put_nfs_open_context(desc.ctx);
 out:
 	return ret;
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index f1eae44..ca20d3c 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -204,9 +204,9 @@
 	lock_kernel();
 
 	error = server->nfs_client->rpc_ops->statfs(server, fh, &res);
-	buf->f_type = NFS_SUPER_MAGIC;
 	if (error < 0)
 		goto out_err;
+	buf->f_type = NFS_SUPER_MAGIC;
 
 	/*
 	 * Current versions of glibc do not correctly handle the
@@ -233,15 +233,14 @@
 	buf->f_ffree = res.afiles;
 
 	buf->f_namelen = server->namelen;
- out:
+
 	unlock_kernel();
 	return 0;
 
  out_err:
 	dprintk("%s: statfs error = %d\n", __FUNCTION__, -error);
-	buf->f_bsize = buf->f_blocks = buf->f_bfree = buf->f_bavail = -1;
-	goto out;
-
+	unlock_kernel();
+	return error;
 }
 
 /*
@@ -291,6 +290,7 @@
 		{ NFS_MOUNT_NOAC, ",noac", "" },
 		{ NFS_MOUNT_NONLM, ",nolock", "" },
 		{ NFS_MOUNT_NOACL, ",noacl", "" },
+		{ NFS_MOUNT_NORDIRPLUS, ",nordirplus", "" },
 		{ 0, NULL, NULL }
 	};
 	const struct proc_nfs_info *nfs_infop;
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 7975589..5d44b8b 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -38,7 +38,8 @@
 static struct nfs_page * nfs_update_request(struct nfs_open_context*,
 					    struct page *,
 					    unsigned int, unsigned int);
-static long nfs_flush_mapping(struct address_space *mapping, struct writeback_control *wbc, int how);
+static void nfs_pageio_init_write(struct nfs_pageio_descriptor *desc,
+				  struct inode *inode, int ioflags);
 static const struct rpc_call_ops nfs_write_partial_ops;
 static const struct rpc_call_ops nfs_write_full_ops;
 static const struct rpc_call_ops nfs_commit_ops;
@@ -71,9 +72,8 @@
 	call_rcu_bh(&wdata->task.u.tk_rcu, nfs_commit_rcu_free);
 }
 
-struct nfs_write_data *nfs_writedata_alloc(size_t len)
+struct nfs_write_data *nfs_writedata_alloc(unsigned int pagecount)
 {
-	unsigned int pagecount = (len + PAGE_SIZE - 1) >> PAGE_SHIFT;
 	struct nfs_write_data *p = mempool_alloc(nfs_wdata_mempool, GFP_NOFS);
 
 	if (p) {
@@ -139,7 +139,7 @@
 {
 	struct inode *inode = page->mapping->host;
 	loff_t end, i_size = i_size_read(inode);
-	unsigned long end_index = (i_size - 1) >> PAGE_CACHE_SHIFT;
+	pgoff_t end_index = (i_size - 1) >> PAGE_CACHE_SHIFT;
 
 	if (i_size > 0 && page->index < end_index)
 		return;
@@ -201,7 +201,7 @@
 static int wb_priority(struct writeback_control *wbc)
 {
 	if (wbc->for_reclaim)
-		return FLUSH_HIGHPRI;
+		return FLUSH_HIGHPRI | FLUSH_STABLE;
 	if (wbc->for_kupdate)
 		return FLUSH_LOWPRI;
 	return 0;
@@ -251,7 +251,8 @@
  * was not tagged.
  * May also return an error if the user signalled nfs_wait_on_request().
  */
-static int nfs_page_mark_flush(struct page *page)
+static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio,
+				struct page *page)
 {
 	struct nfs_page *req;
 	struct nfs_inode *nfsi = NFS_I(page->mapping->host);
@@ -273,6 +274,8 @@
 		 *	 request as dirty (in which case we don't care).
 		 */
 		spin_unlock(req_lock);
+		/* Prevent deadlock! */
+		nfs_pageio_complete(pgio);
 		ret = nfs_wait_on_request(req);
 		nfs_release_request(req);
 		if (ret != 0)
@@ -283,21 +286,18 @@
 		/* This request is marked for commit */
 		spin_unlock(req_lock);
 		nfs_unlock_request(req);
+		nfs_pageio_complete(pgio);
 		return 1;
 	}
-	if (nfs_set_page_writeback(page) == 0) {
-		nfs_list_remove_request(req);
-		/* add the request to the inode's dirty list. */
-		radix_tree_tag_set(&nfsi->nfs_page_tree,
-				req->wb_index, NFS_PAGE_TAG_DIRTY);
-		nfs_list_add_request(req, &nfsi->dirty);
-		nfsi->ndirty++;
+	if (nfs_set_page_writeback(page) != 0) {
 		spin_unlock(req_lock);
-		__mark_inode_dirty(page->mapping->host, I_DIRTY_PAGES);
-	} else
-		spin_unlock(req_lock);
+		BUG();
+	}
+	radix_tree_tag_set(&nfsi->nfs_page_tree, req->wb_index,
+			NFS_PAGE_TAG_WRITEBACK);
 	ret = test_bit(PG_NEED_FLUSH, &req->wb_flags);
-	nfs_unlock_request(req);
+	spin_unlock(req_lock);
+	nfs_pageio_add_request(pgio, req);
 	return ret;
 }
 
@@ -306,6 +306,7 @@
  */
 static int nfs_writepage_locked(struct page *page, struct writeback_control *wbc)
 {
+	struct nfs_pageio_descriptor mypgio, *pgio;
 	struct nfs_open_context *ctx;
 	struct inode *inode = page->mapping->host;
 	unsigned offset;
@@ -314,7 +315,14 @@
 	nfs_inc_stats(inode, NFSIOS_VFSWRITEPAGE);
 	nfs_add_stats(inode, NFSIOS_WRITEPAGES, 1);
 
-	err = nfs_page_mark_flush(page);
+	if (wbc->for_writepages)
+		pgio = wbc->fs_private;
+	else {
+		nfs_pageio_init_write(&mypgio, inode, wb_priority(wbc));
+		pgio = &mypgio;
+	}
+
+	err = nfs_page_async_flush(pgio, page);
 	if (err <= 0)
 		goto out;
 	err = 0;
@@ -331,12 +339,12 @@
 	put_nfs_open_context(ctx);
 	if (err != 0)
 		goto out;
-	err = nfs_page_mark_flush(page);
+	err = nfs_page_async_flush(pgio, page);
 	if (err > 0)
 		err = 0;
 out:
 	if (!wbc->for_writepages)
-		nfs_flush_mapping(page->mapping, wbc, FLUSH_STABLE|wb_priority(wbc));
+		nfs_pageio_complete(pgio);
 	return err;
 }
 
@@ -352,20 +360,20 @@
 int nfs_writepages(struct address_space *mapping, struct writeback_control *wbc)
 {
 	struct inode *inode = mapping->host;
+	struct nfs_pageio_descriptor pgio;
 	int err;
 
 	nfs_inc_stats(inode, NFSIOS_VFSWRITEPAGES);
 
+	nfs_pageio_init_write(&pgio, inode, wb_priority(wbc));
+	wbc->fs_private = &pgio;
 	err = generic_writepages(mapping, wbc);
+	nfs_pageio_complete(&pgio);
 	if (err)
 		return err;
-	err = nfs_flush_mapping(mapping, wbc, wb_priority(wbc));
-	if (err < 0)
-		goto out;
-	nfs_add_stats(inode, NFSIOS_WRITEPAGES, err);
-	err = 0;
-out:
-	return err;
+	if (pgio.pg_error)
+		return pgio.pg_error;
+	return 0;
 }
 
 /*
@@ -503,11 +511,11 @@
  *
  * Interruptible by signals only if mounted with intr flag.
  */
-static int nfs_wait_on_requests_locked(struct inode *inode, unsigned long idx_start, unsigned int npages)
+static int nfs_wait_on_requests_locked(struct inode *inode, pgoff_t idx_start, unsigned int npages)
 {
 	struct nfs_inode *nfsi = NFS_I(inode);
 	struct nfs_page *req;
-	unsigned long		idx_end, next;
+	pgoff_t idx_end, next;
 	unsigned int		res = 0;
 	int			error;
 
@@ -536,18 +544,6 @@
 	return res;
 }
 
-static void nfs_cancel_dirty_list(struct list_head *head)
-{
-	struct nfs_page *req;
-	while(!list_empty(head)) {
-		req = nfs_list_entry(head->next);
-		nfs_list_remove_request(req);
-		nfs_end_page_writeback(req->wb_page);
-		nfs_inode_remove_request(req);
-		nfs_clear_page_writeback(req);
-	}
-}
-
 static void nfs_cancel_commit_list(struct list_head *head)
 {
 	struct nfs_page *req;
@@ -574,7 +570,7 @@
  * The requests are *not* checked to ensure that they form a contiguous set.
  */
 static int
-nfs_scan_commit(struct inode *inode, struct list_head *dst, unsigned long idx_start, unsigned int npages)
+nfs_scan_commit(struct inode *inode, struct list_head *dst, pgoff_t idx_start, unsigned int npages)
 {
 	struct nfs_inode *nfsi = NFS_I(inode);
 	int res = 0;
@@ -588,40 +584,12 @@
 	return res;
 }
 #else
-static inline int nfs_scan_commit(struct inode *inode, struct list_head *dst, unsigned long idx_start, unsigned int npages)
+static inline int nfs_scan_commit(struct inode *inode, struct list_head *dst, pgoff_t idx_start, unsigned int npages)
 {
 	return 0;
 }
 #endif
 
-static int nfs_wait_on_write_congestion(struct address_space *mapping)
-{
-	struct inode *inode = mapping->host;
-	struct backing_dev_info *bdi = mapping->backing_dev_info;
-	int ret = 0;
-
-	might_sleep();
-
-	if (!bdi_write_congested(bdi))
-		return 0;
-
-	nfs_inc_stats(inode, NFSIOS_CONGESTIONWAIT);
-
-	do {
-		struct rpc_clnt *clnt = NFS_CLIENT(inode);
-		sigset_t oldset;
-
-		rpc_clnt_sigmask(clnt, &oldset);
-		ret = congestion_wait_interruptible(WRITE, HZ/10);
-		rpc_clnt_sigunmask(clnt, &oldset);
-		if (ret == -ERESTARTSYS)
-			break;
-		ret = 0;
-	} while (bdi_write_congested(bdi));
-
-	return ret;
-}
-
 /*
  * Try to update any existing write request, or create one if there is none.
  * In order to match, the request's credentials must match those of
@@ -636,12 +604,10 @@
 	struct inode *inode = mapping->host;
 	struct nfs_inode *nfsi = NFS_I(inode);
 	struct nfs_page		*req, *new = NULL;
-	unsigned long		rqend, end;
+	pgoff_t		rqend, end;
 
 	end = offset + bytes;
 
-	if (nfs_wait_on_write_congestion(mapping))
-		return ERR_PTR(-ERESTARTSYS);
 	for (;;) {
 		/* Loop over all inode entries and see if we find
 		 * A request for the page we wish to update
@@ -865,7 +831,7 @@
  * Generate multiple small requests to write out a single
  * contiguous dirty area on one page.
  */
-static int nfs_flush_multi(struct inode *inode, struct list_head *head, int how)
+static int nfs_flush_multi(struct inode *inode, struct list_head *head, unsigned int npages, size_t count, int how)
 {
 	struct nfs_page *req = nfs_list_entry(head->next);
 	struct page *page = req->wb_page;
@@ -877,11 +843,11 @@
 
 	nfs_list_remove_request(req);
 
-	nbytes = req->wb_bytes;
+	nbytes = count;
 	do {
 		size_t len = min(nbytes, wsize);
 
-		data = nfs_writedata_alloc(len);
+		data = nfs_writedata_alloc(1);
 		if (!data)
 			goto out_bad;
 		list_add(&data->pages, &list);
@@ -892,23 +858,19 @@
 
 	ClearPageError(page);
 	offset = 0;
-	nbytes = req->wb_bytes;
+	nbytes = count;
 	do {
 		data = list_entry(list.next, struct nfs_write_data, pages);
 		list_del_init(&data->pages);
 
 		data->pagevec[0] = page;
 
-		if (nbytes > wsize) {
-			nfs_write_rpcsetup(req, data, &nfs_write_partial_ops,
-					wsize, offset, how);
-			offset += wsize;
-			nbytes -= wsize;
-		} else {
-			nfs_write_rpcsetup(req, data, &nfs_write_partial_ops,
-					nbytes, offset, how);
-			nbytes = 0;
-		}
+		if (nbytes < wsize)
+			wsize = nbytes;
+		nfs_write_rpcsetup(req, data, &nfs_write_partial_ops,
+				   wsize, offset, how);
+		offset += wsize;
+		nbytes -= wsize;
 		nfs_execute_write(data);
 	} while (nbytes != 0);
 
@@ -934,26 +896,23 @@
  * This is the case if nfs_updatepage detects a conflicting request
  * that has been written but not committed.
  */
-static int nfs_flush_one(struct inode *inode, struct list_head *head, int how)
+static int nfs_flush_one(struct inode *inode, struct list_head *head, unsigned int npages, size_t count, int how)
 {
 	struct nfs_page		*req;
 	struct page		**pages;
 	struct nfs_write_data	*data;
-	unsigned int		count;
 
-	data = nfs_writedata_alloc(NFS_SERVER(inode)->wsize);
+	data = nfs_writedata_alloc(npages);
 	if (!data)
 		goto out_bad;
 
 	pages = data->pagevec;
-	count = 0;
 	while (!list_empty(head)) {
 		req = nfs_list_entry(head->next);
 		nfs_list_remove_request(req);
 		nfs_list_add_request(req, &data->pages);
 		ClearPageError(req->wb_page);
 		*pages++ = req->wb_page;
-		count += req->wb_bytes;
 	}
 	req = nfs_list_entry(data->pages.next);
 
@@ -973,40 +932,15 @@
 	return -ENOMEM;
 }
 
-static int nfs_flush_list(struct inode *inode, struct list_head *head, int npages, int how)
+static void nfs_pageio_init_write(struct nfs_pageio_descriptor *pgio,
+				  struct inode *inode, int ioflags)
 {
-	LIST_HEAD(one_request);
-	int (*flush_one)(struct inode *, struct list_head *, int);
-	struct nfs_page	*req;
-	int wpages = NFS_SERVER(inode)->wpages;
 	int wsize = NFS_SERVER(inode)->wsize;
-	int error;
 
-	flush_one = nfs_flush_one;
 	if (wsize < PAGE_CACHE_SIZE)
-		flush_one = nfs_flush_multi;
-	/* For single writes, FLUSH_STABLE is more efficient */
-	if (npages <= wpages && npages == NFS_I(inode)->npages
-			&& nfs_list_entry(head->next)->wb_bytes <= wsize)
-		how |= FLUSH_STABLE;
-
-	do {
-		nfs_coalesce_requests(head, &one_request, wpages);
-		req = nfs_list_entry(one_request.next);
-		error = flush_one(inode, &one_request, how);
-		if (error < 0)
-			goto out_err;
-	} while (!list_empty(head));
-	return 0;
-out_err:
-	while (!list_empty(head)) {
-		req = nfs_list_entry(head->next);
-		nfs_list_remove_request(req);
-		nfs_redirty_request(req);
-		nfs_end_page_writeback(req->wb_page);
-		nfs_clear_page_writeback(req);
-	}
-	return error;
+		nfs_pageio_init(pgio, inode, nfs_flush_multi, wsize, ioflags);
+	else
+		nfs_pageio_init(pgio, inode, nfs_flush_one, wsize, ioflags);
 }
 
 /*
@@ -1330,31 +1264,7 @@
 	.rpc_call_done = nfs_commit_done,
 	.rpc_release = nfs_commit_release,
 };
-#else
-static inline int nfs_commit_list(struct inode *inode, struct list_head *head, int how)
-{
-	return 0;
-}
-#endif
 
-static long nfs_flush_mapping(struct address_space *mapping, struct writeback_control *wbc, int how)
-{
-	struct nfs_inode *nfsi = NFS_I(mapping->host);
-	LIST_HEAD(head);
-	long res;
-
-	spin_lock(&nfsi->req_lock);
-	res = nfs_scan_dirty(mapping, wbc, &head);
-	spin_unlock(&nfsi->req_lock);
-	if (res) {
-		int error = nfs_flush_list(mapping->host, &head, res, how);
-		if (error < 0)
-			return error;
-	}
-	return res;
-}
-
-#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
 int nfs_commit_inode(struct inode *inode, int how)
 {
 	struct nfs_inode *nfsi = NFS_I(inode);
@@ -1371,13 +1281,18 @@
 	}
 	return res;
 }
+#else
+static inline int nfs_commit_list(struct inode *inode, struct list_head *head, int how)
+{
+	return 0;
+}
 #endif
 
 long nfs_sync_mapping_wait(struct address_space *mapping, struct writeback_control *wbc, int how)
 {
 	struct inode *inode = mapping->host;
 	struct nfs_inode *nfsi = NFS_I(inode);
-	unsigned long idx_start, idx_end;
+	pgoff_t idx_start, idx_end;
 	unsigned int npages = 0;
 	LIST_HEAD(head);
 	int nocommit = how & FLUSH_NOCOMMIT;
@@ -1390,41 +1305,24 @@
 		idx_start = wbc->range_start >> PAGE_CACHE_SHIFT;
 		idx_end = wbc->range_end >> PAGE_CACHE_SHIFT;
 		if (idx_end > idx_start) {
-			unsigned long l_npages = 1 + idx_end - idx_start;
+			pgoff_t l_npages = 1 + idx_end - idx_start;
 			npages = l_npages;
 			if (sizeof(npages) != sizeof(l_npages) &&
-					(unsigned long)npages != l_npages)
+					(pgoff_t)npages != l_npages)
 				npages = 0;
 		}
 	}
 	how &= ~FLUSH_NOCOMMIT;
 	spin_lock(&nfsi->req_lock);
 	do {
-		wbc->pages_skipped = 0;
 		ret = nfs_wait_on_requests_locked(inode, idx_start, npages);
 		if (ret != 0)
 			continue;
-		pages = nfs_scan_dirty(mapping, wbc, &head);
-		if (pages != 0) {
-			spin_unlock(&nfsi->req_lock);
-			if (how & FLUSH_INVALIDATE) {
-				nfs_cancel_dirty_list(&head);
-				ret = pages;
-			} else
-				ret = nfs_flush_list(inode, &head, pages, how);
-			spin_lock(&nfsi->req_lock);
-			continue;
-		}
-		if (wbc->pages_skipped != 0)
-			continue;
 		if (nocommit)
 			break;
 		pages = nfs_scan_commit(inode, &head, idx_start, npages);
-		if (pages == 0) {
-			if (wbc->pages_skipped != 0)
-				continue;
+		if (pages == 0)
 			break;
-		}
 		if (how & FLUSH_INVALIDATE) {
 			spin_unlock(&nfsi->req_lock);
 			nfs_cancel_commit_list(&head);
@@ -1456,7 +1354,7 @@
 	};
 	int ret;
 
-	ret = generic_writepages(mapping, &wbc);
+	ret = nfs_writepages(mapping, &wbc);
 	if (ret < 0)
 		goto out;
 	ret = nfs_sync_mapping_wait(mapping, &wbc, 0);
@@ -1479,11 +1377,9 @@
 	};
 	int ret;
 
-	if (!(how & FLUSH_NOWRITEPAGE)) {
-		ret = generic_writepages(mapping, &wbc);
-		if (ret < 0)
-			goto out;
-	}
+	ret = nfs_writepages(mapping, &wbc);
+	if (ret < 0)
+		goto out;
 	ret = nfs_sync_mapping_wait(mapping, &wbc, how);
 	if (ret >= 0)
 		return 0;
@@ -1506,7 +1402,7 @@
 	int ret;
 
 	BUG_ON(!PageLocked(page));
-	if (!(how & FLUSH_NOWRITEPAGE) && clear_page_dirty_for_io(page)) {
+	if (clear_page_dirty_for_io(page)) {
 		ret = nfs_writepage_locked(page, &wbc);
 		if (ret < 0)
 			goto out;
@@ -1531,10 +1427,18 @@
 
 int nfs_set_page_dirty(struct page *page)
 {
-	spinlock_t *req_lock = &NFS_I(page->mapping->host)->req_lock;
+	struct address_space *mapping = page->mapping;
+	struct inode *inode;
+	spinlock_t *req_lock;
 	struct nfs_page *req;
 	int ret;
 
+	if (!mapping)
+		goto out_raced;
+	inode = mapping->host;
+	if (!inode)
+		goto out_raced;
+	req_lock = &NFS_I(inode)->req_lock;
 	spin_lock(req_lock);
 	req = nfs_page_find_request_locked(page);
 	if (req != NULL) {
@@ -1547,6 +1451,8 @@
 	ret = __set_page_dirty_nobuffers(page);
 	spin_unlock(req_lock);
 	return ret;
+out_raced:
+	return !TestSetPageDirty(page);
 }
 
 
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
index fb14d68..32ffea0 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -315,16 +315,13 @@
 /*
  * RPC procedure tables
  */
-#ifndef MAX
-# define MAX(a, b)      (((a) > (b))? (a) : (b))
-#endif
-
 #define PROC(proc, call, argtype, restype)                              \
 [NFSPROC4_CLNT_##proc] = {                                      	\
         .p_proc   = NFSPROC4_CB_##call,					\
         .p_encode = (kxdrproc_t) nfs4_xdr_##argtype,                    \
         .p_decode = (kxdrproc_t) nfs4_xdr_##restype,                    \
-        .p_bufsiz = MAX(NFS4_##argtype##_sz,NFS4_##restype##_sz) << 2,  \
+        .p_arglen = NFS4_##argtype##_sz,                                \
+        .p_replen = NFS4_##restype##_sz,                                \
         .p_statidx = NFSPROC4_CB_##call,				\
 	.p_name   = #proc,                                              \
 }
diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c
index a0c8667..19712a7 100644
--- a/fs/ocfs2/alloc.c
+++ b/fs/ocfs2/alloc.c
@@ -2869,7 +2869,7 @@
 	tl = &tl_copy->id2.i_dealloc;
 	num_recs = le16_to_cpu(tl->tl_used);
 	mlog(0, "cleanup %u records from %llu\n", num_recs,
-	     (unsigned long long)tl_copy->i_blkno);
+	     (unsigned long long)le64_to_cpu(tl_copy->i_blkno));
 
 	mutex_lock(&tl_inode->i_mutex);
 	for(i = 0; i < num_recs; i++) {
@@ -3801,8 +3801,8 @@
 	fe = (struct ocfs2_dinode *) fe_bh->b_data;
 
 	mlog(0, "fe->i_clusters = %u, new_i_clusters = %u, fe->i_size ="
-	     "%llu\n", fe->i_clusters, new_i_clusters,
-	     (unsigned long long)fe->i_size);
+	     "%llu\n", le32_to_cpu(fe->i_clusters), new_i_clusters,
+	     (unsigned long long)le64_to_cpu(fe->i_size));
 
 	*tc = kzalloc(sizeof(struct ocfs2_truncate_context), GFP_KERNEL);
 	if (!(*tc)) {
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c
index 56963e6..8e7cafb5 100644
--- a/fs/ocfs2/aops.c
+++ b/fs/ocfs2/aops.c
@@ -78,7 +78,8 @@
 
 	if (!OCFS2_IS_VALID_DINODE(fe)) {
 		mlog(ML_ERROR, "Invalid dinode #%llu: signature = %.*s\n",
-		     (unsigned long long)fe->i_blkno, 7, fe->i_signature);
+		     (unsigned long long)le64_to_cpu(fe->i_blkno), 7,
+		     fe->i_signature);
 		goto bail;
 	}
 
@@ -939,9 +940,9 @@
  * Returns a negative error code or the number of bytes copied into
  * the page.
  */
-int ocfs2_write_data_page(struct inode *inode, handle_t *handle,
-			  u64 *p_blkno, struct page *page,
-			  struct ocfs2_write_ctxt *wc, int new)
+static int ocfs2_write_data_page(struct inode *inode, handle_t *handle,
+				 u64 *p_blkno, struct page *page,
+				 struct ocfs2_write_ctxt *wc, int new)
 {
 	int ret, copied = 0;
 	unsigned int from = 0, to = 0;
@@ -1086,7 +1087,7 @@
 	for(i = 0; i < numpages; i++) {
 		index = start + i;
 
-		cpages[i] = grab_cache_page(mapping, index);
+		cpages[i] = find_or_create_page(mapping, index, GFP_NOFS);
 		if (!cpages[i]) {
 			ret = -ENOMEM;
 			mlog_errno(ret);
diff --git a/fs/ocfs2/cluster/heartbeat.c b/fs/ocfs2/cluster/heartbeat.c
index eba282d..9791134 100644
--- a/fs/ocfs2/cluster/heartbeat.c
+++ b/fs/ocfs2/cluster/heartbeat.c
@@ -438,7 +438,7 @@
 								   hb_block));
 
 	mlog(ML_HB_BIO, "our node generation = 0x%llx, cksum = 0x%x\n",
-	     (long long)cpu_to_le64(generation),
+	     (long long)generation,
 	     le32_to_cpu(hb_block->hb_cksum));
 }
 
diff --git a/fs/ocfs2/cluster/masklog.c b/fs/ocfs2/cluster/masklog.c
index 636593b..2e975c0a 100644
--- a/fs/ocfs2/cluster/masklog.c
+++ b/fs/ocfs2/cluster/masklog.c
@@ -147,7 +147,7 @@
 	.kobj   = {.name = "logmask", .ktype = &mlog_ktype},
 };
 
-int mlog_sys_init(struct subsystem *o2cb_subsys)
+int mlog_sys_init(struct kset *o2cb_subsys)
 {
 	int i = 0;
 
@@ -157,7 +157,7 @@
 	}
 	mlog_attr_ptrs[i] = NULL;
 
-	mlog_kset.subsys = o2cb_subsys;
+	kobj_set_kset_s(&mlog_kset, o2cb_subsys);
 	return kset_register(&mlog_kset);
 }
 
diff --git a/fs/ocfs2/cluster/masklog.h b/fs/ocfs2/cluster/masklog.h
index a42628b..75cd877 100644
--- a/fs/ocfs2/cluster/masklog.h
+++ b/fs/ocfs2/cluster/masklog.h
@@ -278,7 +278,7 @@
 
 #include <linux/kobject.h>
 #include <linux/sysfs.h>
-int mlog_sys_init(struct subsystem *o2cb_subsys);
+int mlog_sys_init(struct kset *o2cb_subsys);
 void mlog_sys_shutdown(void);
 
 #endif /* O2CLUSTER_MASKLOG_H */
diff --git a/fs/ocfs2/cluster/sys.c b/fs/ocfs2/cluster/sys.c
index 1d9f6ac..64f6f37 100644
--- a/fs/ocfs2/cluster/sys.c
+++ b/fs/ocfs2/cluster/sys.c
@@ -42,7 +42,6 @@
 #define O2CB_ATTR(_name, _mode, _show, _store)	\
 struct o2cb_attribute o2cb_attr_##_name = __ATTR(_name, _mode, _show, _store)
 
-#define to_o2cb_subsys(k) container_of(to_kset(k), struct subsystem, kset)
 #define to_o2cb_attr(_attr) container_of(_attr, struct o2cb_attribute, attr)
 
 static ssize_t o2cb_interface_revision_show(char *buf)
@@ -79,7 +78,7 @@
 o2cb_show(struct kobject * kobj, struct attribute * attr, char * buffer)
 {
 	struct o2cb_attribute *o2cb_attr = to_o2cb_attr(attr);
-	struct subsystem *sbs = to_o2cb_subsys(kobj);
+	struct kset *sbs = to_kset(kobj);
 
 	BUG_ON(sbs != &o2cb_subsys);
 
@@ -93,7 +92,7 @@
 	     const char * buffer, size_t count)
 {
 	struct o2cb_attribute *o2cb_attr = to_o2cb_attr(attr);
-	struct subsystem *sbs = to_o2cb_subsys(kobj);
+	struct kset *sbs = to_kset(kobj);
 
 	BUG_ON(sbs != &o2cb_subsys);
 
@@ -112,7 +111,7 @@
 {
 	int ret;
 
-	o2cb_subsys.kset.kobj.ktype = &o2cb_subsys_type;
+	o2cb_subsys.kobj.ktype = &o2cb_subsys_type;
 	ret = subsystem_register(&o2cb_subsys);
 	if (ret)
 		return ret;
diff --git a/fs/ocfs2/cluster/tcp.c b/fs/ocfs2/cluster/tcp.c
index 69caf3e..0b229a9 100644
--- a/fs/ocfs2/cluster/tcp.c
+++ b/fs/ocfs2/cluster/tcp.c
@@ -1496,7 +1496,7 @@
 	sock->sk->sk_allocation = GFP_ATOMIC;
 
 	myaddr.sin_family = AF_INET;
-	myaddr.sin_addr.s_addr = (__force u32)mynode->nd_ipv4_address;
+	myaddr.sin_addr.s_addr = mynode->nd_ipv4_address;
 	myaddr.sin_port = (__force u16)htons(0); /* any port */
 
 	ret = sock->ops->bind(sock, (struct sockaddr *)&myaddr,
@@ -1521,8 +1521,8 @@
 	spin_unlock(&nn->nn_lock);
 
 	remoteaddr.sin_family = AF_INET;
-	remoteaddr.sin_addr.s_addr = (__force u32)node->nd_ipv4_address;
-	remoteaddr.sin_port = (__force u16)node->nd_ipv4_port;
+	remoteaddr.sin_addr.s_addr = node->nd_ipv4_address;
+	remoteaddr.sin_port = node->nd_ipv4_port;
 
 	ret = sc->sc_sock->ops->connect(sc->sc_sock,
 					(struct sockaddr *)&remoteaddr,
@@ -1810,8 +1810,8 @@
 	int ret;
 	struct sockaddr_in sin = {
 		.sin_family = PF_INET,
-		.sin_addr = { .s_addr = (__force u32)addr },
-		.sin_port = (__force u16)port,
+		.sin_addr = { .s_addr = addr },
+		.sin_port = port,
 	};
 
 	ret = sock_create(PF_INET, SOCK_STREAM, IPPROTO_TCP, &sock);
diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c
index 67e6866..c441ef1 100644
--- a/fs/ocfs2/dir.c
+++ b/fs/ocfs2/dir.c
@@ -403,7 +403,7 @@
 			    struct buffer_head **new_de_bh)
 {
 	int status = 0;
-	int credits, num_free_extents;
+	int credits, num_free_extents, drop_alloc_sem = 0;
 	loff_t dir_i_size;
 	struct ocfs2_dinode *fe = (struct ocfs2_dinode *) parent_fe_bh->b_data;
 	struct ocfs2_alloc_context *data_ac = NULL;
@@ -452,6 +452,9 @@
 		credits = OCFS2_SIMPLE_DIR_EXTEND_CREDITS;
 	}
 
+	down_write(&OCFS2_I(dir)->ip_alloc_sem);
+	drop_alloc_sem = 1;
+
 	handle = ocfs2_start_trans(osb, credits);
 	if (IS_ERR(handle)) {
 		status = PTR_ERR(handle);
@@ -497,6 +500,8 @@
 	*new_de_bh = new_bh;
 	get_bh(*new_de_bh);
 bail:
+	if (drop_alloc_sem)
+		up_write(&OCFS2_I(dir)->ip_alloc_sem);
 	if (handle)
 		ocfs2_commit_trans(osb, handle);
 
diff --git a/fs/ocfs2/dlm/dlmast.c b/fs/ocfs2/dlm/dlmast.c
index 241cad3..2fd8bde 100644
--- a/fs/ocfs2/dlm/dlmast.c
+++ b/fs/ocfs2/dlm/dlmast.c
@@ -312,8 +312,8 @@
 	    past->type != DLM_BAST) {
 		mlog(ML_ERROR, "Unknown ast type! %d, cookie=%u:%llu"
 		     "name=%.*s\n", past->type, 
-		     dlm_get_lock_cookie_node(be64_to_cpu(cookie)),
-		     dlm_get_lock_cookie_seq(be64_to_cpu(cookie)),
+		     dlm_get_lock_cookie_node(cookie),
+		     dlm_get_lock_cookie_seq(cookie),
 		     locklen, name);
 		ret = DLM_IVLOCKID;
 		goto leave;
@@ -324,8 +324,8 @@
 		mlog(0, "got %sast for unknown lockres! "
 		     "cookie=%u:%llu, name=%.*s, namelen=%u\n",
 		     past->type == DLM_AST ? "" : "b",
-		     dlm_get_lock_cookie_node(be64_to_cpu(cookie)),
-		     dlm_get_lock_cookie_seq(be64_to_cpu(cookie)),
+		     dlm_get_lock_cookie_node(cookie),
+		     dlm_get_lock_cookie_seq(cookie),
 		     locklen, name, locklen);
 		ret = DLM_IVLOCKID;
 		goto leave;
@@ -370,8 +370,8 @@
 
 	mlog(0, "got %sast for unknown lock!  cookie=%u:%llu, "
 	     "name=%.*s, namelen=%u\n", past->type == DLM_AST ? "" : "b", 
-	     dlm_get_lock_cookie_node(be64_to_cpu(cookie)),
-	     dlm_get_lock_cookie_seq(be64_to_cpu(cookie)),
+	     dlm_get_lock_cookie_node(cookie),
+	     dlm_get_lock_cookie_seq(cookie),
 	     locklen, name, locklen);
 
 	ret = DLM_NORMAL;
diff --git a/fs/ocfs2/dlm/dlmrecovery.c b/fs/ocfs2/dlm/dlmrecovery.c
index c1807a4..671c4ed5 100644
--- a/fs/ocfs2/dlm/dlmrecovery.c
+++ b/fs/ocfs2/dlm/dlmrecovery.c
@@ -1769,7 +1769,7 @@
 			/* lock is always created locally first, and
 			 * destroyed locally last.  it must be on the list */
 			if (!lock) {
-				u64 c = ml->cookie;
+				__be64 c = ml->cookie;
 				mlog(ML_ERROR, "could not find local lock "
 					       "with cookie %u:%llu!\n",
 				     dlm_get_lock_cookie_node(be64_to_cpu(c)),
@@ -1878,7 +1878,7 @@
 		spin_lock(&res->spinlock);
 		list_for_each_entry(lock, queue, list) {
 			if (lock->ml.cookie == ml->cookie) {
-				u64 c = lock->ml.cookie;
+				__be64 c = lock->ml.cookie;
 				mlog(ML_ERROR, "%s:%.*s: %u:%llu: lock already "
 				     "exists on this lockres!\n", dlm->name,
 				     res->lockname.len, res->lockname.name,
diff --git a/fs/ocfs2/dlm/dlmthread.c b/fs/ocfs2/dlm/dlmthread.c
index 2b264c6..cebd089 100644
--- a/fs/ocfs2/dlm/dlmthread.c
+++ b/fs/ocfs2/dlm/dlmthread.c
@@ -76,7 +76,7 @@
 		goto repeat;
 	}
 	remove_wait_queue(&res->wq, &wait);
-	current->state = TASK_RUNNING;
+	__set_current_state(TASK_RUNNING);
 }
 
 int __dlm_lockres_has_locks(struct dlm_lock_resource *res)
diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c
index 27e43b0..024777a 100644
--- a/fs/ocfs2/dlmglue.c
+++ b/fs/ocfs2/dlmglue.c
@@ -104,6 +104,35 @@
 static void ocfs2_dentry_post_unlock(struct ocfs2_super *osb,
 				     struct ocfs2_lock_res *lockres);
 
+
+#define mlog_meta_lvb(__level, __lockres) ocfs2_dump_meta_lvb_info(__level, __PRETTY_FUNCTION__, __LINE__, __lockres)
+
+/* This aids in debugging situations where a bad LVB might be involved. */
+static void ocfs2_dump_meta_lvb_info(u64 level,
+				     const char *function,
+				     unsigned int line,
+				     struct ocfs2_lock_res *lockres)
+{
+	struct ocfs2_meta_lvb *lvb = (struct ocfs2_meta_lvb *) lockres->l_lksb.lvb;
+
+	mlog(level, "LVB information for %s (called from %s:%u):\n",
+	     lockres->l_name, function, line);
+	mlog(level, "version: %u, clusters: %u, generation: 0x%x\n",
+	     lvb->lvb_version, be32_to_cpu(lvb->lvb_iclusters),
+	     be32_to_cpu(lvb->lvb_igeneration));
+	mlog(level, "size: %llu, uid %u, gid %u, mode 0x%x\n",
+	     (unsigned long long)be64_to_cpu(lvb->lvb_isize),
+	     be32_to_cpu(lvb->lvb_iuid), be32_to_cpu(lvb->lvb_igid),
+	     be16_to_cpu(lvb->lvb_imode));
+	mlog(level, "nlink %u, atime_packed 0x%llx, ctime_packed 0x%llx, "
+	     "mtime_packed 0x%llx iattr 0x%x\n", be16_to_cpu(lvb->lvb_inlink),
+	     (long long)be64_to_cpu(lvb->lvb_iatime_packed),
+	     (long long)be64_to_cpu(lvb->lvb_ictime_packed),
+	     (long long)be64_to_cpu(lvb->lvb_imtime_packed),
+	     be32_to_cpu(lvb->lvb_iattr));
+}
+
+
 /*
  * OCFS2 Lock Resource Operations
  *
@@ -3078,28 +3107,3 @@
 
 	mlog_exit_void();
 }
-
-/* This aids in debugging situations where a bad LVB might be involved. */
-void ocfs2_dump_meta_lvb_info(u64 level,
-			      const char *function,
-			      unsigned int line,
-			      struct ocfs2_lock_res *lockres)
-{
-	struct ocfs2_meta_lvb *lvb = (struct ocfs2_meta_lvb *) lockres->l_lksb.lvb;
-
-	mlog(level, "LVB information for %s (called from %s:%u):\n",
-	     lockres->l_name, function, line);
-	mlog(level, "version: %u, clusters: %u, generation: 0x%x\n",
-	     lvb->lvb_version, be32_to_cpu(lvb->lvb_iclusters),
-	     be32_to_cpu(lvb->lvb_igeneration));
-	mlog(level, "size: %llu, uid %u, gid %u, mode 0x%x\n",
-	     (unsigned long long)be64_to_cpu(lvb->lvb_isize),
-	     be32_to_cpu(lvb->lvb_iuid), be32_to_cpu(lvb->lvb_igid),
-	     be16_to_cpu(lvb->lvb_imode));
-	mlog(level, "nlink %u, atime_packed 0x%llx, ctime_packed 0x%llx, "
-	     "mtime_packed 0x%llx iattr 0x%x\n", be16_to_cpu(lvb->lvb_inlink),
-	     (long long)be64_to_cpu(lvb->lvb_iatime_packed),
-	     (long long)be64_to_cpu(lvb->lvb_ictime_packed),
-	     (long long)be64_to_cpu(lvb->lvb_imtime_packed),
-	     be32_to_cpu(lvb->lvb_iattr));
-}
diff --git a/fs/ocfs2/dlmglue.h b/fs/ocfs2/dlmglue.h
index 59cb566..492bad3 100644
--- a/fs/ocfs2/dlmglue.h
+++ b/fs/ocfs2/dlmglue.h
@@ -119,11 +119,4 @@
 struct ocfs2_dlm_debug *ocfs2_new_dlm_debug(void);
 void ocfs2_put_dlm_debug(struct ocfs2_dlm_debug *dlm_debug);
 
-/* aids in debugging and tracking lvbs */
-void ocfs2_dump_meta_lvb_info(u64 level,
-			      const char *function,
-			      unsigned int line,
-			      struct ocfs2_lock_res *lockres);
-#define mlog_meta_lvb(__level, __lockres) ocfs2_dump_meta_lvb_info(__level, __PRETTY_FUNCTION__, __LINE__, __lockres)
-
 #endif	/* DLMGLUE_H */
diff --git a/fs/ocfs2/export.c b/fs/ocfs2/export.c
index 56e1fef..bc48177 100644
--- a/fs/ocfs2/export.c
+++ b/fs/ocfs2/export.c
@@ -140,7 +140,7 @@
 	return parent;
 }
 
-static int ocfs2_encode_fh(struct dentry *dentry, __be32 *fh, int *max_len,
+static int ocfs2_encode_fh(struct dentry *dentry, u32 *fh_in, int *max_len,
 			   int connectable)
 {
 	struct inode *inode = dentry->d_inode;
@@ -148,6 +148,7 @@
 	int type = 1;
 	u64 blkno;
 	u32 generation;
+	__le32 *fh = (__force __le32 *) fh_in;
 
 	mlog_entry("(0x%p, '%.*s', 0x%p, %d, %d)\n", dentry,
 		   dentry->d_name.len, dentry->d_name.name,
@@ -199,7 +200,7 @@
 	return type;
 }
 
-static struct dentry *ocfs2_decode_fh(struct super_block *sb, __be32 *fh,
+static struct dentry *ocfs2_decode_fh(struct super_block *sb, u32 *fh_in,
 				      int fh_len, int fileid_type,
 				      int (*acceptable)(void *context,
 						        struct dentry *de),
@@ -207,6 +208,7 @@
 {
 	struct ocfs2_inode_handle handle, parent;
 	struct dentry *ret = NULL;
+	__le32 *fh = (__force __le32 *) fh_in;
 
 	mlog_entry("(0x%p, 0x%p, %d, %d, 0x%p, 0x%p)\n",
 		   sb, fh, fh_len, fileid_type, acceptable, context);
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
index 520a2a6..9395b4f 100644
--- a/fs/ocfs2/file.c
+++ b/fs/ocfs2/file.c
@@ -207,10 +207,10 @@
 	return ret;
 }
 
-int ocfs2_set_inode_size(handle_t *handle,
-			 struct inode *inode,
-			 struct buffer_head *fe_bh,
-			 u64 new_i_size)
+static int ocfs2_set_inode_size(handle_t *handle,
+				struct inode *inode,
+				struct buffer_head *fe_bh,
+				u64 new_i_size)
 {
 	int status;
 
@@ -713,7 +713,8 @@
 	}
 
 	mlog(0, "fe: i_clusters = %u, i_size=%llu\n",
-	     fe->i_clusters, (unsigned long long)fe->i_size);
+	     le32_to_cpu(fe->i_clusters),
+	     (unsigned long long)le64_to_cpu(fe->i_size));
 	mlog(0, "inode: ip_clusters=%u, i_size=%lld\n",
 	     OCFS2_I(inode)->ip_clusters, i_size_read(inode));
 
@@ -1853,6 +1854,9 @@
 	.aio_read	= ocfs2_file_aio_read,
 	.aio_write	= ocfs2_file_aio_write,
 	.ioctl		= ocfs2_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl   = ocfs2_compat_ioctl,
+#endif
 	.splice_read	= ocfs2_file_splice_read,
 	.splice_write	= ocfs2_file_splice_write,
 };
@@ -1862,4 +1866,7 @@
 	.readdir	= ocfs2_readdir,
 	.fsync		= ocfs2_sync_file,
 	.ioctl		= ocfs2_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl   = ocfs2_compat_ioctl,
+#endif
 };
diff --git a/fs/ocfs2/file.h b/fs/ocfs2/file.h
index 2c4460f..a4dd1fa 100644
--- a/fs/ocfs2/file.h
+++ b/fs/ocfs2/file.h
@@ -56,11 +56,6 @@
 int ocfs2_permission(struct inode *inode, int mask,
 		     struct nameidata *nd);
 
-int ocfs2_set_inode_size(handle_t *handle,
-			 struct inode *inode,
-			 struct buffer_head *fe_bh,
-			 u64 new_i_size);
-
 int ocfs2_should_update_atime(struct inode *inode,
 			      struct vfsmount *vfsmnt);
 int ocfs2_update_inode_atime(struct inode *inode,
diff --git a/fs/ocfs2/inode.c b/fs/ocfs2/inode.c
index 21a6050..bc844bf 100644
--- a/fs/ocfs2/inode.c
+++ b/fs/ocfs2/inode.c
@@ -89,6 +89,25 @@
 		inode->i_flags |= S_DIRSYNC;
 }
 
+/* Propagate flags from i_flags to OCFS2_I(inode)->ip_attr */
+void ocfs2_get_inode_flags(struct ocfs2_inode_info *oi)
+{
+	unsigned int flags = oi->vfs_inode.i_flags;
+
+	oi->ip_attr &= ~(OCFS2_SYNC_FL|OCFS2_APPEND_FL|
+			OCFS2_IMMUTABLE_FL|OCFS2_NOATIME_FL|OCFS2_DIRSYNC_FL);
+	if (flags & S_SYNC)
+		oi->ip_attr |= OCFS2_SYNC_FL;
+	if (flags & S_APPEND)
+		oi->ip_attr |= OCFS2_APPEND_FL;
+	if (flags & S_IMMUTABLE)
+		oi->ip_attr |= OCFS2_IMMUTABLE_FL;
+	if (flags & S_NOATIME)
+		oi->ip_attr |= OCFS2_NOATIME_FL;
+	if (flags & S_DIRSYNC)
+		oi->ip_attr |= OCFS2_DIRSYNC_FL;
+}
+
 struct inode *ocfs2_iget(struct ocfs2_super *osb, u64 blkno, int flags)
 {
 	struct inode *inode = NULL;
@@ -196,7 +215,7 @@
 	int status = -EINVAL;
 
 	mlog_entry("(0x%p, size:%llu)\n", inode,
-		   (unsigned long long)fe->i_size);
+		   (unsigned long long)le64_to_cpu(fe->i_size));
 
 	sb = inode->i_sb;
 	osb = OCFS2_SB(sb);
@@ -248,7 +267,7 @@
 		mlog(ML_ERROR,
 		     "ip_blkno %llu != i_blkno %llu!\n",
 		     (unsigned long long)OCFS2_I(inode)->ip_blkno,
-		     (unsigned long long)fe->i_blkno);
+		     (unsigned long long)le64_to_cpu(fe->i_blkno));
 
 	inode->i_nlink = le16_to_cpu(fe->i_links_count);
 
@@ -301,7 +320,7 @@
 		 * the generation argument to
 		 * ocfs2_inode_lock_res_init() will have to change.
 		 */
-		BUG_ON(fe->i_flags & cpu_to_le32(OCFS2_SYSTEM_FL));
+		BUG_ON(le32_to_cpu(fe->i_flags) & OCFS2_SYSTEM_FL);
 
 		ocfs2_inode_lock_res_init(&OCFS2_I(inode)->ip_meta_lockres,
 					  OCFS2_LOCK_TYPE_META, 0, inode);
@@ -437,7 +456,8 @@
 	fe = (struct ocfs2_dinode *) bh->b_data;
 	if (!OCFS2_IS_VALID_DINODE(fe)) {
 		mlog(ML_ERROR, "Invalid dinode #%llu: signature = %.*s\n",
-		     (unsigned long long)fe->i_blkno, 7, fe->i_signature);
+		     (unsigned long long)le64_to_cpu(fe->i_blkno), 7,
+		     fe->i_signature);
 		goto bail;
 	}
 
@@ -812,8 +832,8 @@
 		     "Inode %llu (on-disk %llu) not orphaned! "
 		     "Disk flags  0x%x, inode flags 0x%x\n",
 		     (unsigned long long)oi->ip_blkno,
-		     (unsigned long long)di->i_blkno, di->i_flags,
-		     oi->ip_flags);
+		     (unsigned long long)le64_to_cpu(di->i_blkno),
+		     le32_to_cpu(di->i_flags), oi->ip_flags);
 		goto bail;
 	}
 
@@ -1106,8 +1126,10 @@
 		return NULL;
 	}
 
+	down_read(&OCFS2_I(inode)->ip_alloc_sem);
 	tmperr = ocfs2_extent_map_get_blocks(inode, block, &p_blkno, NULL,
 					     NULL);
+	up_read(&OCFS2_I(inode)->ip_alloc_sem);
 	if (tmperr < 0) {
 		mlog_errno(tmperr);
 		goto fail;
@@ -1197,6 +1219,7 @@
 
 	spin_lock(&OCFS2_I(inode)->ip_lock);
 	fe->i_clusters = cpu_to_le32(OCFS2_I(inode)->ip_clusters);
+	ocfs2_get_inode_flags(OCFS2_I(inode));
 	fe->i_attr = cpu_to_le32(OCFS2_I(inode)->ip_attr);
 	spin_unlock(&OCFS2_I(inode)->ip_lock);
 
diff --git a/fs/ocfs2/inode.h b/fs/ocfs2/inode.h
index 03ae075..a41d081 100644
--- a/fs/ocfs2/inode.h
+++ b/fs/ocfs2/inode.h
@@ -141,6 +141,7 @@
 int ocfs2_aio_write(struct file *file, struct kiocb *req, struct iocb *iocb);
 
 void ocfs2_set_inode_flags(struct inode *inode);
+void ocfs2_get_inode_flags(struct ocfs2_inode_info *oi);
 
 static inline blkcnt_t ocfs2_inode_sector_count(struct inode *inode)
 {
diff --git a/fs/ocfs2/ioctl.c b/fs/ocfs2/ioctl.c
index 4768be5..f3ad21a 100644
--- a/fs/ocfs2/ioctl.c
+++ b/fs/ocfs2/ioctl.c
@@ -31,6 +31,7 @@
 		mlog_errno(status);
 		return status;
 	}
+	ocfs2_get_inode_flags(OCFS2_I(inode));
 	*flags = OCFS2_I(inode)->ip_attr;
 	ocfs2_meta_unlock(inode, 0);
 
@@ -134,3 +135,26 @@
 	}
 }
 
+#ifdef CONFIG_COMPAT
+long ocfs2_compat_ioctl(struct file *file, unsigned cmd, unsigned long arg)
+{
+	struct inode *inode = file->f_path.dentry->d_inode;
+	int ret;
+
+	switch (cmd) {
+	case OCFS2_IOC32_GETFLAGS:
+		cmd = OCFS2_IOC_GETFLAGS;
+		break;
+	case OCFS2_IOC32_SETFLAGS:
+		cmd = OCFS2_IOC_SETFLAGS;
+		break;
+	default:
+		return -ENOIOCTLCMD;
+	}
+
+	lock_kernel();
+	ret = ocfs2_ioctl(inode, file, cmd, arg);
+	unlock_kernel();
+	return ret;
+}
+#endif
diff --git a/fs/ocfs2/ioctl.h b/fs/ocfs2/ioctl.h
index 4a7c829..4d6c4f4 100644
--- a/fs/ocfs2/ioctl.h
+++ b/fs/ocfs2/ioctl.h
@@ -12,5 +12,6 @@
 
 int ocfs2_ioctl(struct inode * inode, struct file * filp,
 	unsigned int cmd, unsigned long arg);
+long ocfs2_compat_ioctl(struct file *file, unsigned cmd, unsigned long arg);
 
 #endif /* OCFS2_IOCTL_H */
diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c
index 5a8a90d..dc11880 100644
--- a/fs/ocfs2/journal.c
+++ b/fs/ocfs2/journal.c
@@ -435,7 +435,8 @@
 		 * handle the errors in a specific manner, so no need
 		 * to call ocfs2_error() here. */
 		mlog(ML_ERROR, "Journal dinode %llu  has invalid "
-		     "signature: %.*s", (unsigned long long)fe->i_blkno, 7,
+		     "signature: %.*s",
+		     (unsigned long long)le64_to_cpu(fe->i_blkno), 7,
 		     fe->i_signature);
 		status = -EIO;
 		goto out;
@@ -742,7 +743,7 @@
 		la_dinode = item->lri_la_dinode;
 		if (la_dinode) {
 			mlog(0, "Clean up local alloc %llu\n",
-			     (unsigned long long)la_dinode->i_blkno);
+			     (unsigned long long)le64_to_cpu(la_dinode->i_blkno));
 
 			ret = ocfs2_complete_local_alloc_recovery(osb,
 								  la_dinode);
@@ -755,7 +756,7 @@
 		tl_dinode = item->lri_tl_dinode;
 		if (tl_dinode) {
 			mlog(0, "Clean up truncate log %llu\n",
-			     (unsigned long long)tl_dinode->i_blkno);
+			     (unsigned long long)le64_to_cpu(tl_dinode->i_blkno));
 
 			ret = ocfs2_complete_truncate_log_recovery(osb,
 								   tl_dinode);
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c
index 2bcf353..36289e6 100644
--- a/fs/ocfs2/namei.c
+++ b/fs/ocfs2/namei.c
@@ -578,8 +578,9 @@
 	if (ocfs2_populate_inode(inode, fe, 1) < 0) {
 		mlog(ML_ERROR, "populate inode failed! bh->b_blocknr=%llu, "
 		     "i_blkno=%llu, i_ino=%lu\n",
-		     (unsigned long long) (*new_fe_bh)->b_blocknr,
-		     (unsigned long long)fe->i_blkno, inode->i_ino);
+		     (unsigned long long)(*new_fe_bh)->b_blocknr,
+		     (unsigned long long)le64_to_cpu(fe->i_blkno),
+		     inode->i_ino);
 		BUG();
 	}
 
diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h
index 82cc92d..a860633 100644
--- a/fs/ocfs2/ocfs2.h
+++ b/fs/ocfs2/ocfs2.h
@@ -363,9 +363,9 @@
 	typeof(__di) ____di = (__di);					\
 	ocfs2_error((__sb), 						\
 		"Dinode # %llu has bad signature %.*s",			\
-		(unsigned long long)(____di)->i_blkno, 7,		\
+		(unsigned long long)le64_to_cpu((____di)->i_blkno), 7, 	\
 		(____di)->i_signature);					\
-} while (0);
+} while (0)
 
 #define OCFS2_IS_VALID_EXTENT_BLOCK(ptr)				\
 	(!strcmp((ptr)->h_signature, OCFS2_EXTENT_BLOCK_SIGNATURE))
@@ -374,9 +374,9 @@
 	typeof(__eb) ____eb = (__eb);					\
 	ocfs2_error((__sb), 						\
 		"Extent Block # %llu has bad signature %.*s",		\
-		(unsigned long long)(____eb)->h_blkno, 7,		\
+		(unsigned long long)le64_to_cpu((____eb)->h_blkno), 7,	\
 		(____eb)->h_signature);					\
-} while (0);
+} while (0)
 
 #define OCFS2_IS_VALID_GROUP_DESC(ptr)					\
 	(!strcmp((ptr)->bg_signature, OCFS2_GROUP_DESC_SIGNATURE))
@@ -385,9 +385,9 @@
 	typeof(__gd) ____gd = (__gd);					\
 		ocfs2_error((__sb),					\
 		"Group Descriptor # %llu has bad signature %.*s",	\
-		(unsigned long long)(____gd)->bg_blkno, 7,		\
+		(unsigned long long)le64_to_cpu((____gd)->bg_blkno), 7, \
 		(____gd)->bg_signature);				\
-} while (0);
+} while (0)
 
 static inline unsigned long ino_from_blkno(struct super_block *sb,
 					   u64 blkno)
diff --git a/fs/ocfs2/ocfs2_fs.h b/fs/ocfs2/ocfs2_fs.h
index 7130647..f0d9eb0 100644
--- a/fs/ocfs2/ocfs2_fs.h
+++ b/fs/ocfs2/ocfs2_fs.h
@@ -166,6 +166,8 @@
  */
 #define OCFS2_IOC_GETFLAGS	_IOR('f', 1, long)
 #define OCFS2_IOC_SETFLAGS	_IOW('f', 2, long)
+#define OCFS2_IOC32_GETFLAGS	_IOR('f', 1, int)
+#define OCFS2_IOC32_SETFLAGS	_IOW('f', 2, int)
 
 /*
  * Journal Flags (ocfs2_dinode.id1.journal1.i_flags)
diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c
index 0da655a..e343762 100644
--- a/fs/ocfs2/suballoc.c
+++ b/fs/ocfs2/suballoc.c
@@ -849,9 +849,9 @@
 	}
 
 	mlog(0, "Suballoc %llu, chain %u, move group %llu to top, prev = %llu\n",
-	     (unsigned long long)fe->i_blkno, chain,
-	     (unsigned long long)bg->bg_blkno,
-	     (unsigned long long)prev_bg->bg_blkno);
+	     (unsigned long long)le64_to_cpu(fe->i_blkno), chain,
+	     (unsigned long long)le64_to_cpu(bg->bg_blkno),
+	     (unsigned long long)le64_to_cpu(prev_bg->bg_blkno));
 
 	fe_ptr = le64_to_cpu(fe->id2.i_chain.cl_recs[chain].c_blkno);
 	bg_ptr = le64_to_cpu(bg->bg_next_group);
@@ -1162,7 +1162,7 @@
 	}
 
 	mlog(0, "alloc succeeds: we give %u bits from block group %llu\n",
-	     tmp_bits, (unsigned long long)bg->bg_blkno);
+	     tmp_bits, (unsigned long long)le64_to_cpu(bg->bg_blkno));
 
 	*num_bits = tmp_bits;
 
@@ -1227,7 +1227,7 @@
 	}
 
 	mlog(0, "Allocated %u bits from suballocator %llu\n", *num_bits,
-	     (unsigned long long)fe->i_blkno);
+	     (unsigned long long)le64_to_cpu(fe->i_blkno));
 
 	*bg_blkno = le64_to_cpu(bg->bg_blkno);
 	*bits_left = le16_to_cpu(bg->bg_free_bits_count);
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c
index 5c9e824..f549354 100644
--- a/fs/ocfs2/super.c
+++ b/fs/ocfs2/super.c
@@ -1538,7 +1538,7 @@
 		} else if (bh->b_blocknr != le64_to_cpu(di->i_blkno)) {
 			mlog(ML_ERROR, "bad block number on superblock: "
 			     "found %llu, should be %llu\n",
-			     (unsigned long long)di->i_blkno,
+			     (unsigned long long)le64_to_cpu(di->i_blkno),
 			     (unsigned long long)bh->b_blocknr);
 		} else if (le32_to_cpu(di->id2.i_super.s_clustersize_bits) < 12 ||
 			    le32_to_cpu(di->id2.i_super.s_clustersize_bits) > 20) {
diff --git a/fs/partitions/check.c b/fs/partitions/check.c
index 8a7d003..f01572f 100644
--- a/fs/partitions/check.c
+++ b/fs/partitions/check.c
@@ -312,7 +312,7 @@
 	NULL,
 };
 
-extern struct subsystem block_subsys;
+extern struct kset block_subsys;
 
 static void part_release(struct kobject *kobj)
 {
@@ -388,7 +388,7 @@
 	kobject_add(&p->kobj);
 	if (!disk->part_uevent_suppress)
 		kobject_uevent(&p->kobj, KOBJ_ADD);
-	sysfs_create_link(&p->kobj, &block_subsys.kset.kobj, "subsystem");
+	sysfs_create_link(&p->kobj, &block_subsys.kobj, "subsystem");
 	if (flags & ADDPART_FLAG_WHOLEDISK) {
 		static struct attribute addpartattr = {
 			.name = "whole_disk",
@@ -444,7 +444,7 @@
 			goto err_out_dev_link;
 	}
 
-	err = sysfs_create_link(&disk->kobj, &block_subsys.kset.kobj,
+	err = sysfs_create_link(&disk->kobj, &block_subsys.kobj,
 				"subsystem");
 	if (err)
 		goto err_out_disk_name_lnk;
diff --git a/fs/sysfs/bin.c b/fs/sysfs/bin.c
index 8ea2a51..d3b9f5f 100644
--- a/fs/sysfs/bin.c
+++ b/fs/sysfs/bin.c
@@ -59,7 +59,7 @@
 	if (copy_to_user(userbuf, buffer, count))
 		return -EFAULT;
 
-	pr_debug("offs = %lld, *off = %lld, count = %d\n", offs, *off, count);
+	pr_debug("offs = %lld, *off = %lld, count = %zd\n", offs, *off, count);
 
 	*off = offs + count;
 
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index db0413a..0e637ad 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -13,8 +13,7 @@
 
 #include "sysfs.h"
 
-#define to_subsys(k) container_of(k,struct subsystem,kset.kobj)
-#define to_sattr(a) container_of(a,struct subsys_attribute,attr)
+#define to_sattr(a) container_of(a,struct subsys_attribute, attr)
 
 /*
  * Subsystem file operations.
@@ -24,12 +23,12 @@
 static ssize_t 
 subsys_attr_show(struct kobject * kobj, struct attribute * attr, char * page)
 {
-	struct subsystem * s = to_subsys(kobj);
+	struct kset *kset = to_kset(kobj);
 	struct subsys_attribute * sattr = to_sattr(attr);
 	ssize_t ret = -EIO;
 
 	if (sattr->show)
-		ret = sattr->show(s,page);
+		ret = sattr->show(kset, page);
 	return ret;
 }
 
@@ -37,12 +36,12 @@
 subsys_attr_store(struct kobject * kobj, struct attribute * attr, 
 		  const char * page, size_t count)
 {
-	struct subsystem * s = to_subsys(kobj);
+	struct kset *kset = to_kset(kobj);
 	struct subsys_attribute * sattr = to_sattr(attr);
 	ssize_t ret = -EIO;
 
 	if (sattr->store)
-		ret = sattr->store(s,page,count);
+		ret = sattr->store(kset, page, count);
 	return ret;
 }
 
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
index 0d9f984..16c3c44 100644
--- a/include/acpi/acpi_bus.h
+++ b/include/acpi/acpi_bus.h
@@ -316,7 +316,7 @@
 	u32 data;
 };
 
-extern struct subsystem acpi_subsys;
+extern struct kset acpi_subsys;
 
 /*
  * External Functions
diff --git a/include/asm-alpha/scatterlist.h b/include/asm-alpha/scatterlist.h
index 6afb8bd..9173654 100644
--- a/include/asm-alpha/scatterlist.h
+++ b/include/asm-alpha/scatterlist.h
@@ -2,6 +2,7 @@
 #define _ALPHA_SCATTERLIST_H
 
 #include <asm/page.h>
+#include <asm/types.h>
   
 struct scatterlist {
 	struct page *page;
diff --git a/include/asm-arm/arch-imx/mmc.h b/include/asm-arm/arch-imx/mmc.h
index 1937151..84c7269 100644
--- a/include/asm-arm/arch-imx/mmc.h
+++ b/include/asm-arm/arch-imx/mmc.h
@@ -1,7 +1,7 @@
 #ifndef ASMARM_ARCH_MMC_H
 #define ASMARM_ARCH_MMC_H
 
-#include <linux/mmc/protocol.h>
+#include <linux/mmc/host.h>
 
 struct imxmmc_platform_data {
 	int (*card_present)(void);
diff --git a/include/asm-arm/arch-ixp4xx/dma.h b/include/asm-arm/arch-ixp4xx/dma.h
index 789f7f5..2c7f532 100644
--- a/include/asm-arm/arch-ixp4xx/dma.h
+++ b/include/asm-arm/arch-ixp4xx/dma.h
@@ -12,7 +12,6 @@
 #define __ASM_ARCH_DMA_H
 
 #include <linux/device.h>
-#include <linux/pci.h>
 #include <asm/page.h>
 #include <asm/sizes.h>
 #include <asm/hardware.h>
diff --git a/include/asm-arm/arch-pxa/mmc.h b/include/asm-arm/arch-pxa/mmc.h
index a38a28c..ef4f570 100644
--- a/include/asm-arm/arch-pxa/mmc.h
+++ b/include/asm-arm/arch-pxa/mmc.h
@@ -1,7 +1,7 @@
 #ifndef ASMARM_ARCH_MMC_H
 #define ASMARM_ARCH_MMC_H
 
-#include <linux/mmc/protocol.h>
+#include <linux/mmc/host.h>
 #include <linux/interrupt.h>
 
 struct device;
diff --git a/include/asm-arm/arch-pxa/pxa27x_keyboard.h b/include/asm-arm/arch-pxa/pxa27x_keyboard.h
new file mode 100644
index 0000000..3aaff92
--- /dev/null
+++ b/include/asm-arm/arch-pxa/pxa27x_keyboard.h
@@ -0,0 +1,13 @@
+#define PXAKBD_MAXROW		8
+#define PXAKBD_MAXCOL		8
+
+struct pxa27x_keyboard_platform_data {
+	int nr_rows, nr_cols;
+	int keycodes[PXAKBD_MAXROW][PXAKBD_MAXCOL];
+	int gpio_modes[PXAKBD_MAXROW + PXAKBD_MAXCOL];
+
+#ifdef CONFIG_PM
+	u32 reg_kpc;
+	u32 reg_kprec;
+#endif
+};
diff --git a/include/asm-arm/mach/mmc.h b/include/asm-arm/mach/mmc.h
index 1b3555d..eb91145 100644
--- a/include/asm-arm/mach/mmc.h
+++ b/include/asm-arm/mach/mmc.h
@@ -4,7 +4,7 @@
 #ifndef ASMARM_MACH_MMC_H
 #define ASMARM_MACH_MMC_H
 
-#include <linux/mmc/protocol.h>
+#include <linux/mmc/host.h>
 
 struct mmc_platform_data {
 	unsigned int ocr_mask;			/* available voltages */
diff --git a/include/asm-avr32/scatterlist.h b/include/asm-avr32/scatterlist.h
index bfe7d75..c6d5ce3 100644
--- a/include/asm-avr32/scatterlist.h
+++ b/include/asm-avr32/scatterlist.h
@@ -1,6 +1,8 @@
 #ifndef __ASM_AVR32_SCATTERLIST_H
 #define __ASM_AVR32_SCATTERLIST_H
 
+#include <asm/types.h>
+
 struct scatterlist {
     struct page		*page;
     unsigned int	offset;
diff --git a/include/asm-frv/scatterlist.h b/include/asm-frv/scatterlist.h
index fb38fd3..8e827fa 100644
--- a/include/asm-frv/scatterlist.h
+++ b/include/asm-frv/scatterlist.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_SCATTERLIST_H
 #define _ASM_SCATTERLIST_H
 
+#include <asm/types.h>
+
 /*
  * Drivers must set either ->address or (preferred) ->page and ->offset
  * to indicate where data must be transferred to/from.
diff --git a/include/asm-h8300/scatterlist.h b/include/asm-h8300/scatterlist.h
index 7627f0c..985fdf5 100644
--- a/include/asm-h8300/scatterlist.h
+++ b/include/asm-h8300/scatterlist.h
@@ -1,6 +1,8 @@
 #ifndef _H8300_SCATTERLIST_H
 #define _H8300_SCATTERLIST_H
 
+#include <asm/types.h>
+
 struct scatterlist {
 	struct page	*page;
 	unsigned int	offset;
diff --git a/include/asm-i386/agp.h b/include/asm-i386/agp.h
index 9075083..6af173d 100644
--- a/include/asm-i386/agp.h
+++ b/include/asm-i386/agp.h
@@ -12,8 +12,10 @@
  * data corruption on some CPUs.
  */
 
-int map_page_into_agp(struct page *page);
-int unmap_page_from_agp(struct page *page);
+/* Caller's responsibility to call global_flush_tlb() for
+ * performance reasons */
+#define map_page_into_agp(page) change_page_attr(page, 1, PAGE_KERNEL_NOCACHE)
+#define unmap_page_from_agp(page) change_page_attr(page, 1, PAGE_KERNEL)
 #define flush_agp_mappings() global_flush_tlb()
 
 /* Could use CLFLUSH here if the cpu supports it. But then it would
diff --git a/include/asm-i386/scatterlist.h b/include/asm-i386/scatterlist.h
index 55d6c95..d7e45a8 100644
--- a/include/asm-i386/scatterlist.h
+++ b/include/asm-i386/scatterlist.h
@@ -1,6 +1,8 @@
 #ifndef _I386_SCATTERLIST_H
 #define _I386_SCATTERLIST_H
 
+#include <asm/types.h>
+
 struct scatterlist {
     struct page		*page;
     unsigned int	offset;
diff --git a/include/asm-i386/voyager.h b/include/asm-i386/voyager.h
index 5b27838..91a99329 100644
--- a/include/asm-i386/voyager.h
+++ b/include/asm-i386/voyager.h
@@ -487,15 +487,11 @@
 extern struct voyager_SUS *voyager_SUS;
 
 /* variables exported always */
+extern struct task_struct *voyager_thread;
 extern int voyager_level;
-extern int kvoyagerd_running;
-extern struct semaphore kvoyagerd_sem;
 extern struct voyager_status voyager_status;
 
-
-
 /* functions exported by the voyager and voyager_smp modules */
-
 extern int voyager_cat_readb(__u8 module, __u8 asic, int reg);
 extern void voyager_cat_init(void);
 extern void voyager_detect(struct voyager_bios_info *);
diff --git a/include/asm-ia64/scatterlist.h b/include/asm-ia64/scatterlist.h
index 9dbea88..a452ea2 100644
--- a/include/asm-ia64/scatterlist.h
+++ b/include/asm-ia64/scatterlist.h
@@ -6,6 +6,8 @@
  *	David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
  */
 
+#include <asm/types.h>
+
 struct scatterlist {
 	struct page *page;
 	unsigned int offset;
diff --git a/include/asm-m32r/scatterlist.h b/include/asm-m32r/scatterlist.h
index c2de96c..352415f 100644
--- a/include/asm-m32r/scatterlist.h
+++ b/include/asm-m32r/scatterlist.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_M32R_SCATTERLIST_H
 #define _ASM_M32R_SCATTERLIST_H
 
+#include <asm/types.h>
+
 struct scatterlist {
     char *  address;    /* Location data is to be transferred to, NULL for
                          * highmem page */
diff --git a/include/asm-m68k/adb.h b/include/asm-m68k/adb.h
deleted file mode 100644
index 9176b55..0000000
--- a/include/asm-m68k/adb.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Definitions for talking to ADB and CUDA.  The CUDA is a microcontroller
- * which controls the ADB, system power, RTC, and various other things on
- * later Macintoshes
- *
- * Copyright (C) 1996 Paul Mackerras.
- */
-
-/* First byte sent to or received from CUDA */
-#define ADB_PACKET	0
-#define CUDA_PACKET	1
-#define ERROR_PACKET	2
-#define TIMER_PACKET	3
-#define POWER_PACKET	4
-#define MACIIC_PACKET	5
-
-/* ADB commands (2nd byte) */
-#define ADB_BUSRESET		0
-#define ADB_FLUSH(id)		(1 + ((id) << 4))
-#define ADB_WRITEREG(id, reg)	(8 + (reg) + ((id) << 4))
-#define ADB_READREG(id, reg)	(0xc + (reg) + ((id) << 4))
-
-/* ADB default device IDs (upper 4 bits of 2nd byte) */
-#define ADB_DONGLE	1	/* "software execution control" devices */
-#define ADB_KEYBOARD	2
-#define ADB_MOUSE	3
-#define ADB_TABLET	4
-#define ADB_MODEM	5
-#define ADB_MISC	7	/* maybe a monitor */
-
-/* CUDA commands (2nd byte) */
-#define CUDA_WARM_START		0
-#define CUDA_AUTOPOLL		1
-#define CUDA_GET_6805_ADDR	2
-#define CUDA_GET_TIME		3
-#define CUDA_GET_PRAM		7
-#define CUDA_SET_6805_ADDR	8
-#define CUDA_SET_TIME		9
-#define CUDA_POWERDOWN		0xa
-#define CUDA_POWERUP_TIME	0xb
-#define CUDA_SET_PRAM		0xc
-#define CUDA_MS_RESET		0xd
-#define CUDA_SEND_DFAC		0xe
-#define CUDA_RESET_SYSTEM	0x11
-#define CUDA_SET_IPL		0x12
-#define CUDA_SET_AUTO_RATE	0x14
-#define CUDA_GET_AUTO_RATE	0x16
-#define CUDA_SET_DEVICE_LIST	0x19
-#define CUDA_GET_DEVICE_LIST	0x1a
-#define CUDA_GET_SET_IIC	0x22
-
-#ifdef __KERNEL__
-
-struct adb_request {
-    unsigned char data[16];
-    int nbytes;
-    unsigned char reply[16];
-    int reply_len;
-    unsigned char reply_expected;
-    unsigned char sent;
-    unsigned char got_reply;
-    void (*done)(struct adb_request *);
-    void *arg;
-    struct adb_request *next;
-};
-
-void via_adb_init(void);
-int adb_request(struct adb_request *req,
-		 void (*done)(struct adb_request *), int nbytes, ...);
-int adb_send_request(struct adb_request *req);
-void adb_poll(void);
-int adb_register(int default_id,
-		 void (*handler)(unsigned char *, int, struct pt_regs *));
-
-#endif	/* __KERNEL */
diff --git a/include/asm-m68k/atarikb.h b/include/asm-m68k/atarikb.h
index 1892605..546e7da 100644
--- a/include/asm-m68k/atarikb.h
+++ b/include/asm-m68k/atarikb.h
@@ -36,5 +36,11 @@
 extern void (*atari_MIDI_interrupt_hook) (void);
 /* Hook for mouse driver */
 extern void (*atari_mouse_interrupt_hook) (char *);
+/* Hook for keyboard inputdev  driver */
+extern void (*atari_input_keyboard_interrupt_hook) (unsigned char, char);
+/* Hook for mouse inputdev  driver */
+extern void (*atari_input_mouse_interrupt_hook) (char *);
+
+int atari_keyb_init(void);
 
 #endif /* _LINUX_ATARIKB_H */
diff --git a/include/asm-m68knommu/scatterlist.h b/include/asm-m68knommu/scatterlist.h
index 2085d6f..4da79d3 100644
--- a/include/asm-m68knommu/scatterlist.h
+++ b/include/asm-m68knommu/scatterlist.h
@@ -2,6 +2,7 @@
 #define _M68KNOMMU_SCATTERLIST_H
 
 #include <linux/mm.h>
+#include <asm/types.h>
 
 struct scatterlist {
 	struct page	*page;
diff --git a/include/asm-mips/scatterlist.h b/include/asm-mips/scatterlist.h
index 2263470..7af104c 100644
--- a/include/asm-mips/scatterlist.h
+++ b/include/asm-mips/scatterlist.h
@@ -1,6 +1,8 @@
 #ifndef __ASM_SCATTERLIST_H
 #define __ASM_SCATTERLIST_H
 
+#include <asm/types.h>
+
 struct scatterlist {
 	struct page *	page;
 	unsigned int	offset;
diff --git a/include/asm-parisc/scatterlist.h b/include/asm-parisc/scatterlist.h
index 236c1d0..e7211c7 100644
--- a/include/asm-parisc/scatterlist.h
+++ b/include/asm-parisc/scatterlist.h
@@ -2,6 +2,7 @@
 #define _ASM_PARISC_SCATTERLIST_H
 
 #include <asm/page.h>
+#include <asm/types.h>
 
 struct scatterlist {
 	struct page *page;
diff --git a/include/asm-powerpc/ps3av.h b/include/asm-powerpc/ps3av.h
index 43e90ea..9efc40f 100644
--- a/include/asm-powerpc/ps3av.h
+++ b/include/asm-powerpc/ps3av.h
@@ -18,8 +18,6 @@
 #ifndef _ASM_POWERPC_PS3AV_H_
 #define _ASM_POWERPC_PS3AV_H_
 
-#include <linux/mutex.h>
-
 /** command for ioctl() **/
 #define PS3AV_VERSION 0x205	/* version of ps3av command */
 
@@ -643,24 +641,6 @@
 	u8 buf[PS3AV_PKT_AVB_PARAM_MAX_BUF_SIZE];
 };
 
-struct ps3av {
-	int available;
-	struct semaphore sem;
-	struct semaphore ping;
-	struct semaphore pong;
-	struct mutex mutex;
-	int open_count;
-	struct ps3_vuart_port_device *dev;
-
-	int region;
-	struct ps3av_pkt_av_get_hw_conf av_hw_conf;
-	u32 av_port[PS3AV_AV_PORT_MAX + PS3AV_OPT_PORT_MAX];
-	u32 opt_port[PS3AV_OPT_PORT_MAX];
-	u32 head[PS3AV_HEAD_MAX];
-	u32 audio_port;
-	int ps3av_mode;
-	int ps3av_mode_old;
-};
 
 /** command status **/
 #define PS3AV_STATUS_SUCCESS			0x0000	/* success */
@@ -718,6 +698,7 @@
 extern int ps3av_cmd_video_get_monitor_info(struct ps3av_pkt_av_get_monitor_info *,
 					    u32);
 
+struct ps3_vuart_port_device;
 extern int ps3av_vuart_write(struct ps3_vuart_port_device *dev,
 			     const void *buf, unsigned long size);
 extern int ps3av_vuart_read(struct ps3_vuart_port_device *dev, void *buf,
@@ -725,6 +706,7 @@
 
 extern int ps3av_set_video_mode(u32, int);
 extern int ps3av_set_audio_mode(u32, u32, u32, u32, u32);
+extern int ps3av_get_auto_mode(int);
 extern int ps3av_set_mode(u32, int);
 extern int ps3av_get_mode(void);
 extern int ps3av_get_scanmode(int);
diff --git a/include/asm-s390/ccwdev.h b/include/asm-s390/ccwdev.h
index cfc8153..6795ece 100644
--- a/include/asm-s390/ccwdev.h
+++ b/include/asm-s390/ccwdev.h
@@ -164,9 +164,9 @@
 extern int ccw_device_halt(struct ccw_device *, unsigned long);
 extern int ccw_device_clear(struct ccw_device *, unsigned long);
 
-extern int read_dev_chars(struct ccw_device *cdev, void **buffer, int length);
-extern int read_conf_data(struct ccw_device *cdev, void **buffer, int *length);
-extern int read_conf_data_lpm(struct ccw_device *cdev, void **buffer,
+extern int __deprecated read_dev_chars(struct ccw_device *cdev, void **buffer, int length);
+extern int __deprecated read_conf_data(struct ccw_device *cdev, void **buffer, int *length);
+extern int __deprecated read_conf_data_lpm(struct ccw_device *cdev, void **buffer,
 			      int *length, __u8 lpm);
 
 extern int ccw_device_set_online(struct ccw_device *cdev);
diff --git a/include/asm-s390/elf.h b/include/asm-s390/elf.h
index c0d629d..91d0632 100644
--- a/include/asm-s390/elf.h
+++ b/include/asm-s390/elf.h
@@ -188,7 +188,8 @@
 /* This yields a mask that user programs can use to figure out what
    instruction set this CPU supports. */
 
-#define ELF_HWCAP (0)
+extern unsigned long elf_hwcap;
+#define ELF_HWCAP (elf_hwcap)
 
 /* This yields a string that ld.so will use to load implementation
    specific libraries for optimization.  This is more specific in
@@ -197,7 +198,9 @@
    For the moment, we have only optimizations for the Intel generations,
    but that could change... */
 
-#define ELF_PLATFORM (NULL)
+#define ELF_PLATFORM_SIZE 8
+extern char elf_platform[];
+#define ELF_PLATFORM (elf_platform)
 
 #ifndef __s390x__
 #define SET_PERSONALITY(ex, ibcs2) set_personality((ibcs2)?PER_SVR4:PER_LINUX)
diff --git a/include/asm-s390/kdebug.h b/include/asm-s390/kdebug.h
index 1b50f89..d2d7ad27 100644
--- a/include/asm-s390/kdebug.h
+++ b/include/asm-s390/kdebug.h
@@ -22,8 +22,21 @@
  */
 extern int register_die_notifier(struct notifier_block *);
 extern int unregister_die_notifier(struct notifier_block *);
-extern int register_page_fault_notifier(struct notifier_block *);
-extern int unregister_page_fault_notifier(struct notifier_block *);
+
+/*
+ * These are only here because kprobes.c wants them to implement a
+ * blatant layering violation. Will hopefully go away soon once all
+ * architectures are updated.
+ */
+static inline int register_page_fault_notifier(struct notifier_block *nb)
+{
+	return 0;
+}
+static inline int unregister_page_fault_notifier(struct notifier_block *nb)
+{
+	return 0;
+}
+
 extern struct atomic_notifier_head s390die_chain;
 
 enum die_val {
@@ -39,7 +52,6 @@
 	DIE_GPF,
 	DIE_CALL,
 	DIE_NMI_IPI,
-	DIE_PAGE_FAULT,
 };
 
 static inline int notify_die(enum die_val val, const char *str,
diff --git a/include/asm-s390/kprobes.h b/include/asm-s390/kprobes.h
index b847ff0..830fe4c 100644
--- a/include/asm-s390/kprobes.h
+++ b/include/asm-s390/kprobes.h
@@ -97,18 +97,10 @@
 int  is_prohibited_opcode(kprobe_opcode_t *instruction);
 void get_instruction_type(struct arch_specific_insn *ainsn);
 
+int kprobe_fault_handler(struct pt_regs *regs, int trapnr);
+int kprobe_exceptions_notify(struct notifier_block *self,
+	unsigned long val, void *data);
+
 #define flush_insn_slot(p)	do { } while (0)
 
 #endif	/* _ASM_S390_KPROBES_H */
-
-#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
diff --git a/include/asm-s390/lowcore.h b/include/asm-s390/lowcore.h
index ffc9788..801a6fd 100644
--- a/include/asm-s390/lowcore.h
+++ b/include/asm-s390/lowcore.h
@@ -229,17 +229,19 @@
 	__u16        subchannel_nr;            /* 0x0ba */
 	__u32        io_int_parm;              /* 0x0bc */
 	__u32        io_int_word;              /* 0x0c0 */
-        __u8         pad3[0xD4-0xC4];          /* 0x0c4 */
+	__u8	     pad3[0xc8-0xc4];	       /* 0x0c4 */
+	__u32	     stfl_fac_list;	       /* 0x0c8 */
+	__u8	     pad4[0xd4-0xcc];	       /* 0x0cc */
 	__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 */
-	__u8         pad4[0xf4-0xf0];          /* 0x0f0 */
+	__u8	     pad5[0xf4-0xf0];	       /* 0x0f0 */
 	__u32        external_damage_code;     /* 0x0f4 */
 	__u32        failing_storage_address;  /* 0x0f8 */
-	__u8         pad5[0x100-0xfc];         /* 0x0fc */
+	__u8	     pad6[0x100-0xfc];	       /* 0x0fc */
 	__u32        st_status_fixed_logout[4];/* 0x100 */
-	__u8         pad6[0x120-0x110];        /* 0x110 */
+	__u8	     pad7[0x120-0x110];        /* 0x110 */
 	__u32        access_regs_save_area[16];/* 0x120 */
 	__u32        floating_pt_save_area[8]; /* 0x160 */
 	__u32        gpregs_save_area[16];     /* 0x180 */
diff --git a/include/asm-sh/scatterlist.h b/include/asm-sh/scatterlist.h
index d19e7cd..b9ae53c 100644
--- a/include/asm-sh/scatterlist.h
+++ b/include/asm-sh/scatterlist.h
@@ -1,6 +1,8 @@
 #ifndef __ASM_SH_SCATTERLIST_H
 #define __ASM_SH_SCATTERLIST_H
 
+#include <asm/types.h>
+
 struct scatterlist {
     struct page * page; /* Location for highmem page, if any */
     unsigned int offset;/* for highmem, page offset */
diff --git a/include/asm-sh64/scatterlist.h b/include/asm-sh64/scatterlist.h
index 5d8fa32..1c723f2 100644
--- a/include/asm-sh64/scatterlist.h
+++ b/include/asm-sh64/scatterlist.h
@@ -11,6 +11,8 @@
 #ifndef __ASM_SH64_SCATTERLIST_H
 #define __ASM_SH64_SCATTERLIST_H
 
+#include <asm/types.h>
+
 struct scatterlist {
     struct page * page; /* Location for highmem page, if any */
     unsigned int offset;/* for highmem, page offset */
diff --git a/include/asm-sparc64/scatterlist.h b/include/asm-sparc64/scatterlist.h
index ec4f3c6..048fdb4 100644
--- a/include/asm-sparc64/scatterlist.h
+++ b/include/asm-sparc64/scatterlist.h
@@ -3,6 +3,7 @@
 #define _SPARC64_SCATTERLIST_H
 
 #include <asm/page.h>
+#include <asm/types.h>
 
 struct scatterlist {
 	struct page	*page;
diff --git a/include/asm-v850/scatterlist.h b/include/asm-v850/scatterlist.h
index af1cba6..56f4029 100644
--- a/include/asm-v850/scatterlist.h
+++ b/include/asm-v850/scatterlist.h
@@ -14,6 +14,8 @@
 #ifndef __V850_SCATTERLIST_H__
 #define __V850_SCATTERLIST_H__
 
+#include <asm/types.h>
+
 struct scatterlist {
 	struct page	*page;
 	unsigned	offset;
diff --git a/include/asm-x86_64/agp.h b/include/asm-x86_64/agp.h
index 06c52ee..de33866 100644
--- a/include/asm-x86_64/agp.h
+++ b/include/asm-x86_64/agp.h
@@ -10,8 +10,10 @@
  * with different cachability attributes for the same page.
  */
 
-int map_page_into_agp(struct page *page);
-int unmap_page_from_agp(struct page *page);
+/* Caller's responsibility to call global_flush_tlb() for
+ * performance reasons */
+#define map_page_into_agp(page) change_page_attr(page, 1, PAGE_KERNEL_NOCACHE)
+#define unmap_page_from_agp(page) change_page_attr(page, 1, PAGE_KERNEL)
 #define flush_agp_mappings() global_flush_tlb()
 
 /* Could use CLFLUSH here if the cpu supports it. But then it would
diff --git a/include/asm-x86_64/scatterlist.h b/include/asm-x86_64/scatterlist.h
index 49d89f8..eaf7ada 100644
--- a/include/asm-x86_64/scatterlist.h
+++ b/include/asm-x86_64/scatterlist.h
@@ -1,6 +1,8 @@
 #ifndef _X8664_SCATTERLIST_H
 #define _X8664_SCATTERLIST_H
 
+#include <asm/types.h>
+
 struct scatterlist {
     struct page		*page;
     unsigned int	offset;
diff --git a/include/asm-xtensa/scatterlist.h b/include/asm-xtensa/scatterlist.h
index 38a2b9a..ca337a2 100644
--- a/include/asm-xtensa/scatterlist.h
+++ b/include/asm-xtensa/scatterlist.h
@@ -11,6 +11,8 @@
 #ifndef _XTENSA_SCATTERLIST_H
 #define _XTENSA_SCATTERLIST_H
 
+#include <asm/types.h>
+
 struct scatterlist {
 	struct page 	*page;
 	unsigned int	offset;
diff --git a/include/crypto/algapi.h b/include/crypto/algapi.h
index 4e05e93..b2b1e6e 100644
--- a/include/crypto/algapi.h
+++ b/include/crypto/algapi.h
@@ -13,8 +13,11 @@
 #define _CRYPTO_ALGAPI_H
 
 #include <linux/crypto.h>
+#include <linux/list.h>
+#include <linux/kernel.h>
 
 struct module;
+struct rtattr;
 struct seq_file;
 
 struct crypto_type {
@@ -38,7 +41,7 @@
 	struct hlist_head instances;
 	struct module *module;
 
-	struct crypto_instance *(*alloc)(void *param, unsigned int len);
+	struct crypto_instance *(*alloc)(struct rtattr **tb);
 	void (*free)(struct crypto_instance *inst);
 
 	char name[CRYPTO_MAX_ALG_NAME];
@@ -48,6 +51,15 @@
 	struct list_head list;
 	struct crypto_alg *alg;
 	struct crypto_instance *inst;
+	u32 mask;
+};
+
+struct crypto_queue {
+	struct list_head list;
+	struct list_head *backlog;
+
+	unsigned int qlen;
+	unsigned int max_qlen;
 };
 
 struct scatter_walk {
@@ -81,6 +93,7 @@
 	int flags;
 };
 
+extern const struct crypto_type crypto_ablkcipher_type;
 extern const struct crypto_type crypto_blkcipher_type;
 extern const struct crypto_type crypto_hash_type;
 
@@ -91,16 +104,23 @@
 struct crypto_template *crypto_lookup_template(const char *name);
 
 int crypto_init_spawn(struct crypto_spawn *spawn, struct crypto_alg *alg,
-		      struct crypto_instance *inst);
+		      struct crypto_instance *inst, u32 mask);
 void crypto_drop_spawn(struct crypto_spawn *spawn);
 struct crypto_tfm *crypto_spawn_tfm(struct crypto_spawn *spawn, u32 type,
 				    u32 mask);
 
-struct crypto_alg *crypto_get_attr_alg(void *param, unsigned int len,
-				       u32 type, u32 mask);
+struct crypto_attr_type *crypto_get_attr_type(struct rtattr **tb);
+int crypto_check_attr_type(struct rtattr **tb, u32 type);
+struct crypto_alg *crypto_get_attr_alg(struct rtattr **tb, u32 type, u32 mask);
 struct crypto_instance *crypto_alloc_instance(const char *name,
 					      struct crypto_alg *alg);
 
+void crypto_init_queue(struct crypto_queue *queue, unsigned int max_qlen);
+int crypto_enqueue_request(struct crypto_queue *queue,
+			   struct crypto_async_request *request);
+struct crypto_async_request *crypto_dequeue_request(struct crypto_queue *queue);
+int crypto_tfm_in_queue(struct crypto_queue *queue, struct crypto_tfm *tfm);
+
 int blkcipher_walk_done(struct blkcipher_desc *desc,
 			struct blkcipher_walk *walk, int err);
 int blkcipher_walk_virt(struct blkcipher_desc *desc,
@@ -118,11 +138,37 @@
 	return (void *)ALIGN(addr, align);
 }
 
+static inline struct crypto_instance *crypto_tfm_alg_instance(
+	struct crypto_tfm *tfm)
+{
+	return container_of(tfm->__crt_alg, struct crypto_instance, alg);
+}
+
 static inline void *crypto_instance_ctx(struct crypto_instance *inst)
 {
 	return inst->__ctx;
 }
 
+static inline struct ablkcipher_alg *crypto_ablkcipher_alg(
+	struct crypto_ablkcipher *tfm)
+{
+	return &crypto_ablkcipher_tfm(tfm)->__crt_alg->cra_ablkcipher;
+}
+
+static inline void *crypto_ablkcipher_ctx(struct crypto_ablkcipher *tfm)
+{
+	return crypto_tfm_ctx(&tfm->base);
+}
+
+static inline struct crypto_blkcipher *crypto_spawn_blkcipher(
+	struct crypto_spawn *spawn)
+{
+	u32 type = CRYPTO_ALG_TYPE_BLKCIPHER;
+	u32 mask = CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_ASYNC;
+
+	return __crypto_blkcipher_cast(crypto_spawn_tfm(spawn, type, mask));
+}
+
 static inline void *crypto_blkcipher_ctx(struct crypto_blkcipher *tfm)
 {
 	return crypto_tfm_ctx(&tfm->base);
@@ -170,5 +216,35 @@
 	walk->total = nbytes;
 }
 
+static inline struct crypto_async_request *crypto_get_backlog(
+	struct crypto_queue *queue)
+{
+	return queue->backlog == &queue->list ? NULL :
+	       container_of(queue->backlog, struct crypto_async_request, list);
+}
+
+static inline int ablkcipher_enqueue_request(struct ablkcipher_alg *alg,
+					     struct ablkcipher_request *request)
+{
+	return crypto_enqueue_request(alg->queue, &request->base);
+}
+
+static inline struct ablkcipher_request *ablkcipher_dequeue_request(
+	struct ablkcipher_alg *alg)
+{
+	return ablkcipher_request_cast(crypto_dequeue_request(alg->queue));
+}
+
+static inline void *ablkcipher_request_ctx(struct ablkcipher_request *req)
+{
+	return req->__ctx;
+}
+
+static inline int ablkcipher_tfm_in_queue(struct crypto_ablkcipher *tfm)
+{
+	return crypto_tfm_in_queue(crypto_ablkcipher_alg(tfm)->queue,
+				   crypto_ablkcipher_tfm(tfm));
+}
+
 #endif	/* _CRYPTO_ALGAPI_H */
 
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index cb9b2ec..963051a 100644
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -265,7 +265,6 @@
 /*********************************************************************
  *                        CPUFREQ 2.6. INTERFACE                     *
  *********************************************************************/
-int cpufreq_set_policy(struct cpufreq_policy *policy);
 int cpufreq_get_policy(struct cpufreq_policy *policy, unsigned int cpu);
 int cpufreq_update_policy(unsigned int cpu);
 
diff --git a/include/linux/crypto.h b/include/linux/crypto.h
index 779aa78..0de7e2a 100644
--- a/include/linux/crypto.h
+++ b/include/linux/crypto.h
@@ -56,6 +56,7 @@
 
 #define CRYPTO_TFM_REQ_WEAK_KEY		0x00000100
 #define CRYPTO_TFM_REQ_MAY_SLEEP	0x00000200
+#define CRYPTO_TFM_REQ_MAY_BACKLOG	0x00000400
 #define CRYPTO_TFM_RES_WEAK_KEY		0x00100000
 #define CRYPTO_TFM_RES_BAD_KEY_LEN   	0x00200000
 #define CRYPTO_TFM_RES_BAD_KEY_SCHED 	0x00400000
@@ -88,11 +89,38 @@
 #endif
 
 struct scatterlist;
+struct crypto_ablkcipher;
+struct crypto_async_request;
 struct crypto_blkcipher;
 struct crypto_hash;
+struct crypto_queue;
 struct crypto_tfm;
 struct crypto_type;
 
+typedef void (*crypto_completion_t)(struct crypto_async_request *req, int err);
+
+struct crypto_async_request {
+	struct list_head list;
+	crypto_completion_t complete;
+	void *data;
+	struct crypto_tfm *tfm;
+
+	u32 flags;
+};
+
+struct ablkcipher_request {
+	struct crypto_async_request base;
+
+	unsigned int nbytes;
+
+	void *info;
+
+	struct scatterlist *src;
+	struct scatterlist *dst;
+
+	void *__ctx[] CRYPTO_MINALIGN_ATTR;
+};
+
 struct blkcipher_desc {
 	struct crypto_blkcipher *tfm;
 	void *info;
@@ -116,6 +144,19 @@
  * Algorithms: modular crypto algorithm implementations, managed
  * via crypto_register_alg() and crypto_unregister_alg().
  */
+struct ablkcipher_alg {
+	int (*setkey)(struct crypto_ablkcipher *tfm, const u8 *key,
+	              unsigned int keylen);
+	int (*encrypt)(struct ablkcipher_request *req);
+	int (*decrypt)(struct ablkcipher_request *req);
+
+	struct crypto_queue *queue;
+
+	unsigned int min_keysize;
+	unsigned int max_keysize;
+	unsigned int ivsize;
+};
+
 struct blkcipher_alg {
 	int (*setkey)(struct crypto_tfm *tfm, const u8 *key,
 	              unsigned int keylen);
@@ -170,6 +211,7 @@
 			      unsigned int slen, u8 *dst, unsigned int *dlen);
 };
 
+#define cra_ablkcipher	cra_u.ablkcipher
 #define cra_blkcipher	cra_u.blkcipher
 #define cra_cipher	cra_u.cipher
 #define cra_digest	cra_u.digest
@@ -194,6 +236,7 @@
 	const struct crypto_type *cra_type;
 
 	union {
+		struct ablkcipher_alg ablkcipher;
 		struct blkcipher_alg blkcipher;
 		struct cipher_alg cipher;
 		struct digest_alg digest;
@@ -232,6 +275,15 @@
  * crypto_free_*(), as well as the various helpers below.
  */
 
+struct ablkcipher_tfm {
+	int (*setkey)(struct crypto_ablkcipher *tfm, const u8 *key,
+	              unsigned int keylen);
+	int (*encrypt)(struct ablkcipher_request *req);
+	int (*decrypt)(struct ablkcipher_request *req);
+	unsigned int ivsize;
+	unsigned int reqsize;
+};
+
 struct blkcipher_tfm {
 	void *iv;
 	int (*setkey)(struct crypto_tfm *tfm, const u8 *key,
@@ -290,6 +342,7 @@
 	                      u8 *dst, unsigned int *dlen);
 };
 
+#define crt_ablkcipher	crt_u.ablkcipher
 #define crt_blkcipher	crt_u.blkcipher
 #define crt_cipher	crt_u.cipher
 #define crt_hash	crt_u.hash
@@ -300,6 +353,7 @@
 	u32 crt_flags;
 	
 	union {
+		struct ablkcipher_tfm ablkcipher;
 		struct blkcipher_tfm blkcipher;
 		struct cipher_tfm cipher;
 		struct hash_tfm hash;
@@ -311,6 +365,10 @@
 	void *__crt_ctx[] CRYPTO_MINALIGN_ATTR;
 };
 
+struct crypto_ablkcipher {
+	struct crypto_tfm base;
+};
+
 struct crypto_blkcipher {
 	struct crypto_tfm base;
 };
@@ -330,12 +388,21 @@
 enum {
 	CRYPTOA_UNSPEC,
 	CRYPTOA_ALG,
+	CRYPTOA_TYPE,
+	__CRYPTOA_MAX,
 };
 
+#define CRYPTOA_MAX (__CRYPTOA_MAX - 1)
+
 struct crypto_attr_alg {
 	char name[CRYPTO_MAX_ALG_NAME];
 };
 
+struct crypto_attr_type {
+	u32 type;
+	u32 mask;
+};
+
 /* 
  * Transform user interface.
  */
@@ -411,6 +478,167 @@
 /*
  * API wrappers.
  */
+static inline struct crypto_ablkcipher *__crypto_ablkcipher_cast(
+	struct crypto_tfm *tfm)
+{
+	return (struct crypto_ablkcipher *)tfm;
+}
+
+static inline struct crypto_ablkcipher *crypto_alloc_ablkcipher(
+	const char *alg_name, u32 type, u32 mask)
+{
+	type &= ~CRYPTO_ALG_TYPE_MASK;
+	type |= CRYPTO_ALG_TYPE_BLKCIPHER;
+	mask |= CRYPTO_ALG_TYPE_MASK;
+
+	return __crypto_ablkcipher_cast(
+		crypto_alloc_base(alg_name, type, mask));
+}
+
+static inline struct crypto_tfm *crypto_ablkcipher_tfm(
+	struct crypto_ablkcipher *tfm)
+{
+	return &tfm->base;
+}
+
+static inline void crypto_free_ablkcipher(struct crypto_ablkcipher *tfm)
+{
+	crypto_free_tfm(crypto_ablkcipher_tfm(tfm));
+}
+
+static inline int crypto_has_ablkcipher(const char *alg_name, u32 type,
+					u32 mask)
+{
+	type &= ~CRYPTO_ALG_TYPE_MASK;
+	type |= CRYPTO_ALG_TYPE_BLKCIPHER;
+	mask |= CRYPTO_ALG_TYPE_MASK;
+
+	return crypto_has_alg(alg_name, type, mask);
+}
+
+static inline struct ablkcipher_tfm *crypto_ablkcipher_crt(
+	struct crypto_ablkcipher *tfm)
+{
+	return &crypto_ablkcipher_tfm(tfm)->crt_ablkcipher;
+}
+
+static inline unsigned int crypto_ablkcipher_ivsize(
+	struct crypto_ablkcipher *tfm)
+{
+	return crypto_ablkcipher_crt(tfm)->ivsize;
+}
+
+static inline unsigned int crypto_ablkcipher_blocksize(
+	struct crypto_ablkcipher *tfm)
+{
+	return crypto_tfm_alg_blocksize(crypto_ablkcipher_tfm(tfm));
+}
+
+static inline unsigned int crypto_ablkcipher_alignmask(
+	struct crypto_ablkcipher *tfm)
+{
+	return crypto_tfm_alg_alignmask(crypto_ablkcipher_tfm(tfm));
+}
+
+static inline u32 crypto_ablkcipher_get_flags(struct crypto_ablkcipher *tfm)
+{
+	return crypto_tfm_get_flags(crypto_ablkcipher_tfm(tfm));
+}
+
+static inline void crypto_ablkcipher_set_flags(struct crypto_ablkcipher *tfm,
+					       u32 flags)
+{
+	crypto_tfm_set_flags(crypto_ablkcipher_tfm(tfm), flags);
+}
+
+static inline void crypto_ablkcipher_clear_flags(struct crypto_ablkcipher *tfm,
+						 u32 flags)
+{
+	crypto_tfm_clear_flags(crypto_ablkcipher_tfm(tfm), flags);
+}
+
+static inline int crypto_ablkcipher_setkey(struct crypto_ablkcipher *tfm,
+					   const u8 *key, unsigned int keylen)
+{
+	return crypto_ablkcipher_crt(tfm)->setkey(tfm, key, keylen);
+}
+
+static inline struct crypto_ablkcipher *crypto_ablkcipher_reqtfm(
+	struct ablkcipher_request *req)
+{
+	return __crypto_ablkcipher_cast(req->base.tfm);
+}
+
+static inline int crypto_ablkcipher_encrypt(struct ablkcipher_request *req)
+{
+	struct ablkcipher_tfm *crt =
+		crypto_ablkcipher_crt(crypto_ablkcipher_reqtfm(req));
+	return crt->encrypt(req);
+}
+
+static inline int crypto_ablkcipher_decrypt(struct ablkcipher_request *req)
+{
+	struct ablkcipher_tfm *crt =
+		crypto_ablkcipher_crt(crypto_ablkcipher_reqtfm(req));
+	return crt->decrypt(req);
+}
+
+static inline int crypto_ablkcipher_reqsize(struct crypto_ablkcipher *tfm)
+{
+	return crypto_ablkcipher_crt(tfm)->reqsize;
+}
+
+static inline void ablkcipher_request_set_tfm(
+	struct ablkcipher_request *req, struct crypto_ablkcipher *tfm)
+{
+	req->base.tfm = crypto_ablkcipher_tfm(tfm);
+}
+
+static inline struct ablkcipher_request *ablkcipher_request_cast(
+	struct crypto_async_request *req)
+{
+	return container_of(req, struct ablkcipher_request, base);
+}
+
+static inline struct ablkcipher_request *ablkcipher_request_alloc(
+	struct crypto_ablkcipher *tfm, gfp_t gfp)
+{
+	struct ablkcipher_request *req;
+
+	req = kmalloc(sizeof(struct ablkcipher_request) +
+		      crypto_ablkcipher_reqsize(tfm), gfp);
+
+	if (likely(req))
+		ablkcipher_request_set_tfm(req, tfm);
+
+	return req;
+}
+
+static inline void ablkcipher_request_free(struct ablkcipher_request *req)
+{
+	kfree(req);
+}
+
+static inline void ablkcipher_request_set_callback(
+	struct ablkcipher_request *req,
+	u32 flags, crypto_completion_t complete, void *data)
+{
+	req->base.complete = complete;
+	req->base.data = data;
+	req->base.flags = flags;
+}
+
+static inline void ablkcipher_request_set_crypt(
+	struct ablkcipher_request *req,
+	struct scatterlist *src, struct scatterlist *dst,
+	unsigned int nbytes, void *iv)
+{
+	req->src = src;
+	req->dst = dst;
+	req->nbytes = nbytes;
+	req->info = iv;
+}
+
 static inline struct crypto_blkcipher *__crypto_blkcipher_cast(
 	struct crypto_tfm *tfm)
 {
@@ -427,9 +655,9 @@
 static inline struct crypto_blkcipher *crypto_alloc_blkcipher(
 	const char *alg_name, u32 type, u32 mask)
 {
-	type &= ~CRYPTO_ALG_TYPE_MASK;
+	type &= ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_ASYNC);
 	type |= CRYPTO_ALG_TYPE_BLKCIPHER;
-	mask |= CRYPTO_ALG_TYPE_MASK;
+	mask |= CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_ASYNC;
 
 	return __crypto_blkcipher_cast(crypto_alloc_base(alg_name, type, mask));
 }
@@ -447,9 +675,9 @@
 
 static inline int crypto_has_blkcipher(const char *alg_name, u32 type, u32 mask)
 {
-	type &= ~CRYPTO_ALG_TYPE_MASK;
+	type &= ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_ASYNC);
 	type |= CRYPTO_ALG_TYPE_BLKCIPHER;
-	mask |= CRYPTO_ALG_TYPE_MASK;
+	mask |= CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_ASYNC;
 
 	return crypto_has_alg(alg_name, type, mask);
 }
diff --git a/include/linux/device.h b/include/linux/device.h
index a0cd2ce..6579068 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -53,7 +53,7 @@
 	const char		* name;
 	struct module		* owner;
 
-	struct subsystem	subsys;
+	struct kset		subsys;
 	struct kset		drivers;
 	struct kset		devices;
 	struct klist		klist_devices;
@@ -80,7 +80,6 @@
 	int (*resume)(struct device * dev);
 
 	unsigned int drivers_autoprobe:1;
-	unsigned int multithread_probe:1;
 };
 
 extern int __must_check bus_register(struct bus_type * bus);
@@ -179,7 +178,7 @@
 	const char		* name;
 	struct module		* owner;
 
-	struct subsystem	subsys;
+	struct kset		subsys;
 	struct list_head	children;
 	struct list_head	devices;
 	struct list_head	interfaces;
@@ -559,8 +558,8 @@
 
 
 /* drivers/base/firmware.c */
-extern int __must_check firmware_register(struct subsystem *);
-extern void firmware_unregister(struct subsystem *);
+extern int __must_check firmware_register(struct kset *);
+extern void firmware_unregister(struct kset *);
 
 /* debugging and troubleshooting/diagnostic helpers. */
 extern const char *dev_driver_string(struct device *dev);
diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
index c6310ae..f2d248f 100644
--- a/include/linux/ethtool.h
+++ b/include/linux/ethtool.h
@@ -434,6 +434,7 @@
 #define SUPPORTED_10000baseT_Full	(1 << 12)
 #define SUPPORTED_Pause			(1 << 13)
 #define SUPPORTED_Asym_Pause		(1 << 14)
+#define SUPPORTED_2500baseX_Full	(1 << 15)
 
 /* Indicates what features are advertised by the interface. */
 #define ADVERTISED_10baseT_Half		(1 << 0)
@@ -451,6 +452,7 @@
 #define ADVERTISED_10000baseT_Full	(1 << 12)
 #define ADVERTISED_Pause		(1 << 13)
 #define ADVERTISED_Asym_Pause		(1 << 14)
+#define ADVERTISED_2500baseX_Full	(1 << 15)
 
 /* The following are all involved in forcing a particular link
  * mode for the device for setting things.  When getting the
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 095a9c9..7c0077f 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1416,7 +1416,7 @@
 extern int vfs_statfs(struct dentry *, struct kstatfs *);
 
 /* /sys/fs */
-extern struct subsystem fs_subsys;
+extern struct kset fs_subsys;
 
 #define FLOCK_VERIFY_READ  1
 #define FLOCK_VERIFY_WRITE 2
diff --git a/include/linux/gpio_keys.h b/include/linux/gpio_keys.h
index 2b217c7..265d178 100644
--- a/include/linux/gpio_keys.h
+++ b/include/linux/gpio_keys.h
@@ -3,10 +3,11 @@
 
 struct gpio_keys_button {
 	/* Configuration parameters */
-	int keycode;
+	int code;		/* input event code (KEY_*, SW_*) */
 	int gpio;
 	int active_low;
 	char *desc;
+	int type;		/* input event type (EV_KEY, EV_SW) */
 };
 
 struct gpio_keys_platform_data {
diff --git a/include/linux/highmem.h b/include/linux/highmem.h
index bca8e2d..a515eb0 100644
--- a/include/linux/highmem.h
+++ b/include/linux/highmem.h
@@ -44,8 +44,13 @@
 
 #define kunmap(page) do { (void) (page); } while (0)
 
-#define kmap_atomic(page, idx) \
-	({ pagefault_disable(); page_address(page); })
+#include <asm/kmap_types.h>
+
+static inline void *kmap_atomic(struct page *page, enum km_type idx)
+{
+	pagefault_disable();
+	return page_address(page);
+}
 #define kmap_atomic_prot(page, idx, prot)	kmap_atomic(page, idx)
 
 #define kunmap_atomic(addr, idx)	do { pagefault_enable(); } while (0)
diff --git a/include/linux/hp_sdc.h b/include/linux/hp_sdc.h
index debd715..9db3d45 100644
--- a/include/linux/hp_sdc.h
+++ b/include/linux/hp_sdc.h
@@ -71,6 +71,7 @@
 	  struct semaphore *semaphore;	/* Semaphore to sleep on. */
 	} act;
 } hp_sdc_transaction;
+int __hp_sdc_enqueue_transaction(hp_sdc_transaction *this);
 int hp_sdc_enqueue_transaction(hp_sdc_transaction *this);
 int hp_sdc_dequeue_transaction(hp_sdc_transaction *this);
 
diff --git a/include/linux/i2c-algo-bit.h b/include/linux/i2c-algo-bit.h
index 937da70..9ee0f80 100644
--- a/include/linux/i2c-algo-bit.h
+++ b/include/linux/i2c-algo-bit.h
@@ -38,11 +38,14 @@
 	int  (*getscl) (void *data);
 
 	/* local settings */
-	int udelay;		/* half-clock-cycle time in microsecs */
-				/* i.e. clock is (500 / udelay) KHz */
+	int udelay;		/* half clock cycle time in us,
+				   minimum 2 us for fast-mode I2C,
+				   minimum 5 us for standard-mode I2C and SMBus,
+				   maximum 50 us for SMBus */
 	int timeout;		/* in jiffies */
 };
 
 int i2c_bit_add_bus(struct i2c_adapter *);
+int i2c_bit_add_numbered_bus(struct i2c_adapter *);
 
 #endif /* _LINUX_I2C_ALGO_BIT_H */
diff --git a/include/linux/i2c-gpio.h b/include/linux/i2c-gpio.h
new file mode 100644
index 0000000..c1bcb1f
--- /dev/null
+++ b/include/linux/i2c-gpio.h
@@ -0,0 +1,38 @@
+/*
+ * i2c-gpio interface to platform code
+ *
+ * Copyright (C) 2007 Atmel Corporation
+ *
+ * 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 _LINUX_I2C_GPIO_H
+#define _LINUX_I2C_GPIO_H
+
+/**
+ * struct i2c_gpio_platform_data - Platform-dependent data for i2c-gpio
+ * @sda_pin: GPIO pin ID to use for SDA
+ * @scl_pin: GPIO pin ID to use for SCL
+ * @udelay: signal toggle delay. SCL frequency is (500 / udelay) kHz
+ * @timeout: clock stretching timeout in jiffies. If the slave keeps
+ *	SCL low for longer than this, the transfer will time out.
+ * @sda_is_open_drain: SDA is configured as open drain, i.e. the pin
+ *	isn't actively driven high when setting the output value high.
+ *	gpio_get_value() must return the actual pin state even if the
+ *	pin is configured as an output.
+ * @scl_is_open_drain: SCL is set up as open drain. Same requirements
+ *	as for sda_is_open_drain apply.
+ * @scl_is_output_only: SCL output drivers cannot be turned off.
+ */
+struct i2c_gpio_platform_data {
+	unsigned int	sda_pin;
+	unsigned int	scl_pin;
+	int		udelay;
+	int		timeout;
+	unsigned int	sda_is_open_drain:1;
+	unsigned int	scl_is_open_drain:1;
+	unsigned int	scl_is_output_only:1;
+};
+
+#endif /* _LINUX_I2C_GPIO_H */
diff --git a/include/linux/i2c-id.h b/include/linux/i2c-id.h
index 9c21dc7..0e8da68 100644
--- a/include/linux/i2c-id.h
+++ b/include/linux/i2c-id.h
@@ -258,8 +258,9 @@
 /* --- MCP107 adapter */
 #define I2C_HW_MPC107		0x0d0000
 
-/* --- Marvell mv64xxx i2c adapter */
+/* --- Embedded adapters */
 #define I2C_HW_MV64XXX		0x190000
+#define I2C_HW_BLACKFIN		0x190001 /* ADI Blackfin I2C TWI driver */
 
 /* --- Miscellaneous adapters */
 #define I2C_HW_SAA7146		0x060000 /* SAA7146 video decoder bus */
diff --git a/include/linux/i2c.h b/include/linux/i2c.h
index 9428092..cae7d61 100644
--- a/include/linux/i2c.h
+++ b/include/linux/i2c.h
@@ -35,11 +35,6 @@
 #include <linux/sched.h>	/* for completion */
 #include <linux/mutex.h>
 
-/* --- For i2c-isa ---------------------------------------------------- */
-
-extern void i2c_adapter_dev_release(struct device *dev);
-extern struct device_driver i2c_adapter_driver;
-extern struct class i2c_adapter_class;
 extern struct bus_type i2c_bus_type;
 
 /* --- General options ------------------------------------------------	*/
@@ -87,6 +82,9 @@
 extern s32 i2c_smbus_read_word_data(struct i2c_client * client, u8 command);
 extern s32 i2c_smbus_write_word_data(struct i2c_client * client,
                                      u8 command, u16 value);
+/* Returns the number of read bytes */
+extern s32 i2c_smbus_read_block_data(struct i2c_client *client,
+				     u8 command, u8 *values);
 extern s32 i2c_smbus_write_block_data(struct i2c_client * client,
 				      u8 command, u8 length,
 				      const u8 *values);
@@ -114,7 +112,7 @@
 	 * can be used by the driver to test if the bus meets its conditions
 	 * & seek for the presence of the chip(s) it supports. If found, it
 	 * registers the client(s) that are on the bus to the i2c admin. via
-	 * i2c_attach_client.
+	 * i2c_attach_client.  (LEGACY I2C DRIVERS ONLY)
 	 */
 	int (*attach_adapter)(struct i2c_adapter *);
 	int (*detach_adapter)(struct i2c_adapter *);
@@ -122,10 +120,17 @@
 	/* tells the driver that a client is about to be deleted & gives it
 	 * the chance to remove its private data. Also, if the client struct
 	 * has been dynamically allocated by the driver in the function above,
-	 * it must be freed here.
+	 * it must be freed here.  (LEGACY I2C DRIVERS ONLY)
 	 */
 	int (*detach_client)(struct i2c_client *);
 
+	/* Standard driver model interfaces, for "new style" i2c drivers.
+	 * With the driver model, device enumeration is NEVER done by drivers;
+	 * it's done by infrastructure.  (NEW STYLE DRIVERS ONLY)
+	 */
+	int (*probe)(struct i2c_client *);
+	int (*remove)(struct i2c_client *);
+
 	/* driver model interfaces that don't relate to enumeration  */
 	void (*shutdown)(struct i2c_client *);
 	int (*suspend)(struct i2c_client *, pm_message_t mesg);
@@ -141,25 +146,34 @@
 };
 #define to_i2c_driver(d) container_of(d, struct i2c_driver, driver)
 
-#define I2C_NAME_SIZE	50
+#define I2C_NAME_SIZE	20
 
-/*
- * i2c_client identifies a single device (i.e. chip) that is connected to an
- * i2c bus. The behaviour is defined by the routines of the driver. This
- * function is mainly used for lookup & other admin. functions.
+/**
+ * struct i2c_client - represent an I2C slave device
+ * @addr: Address used on the I2C bus connected to the parent adapter.
+ * @name: Indicates the type of the device, usually a chip name that's
+ *	generic enough to hide second-sourcing and compatible revisions.
+ * @dev: Driver model device node for the slave.
+ * @driver_name: Identifies new-style driver used with this device; also
+ *	used as the module name for hotplug/coldplug modprobe support.
+ *
+ * An i2c_client identifies a single device (i.e. chip) connected to an
+ * i2c bus. The behaviour is defined by the routines of the driver.
  */
 struct i2c_client {
-	unsigned int flags;		/* div., see below		*/
+	unsigned short flags;		/* div., see below		*/
 	unsigned short addr;		/* chip address - NOTE: 7bit	*/
 					/* addresses are stored in the	*/
 					/* _LOWER_ 7 bits		*/
+	char name[I2C_NAME_SIZE];
 	struct i2c_adapter *adapter;	/* the adapter we sit on	*/
 	struct i2c_driver *driver;	/* and our access routines	*/
 	int usage_count;		/* How many accesses currently  */
 					/* to the client		*/
 	struct device dev;		/* the device structure		*/
+	int irq;			/* irq issued by device (or -1) */
+	char driver_name[KOBJ_NAME_LEN];
 	struct list_head list;
-	char name[I2C_NAME_SIZE];
 	struct completion released;
 };
 #define to_i2c_client(d) container_of(d, struct i2c_client, dev)
@@ -179,6 +193,76 @@
 	dev_set_drvdata (&dev->dev, data);
 }
 
+/**
+ * struct i2c_board_info - template for device creation
+ * @driver_name: identifies the driver to be bound to the device
+ * @type: optional chip type information, to initialize i2c_client.name
+ * @flags: to initialize i2c_client.flags
+ * @addr: stored in i2c_client.addr
+ * @platform_data: stored in i2c_client.dev.platform_data
+ * @irq: stored in i2c_client.irq
+
+ * I2C doesn't actually support hardware probing, although controllers and
+ * devices may be able to use I2C_SMBUS_QUICK to tell whether or not there's
+ * a device at a given address.  Drivers commonly need more information than
+ * that, such as chip type, configuration, associated IRQ, and so on.
+ *
+ * i2c_board_info is used to build tables of information listing I2C devices
+ * that are present.  This information is used to grow the driver model tree
+ * for "new style" I2C drivers.  For mainboards this is done statically using
+ * i2c_register_board_info(), where @bus_num represents an adapter that isn't
+ * yet available.  For add-on boards, i2c_new_device() does this dynamically
+ * with the adapter already known.
+ */
+struct i2c_board_info {
+	char		driver_name[KOBJ_NAME_LEN];
+	char		type[I2C_NAME_SIZE];
+	unsigned short	flags;
+	unsigned short	addr;
+	void		*platform_data;
+	int		irq;
+};
+
+/**
+ * I2C_BOARD_INFO - macro used to list an i2c device and its driver
+ * @driver: identifies the driver to use with the device
+ * @dev_addr: the device's address on the bus.
+ *
+ * This macro initializes essential fields of a struct i2c_board_info,
+ * declaring what has been provided on a particular board.  Optional
+ * fields (such as the chip type, its associated irq, or device-specific
+ * platform_data) are provided using conventional syntax.
+ */
+#define I2C_BOARD_INFO(driver,dev_addr) \
+	.driver_name = (driver), .addr = (dev_addr)
+
+
+/* Add-on boards should register/unregister their devices; e.g. a board
+ * with integrated I2C, a config eeprom, sensors, and a codec that's
+ * used in conjunction with the primary hardware.
+ */
+extern struct i2c_client *
+i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info);
+
+/* If you don't know the exact address of an I2C device, use this variant
+ * instead, which can probe for device presence in a list of possible
+ * addresses.
+ */
+extern struct i2c_client *
+i2c_new_probed_device(struct i2c_adapter *adap,
+		      struct i2c_board_info *info,
+		      unsigned short const *addr_list);
+
+extern void i2c_unregister_device(struct i2c_client *);
+
+/* Mainboard arch_initcall() code should register all its I2C devices.
+ * This is done at arch_initcall time, before declaring any i2c adapters.
+ * Modules for add-on boards must use other calls.
+ */
+extern int
+i2c_register_board_info(int busnum, struct i2c_board_info const *info, unsigned n);
+
+
 /*
  * The following structs are for those who like to implement new bus drivers:
  * i2c_algorithm is the interface to a class of hardware solutions which can
@@ -228,17 +312,14 @@
 	int timeout;
 	int retries;
 	struct device dev;		/* the adapter device */
-	struct class_device class_dev;	/* the class device */
 
 	int nr;
 	struct list_head clients;
 	struct list_head list;
-	char name[I2C_NAME_SIZE];
+	char name[48];
 	struct completion dev_released;
-	struct completion class_dev_released;
 };
-#define dev_to_i2c_adapter(d) container_of(d, struct i2c_adapter, dev)
-#define class_dev_to_i2c_adapter(d) container_of(d, struct i2c_adapter, class_dev)
+#define to_i2c_adapter(d) container_of(d, struct i2c_adapter, dev)
 
 static inline void *i2c_get_adapdata (struct i2c_adapter *dev)
 {
@@ -290,9 +371,10 @@
  */
 extern int i2c_add_adapter(struct i2c_adapter *);
 extern int i2c_del_adapter(struct i2c_adapter *);
+extern int i2c_add_numbered_adapter(struct i2c_adapter *);
 
 extern int i2c_register_driver(struct module *, struct i2c_driver *);
-extern int i2c_del_driver(struct i2c_driver *);
+extern void i2c_del_driver(struct i2c_driver *);
 
 static inline int i2c_add_driver(struct i2c_driver *driver)
 {
@@ -365,6 +447,7 @@
 #define I2C_M_REV_DIR_ADDR	0x2000
 #define I2C_M_IGNORE_NAK	0x1000
 #define I2C_M_NO_RD_ACK		0x0800
+#define I2C_M_RECV_LEN		0x0400 /* length will be first received byte */
 	__u16 len;		/* msg length				*/
 	__u8 *buf;		/* pointer to msg data			*/
 };
diff --git a/include/linux/ide.h b/include/linux/ide.h
index d3bbc71..418dfb5 100644
--- a/include/linux/ide.h
+++ b/include/linux/ide.h
@@ -613,7 +613,6 @@
 
         u8	quirk_list;	/* considered quirky, set for a specific host */
         u8	init_speed;	/* transfer rate set at boot */
-        u8	pio_speed;      /* unused by core, used by some drivers for fallback from DMA */
         u8	current_speed;	/* current transfer rate set */
 	u8	desired_speed;	/* desired transfer rate set */
         u8	dn;		/* now wide spread use */
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
new file mode 100644
index 0000000..ecd61e8
--- /dev/null
+++ b/include/linux/ieee80211.h
@@ -0,0 +1,342 @@
+/*
+ * IEEE 802.11 defines
+ *
+ * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
+ * <jkmaline@cc.hut.fi>
+ * Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
+ * Copyright (c) 2005, Devicescape Software, Inc.
+ * Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef IEEE80211_H
+#define IEEE80211_H
+
+#include <linux/types.h>
+
+#define FCS_LEN 4
+
+#define IEEE80211_FCTL_VERS		0x0003
+#define IEEE80211_FCTL_FTYPE		0x000c
+#define IEEE80211_FCTL_STYPE		0x00f0
+#define IEEE80211_FCTL_TODS		0x0100
+#define IEEE80211_FCTL_FROMDS		0x0200
+#define IEEE80211_FCTL_MOREFRAGS	0x0400
+#define IEEE80211_FCTL_RETRY		0x0800
+#define IEEE80211_FCTL_PM		0x1000
+#define IEEE80211_FCTL_MOREDATA		0x2000
+#define IEEE80211_FCTL_PROTECTED	0x4000
+#define IEEE80211_FCTL_ORDER		0x8000
+
+#define IEEE80211_SCTL_FRAG		0x000F
+#define IEEE80211_SCTL_SEQ		0xFFF0
+
+#define IEEE80211_FTYPE_MGMT		0x0000
+#define IEEE80211_FTYPE_CTL		0x0004
+#define IEEE80211_FTYPE_DATA		0x0008
+
+/* management */
+#define IEEE80211_STYPE_ASSOC_REQ	0x0000
+#define IEEE80211_STYPE_ASSOC_RESP	0x0010
+#define IEEE80211_STYPE_REASSOC_REQ	0x0020
+#define IEEE80211_STYPE_REASSOC_RESP	0x0030
+#define IEEE80211_STYPE_PROBE_REQ	0x0040
+#define IEEE80211_STYPE_PROBE_RESP	0x0050
+#define IEEE80211_STYPE_BEACON		0x0080
+#define IEEE80211_STYPE_ATIM		0x0090
+#define IEEE80211_STYPE_DISASSOC	0x00A0
+#define IEEE80211_STYPE_AUTH		0x00B0
+#define IEEE80211_STYPE_DEAUTH		0x00C0
+#define IEEE80211_STYPE_ACTION		0x00D0
+
+/* control */
+#define IEEE80211_STYPE_PSPOLL		0x00A0
+#define IEEE80211_STYPE_RTS		0x00B0
+#define IEEE80211_STYPE_CTS		0x00C0
+#define IEEE80211_STYPE_ACK		0x00D0
+#define IEEE80211_STYPE_CFEND		0x00E0
+#define IEEE80211_STYPE_CFENDACK	0x00F0
+
+/* data */
+#define IEEE80211_STYPE_DATA			0x0000
+#define IEEE80211_STYPE_DATA_CFACK		0x0010
+#define IEEE80211_STYPE_DATA_CFPOLL		0x0020
+#define IEEE80211_STYPE_DATA_CFACKPOLL		0x0030
+#define IEEE80211_STYPE_NULLFUNC		0x0040
+#define IEEE80211_STYPE_CFACK			0x0050
+#define IEEE80211_STYPE_CFPOLL			0x0060
+#define IEEE80211_STYPE_CFACKPOLL		0x0070
+#define IEEE80211_STYPE_QOS_DATA		0x0080
+#define IEEE80211_STYPE_QOS_DATA_CFACK		0x0090
+#define IEEE80211_STYPE_QOS_DATA_CFPOLL		0x00A0
+#define IEEE80211_STYPE_QOS_DATA_CFACKPOLL	0x00B0
+#define IEEE80211_STYPE_QOS_NULLFUNC		0x00C0
+#define IEEE80211_STYPE_QOS_CFACK		0x00D0
+#define IEEE80211_STYPE_QOS_CFPOLL		0x00E0
+#define IEEE80211_STYPE_QOS_CFACKPOLL		0x00F0
+
+
+/* miscellaneous IEEE 802.11 constants */
+#define IEEE80211_MAX_FRAG_THRESHOLD	2346
+#define IEEE80211_MAX_RTS_THRESHOLD	2347
+#define IEEE80211_MAX_AID		2007
+#define IEEE80211_MAX_TIM_LEN		251
+#define IEEE80211_MAX_DATA_LEN		2304
+/* Maximum size for the MA-UNITDATA primitive, 802.11 standard section
+   6.2.1.1.2.
+
+   The figure in section 7.1.2 suggests a body size of up to 2312
+   bytes is allowed, which is a bit confusing, I suspect this
+   represents the 2304 bytes of real data, plus a possible 8 bytes of
+   WEP IV and ICV. (this interpretation suggested by Ramiro Barreiro) */
+
+#define IEEE80211_MAX_SSID_LEN		32
+
+struct ieee80211_hdr {
+	__le16 frame_control;
+	__le16 duration_id;
+	u8 addr1[6];
+	u8 addr2[6];
+	u8 addr3[6];
+	__le16 seq_ctrl;
+	u8 addr4[6];
+} __attribute__ ((packed));
+
+
+struct ieee80211_mgmt {
+	__le16 frame_control;
+	__le16 duration;
+	u8 da[6];
+	u8 sa[6];
+	u8 bssid[6];
+	__le16 seq_ctrl;
+	union {
+		struct {
+			__le16 auth_alg;
+			__le16 auth_transaction;
+			__le16 status_code;
+			/* possibly followed by Challenge text */
+			u8 variable[0];
+		} __attribute__ ((packed)) auth;
+		struct {
+			__le16 reason_code;
+		} __attribute__ ((packed)) deauth;
+		struct {
+			__le16 capab_info;
+			__le16 listen_interval;
+			/* followed by SSID and Supported rates */
+			u8 variable[0];
+		} __attribute__ ((packed)) assoc_req;
+		struct {
+			__le16 capab_info;
+			__le16 status_code;
+			__le16 aid;
+			/* followed by Supported rates */
+			u8 variable[0];
+		} __attribute__ ((packed)) assoc_resp, reassoc_resp;
+		struct {
+			__le16 capab_info;
+			__le16 listen_interval;
+			u8 current_ap[6];
+			/* followed by SSID and Supported rates */
+			u8 variable[0];
+		} __attribute__ ((packed)) reassoc_req;
+		struct {
+			__le16 reason_code;
+		} __attribute__ ((packed)) disassoc;
+		struct {
+			__le64 timestamp;
+			__le16 beacon_int;
+			__le16 capab_info;
+			/* followed by some of SSID, Supported rates,
+			 * FH Params, DS Params, CF Params, IBSS Params, TIM */
+			u8 variable[0];
+		} __attribute__ ((packed)) beacon;
+		struct {
+			/* only variable items: SSID, Supported rates */
+			u8 variable[0];
+		} __attribute__ ((packed)) probe_req;
+		struct {
+			__le64 timestamp;
+			__le16 beacon_int;
+			__le16 capab_info;
+			/* followed by some of SSID, Supported rates,
+			 * FH Params, DS Params, CF Params, IBSS Params */
+			u8 variable[0];
+		} __attribute__ ((packed)) probe_resp;
+		struct {
+			u8 category;
+			union {
+				struct {
+					u8 action_code;
+					u8 dialog_token;
+					u8 status_code;
+					u8 variable[0];
+				} __attribute__ ((packed)) wme_action;
+				struct{
+					u8 action_code;
+					u8 element_id;
+					u8 length;
+					u8 switch_mode;
+					u8 new_chan;
+					u8 switch_count;
+				} __attribute__((packed)) chan_switch;
+			} u;
+		} __attribute__ ((packed)) action;
+	} u;
+} __attribute__ ((packed));
+
+
+/* Control frames */
+struct ieee80211_rts {
+	__le16 frame_control;
+	__le16 duration;
+	u8 ra[6];
+	u8 ta[6];
+} __attribute__ ((packed));
+
+struct ieee80211_cts {
+	__le16 frame_control;
+	__le16 duration;
+	u8 ra[6];
+} __attribute__ ((packed));
+
+
+/* Authentication algorithms */
+#define WLAN_AUTH_OPEN 0
+#define WLAN_AUTH_SHARED_KEY 1
+#define WLAN_AUTH_FAST_BSS_TRANSITION 2
+#define WLAN_AUTH_LEAP 128
+
+#define WLAN_AUTH_CHALLENGE_LEN 128
+
+#define WLAN_CAPABILITY_ESS		(1<<0)
+#define WLAN_CAPABILITY_IBSS		(1<<1)
+#define WLAN_CAPABILITY_CF_POLLABLE	(1<<2)
+#define WLAN_CAPABILITY_CF_POLL_REQUEST	(1<<3)
+#define WLAN_CAPABILITY_PRIVACY		(1<<4)
+#define WLAN_CAPABILITY_SHORT_PREAMBLE	(1<<5)
+#define WLAN_CAPABILITY_PBCC		(1<<6)
+#define WLAN_CAPABILITY_CHANNEL_AGILITY	(1<<7)
+/* 802.11h */
+#define WLAN_CAPABILITY_SPECTRUM_MGMT	(1<<8)
+#define WLAN_CAPABILITY_QOS		(1<<9)
+#define WLAN_CAPABILITY_SHORT_SLOT_TIME	(1<<10)
+#define WLAN_CAPABILITY_DSSS_OFDM	(1<<13)
+
+/* Status codes */
+enum ieee80211_statuscode {
+	WLAN_STATUS_SUCCESS = 0,
+	WLAN_STATUS_UNSPECIFIED_FAILURE = 1,
+	WLAN_STATUS_CAPS_UNSUPPORTED = 10,
+	WLAN_STATUS_REASSOC_NO_ASSOC = 11,
+	WLAN_STATUS_ASSOC_DENIED_UNSPEC = 12,
+	WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG = 13,
+	WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION = 14,
+	WLAN_STATUS_CHALLENGE_FAIL = 15,
+	WLAN_STATUS_AUTH_TIMEOUT = 16,
+	WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA = 17,
+	WLAN_STATUS_ASSOC_DENIED_RATES = 18,
+	/* 802.11b */
+	WLAN_STATUS_ASSOC_DENIED_NOSHORTPREAMBLE = 19,
+	WLAN_STATUS_ASSOC_DENIED_NOPBCC = 20,
+	WLAN_STATUS_ASSOC_DENIED_NOAGILITY = 21,
+	/* 802.11h */
+	WLAN_STATUS_ASSOC_DENIED_NOSPECTRUM = 22,
+	WLAN_STATUS_ASSOC_REJECTED_BAD_POWER = 23,
+	WLAN_STATUS_ASSOC_REJECTED_BAD_SUPP_CHAN = 24,
+	/* 802.11g */
+	WLAN_STATUS_ASSOC_DENIED_NOSHORTTIME = 25,
+	WLAN_STATUS_ASSOC_DENIED_NODSSSOFDM = 26,
+	/* 802.11i */
+	WLAN_STATUS_INVALID_IE = 40,
+	WLAN_STATUS_INVALID_GROUP_CIPHER = 41,
+	WLAN_STATUS_INVALID_PAIRWISE_CIPHER = 42,
+	WLAN_STATUS_INVALID_AKMP = 43,
+	WLAN_STATUS_UNSUPP_RSN_VERSION = 44,
+	WLAN_STATUS_INVALID_RSN_IE_CAP = 45,
+	WLAN_STATUS_CIPHER_SUITE_REJECTED = 46,
+};
+
+
+/* Reason codes */
+enum ieee80211_reasoncode {
+	WLAN_REASON_UNSPECIFIED = 1,
+	WLAN_REASON_PREV_AUTH_NOT_VALID = 2,
+	WLAN_REASON_DEAUTH_LEAVING = 3,
+	WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY = 4,
+	WLAN_REASON_DISASSOC_AP_BUSY = 5,
+	WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA = 6,
+	WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA = 7,
+	WLAN_REASON_DISASSOC_STA_HAS_LEFT = 8,
+	WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH = 9,
+	/* 802.11h */
+	WLAN_REASON_DISASSOC_BAD_POWER = 10,
+	WLAN_REASON_DISASSOC_BAD_SUPP_CHAN = 11,
+	/* 802.11i */
+	WLAN_REASON_INVALID_IE = 13,
+	WLAN_REASON_MIC_FAILURE = 14,
+	WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT = 15,
+	WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT = 16,
+	WLAN_REASON_IE_DIFFERENT = 17,
+	WLAN_REASON_INVALID_GROUP_CIPHER = 18,
+	WLAN_REASON_INVALID_PAIRWISE_CIPHER = 19,
+	WLAN_REASON_INVALID_AKMP = 20,
+	WLAN_REASON_UNSUPP_RSN_VERSION = 21,
+	WLAN_REASON_INVALID_RSN_IE_CAP = 22,
+	WLAN_REASON_IEEE8021X_FAILED = 23,
+	WLAN_REASON_CIPHER_SUITE_REJECTED = 24,
+};
+
+
+/* Information Element IDs */
+enum ieee80211_eid {
+	WLAN_EID_SSID = 0,
+	WLAN_EID_SUPP_RATES = 1,
+	WLAN_EID_FH_PARAMS = 2,
+	WLAN_EID_DS_PARAMS = 3,
+	WLAN_EID_CF_PARAMS = 4,
+	WLAN_EID_TIM = 5,
+	WLAN_EID_IBSS_PARAMS = 6,
+	WLAN_EID_CHALLENGE = 16,
+	/* 802.11d */
+	WLAN_EID_COUNTRY = 7,
+	WLAN_EID_HP_PARAMS = 8,
+	WLAN_EID_HP_TABLE = 9,
+	WLAN_EID_REQUEST = 10,
+	/* 802.11h */
+	WLAN_EID_PWR_CONSTRAINT = 32,
+	WLAN_EID_PWR_CAPABILITY = 33,
+	WLAN_EID_TPC_REQUEST = 34,
+	WLAN_EID_TPC_REPORT = 35,
+	WLAN_EID_SUPPORTED_CHANNELS = 36,
+	WLAN_EID_CHANNEL_SWITCH = 37,
+	WLAN_EID_MEASURE_REQUEST = 38,
+	WLAN_EID_MEASURE_REPORT = 39,
+	WLAN_EID_QUIET = 40,
+	WLAN_EID_IBSS_DFS = 41,
+	/* 802.11g */
+	WLAN_EID_ERP_INFO = 42,
+	WLAN_EID_EXT_SUPP_RATES = 50,
+	/* 802.11i */
+	WLAN_EID_RSN = 48,
+	WLAN_EID_WPA = 221,
+	WLAN_EID_GENERIC = 221,
+	WLAN_EID_VENDOR_SPECIFIC = 221,
+	WLAN_EID_QOS_PARAMETER = 222
+};
+
+/* cipher suite selectors */
+#define WLAN_CIPHER_SUITE_USE_GROUP	0x000FAC00
+#define WLAN_CIPHER_SUITE_WEP40		0x000FAC01
+#define WLAN_CIPHER_SUITE_TKIP		0x000FAC02
+/* reserved: 				0x000FAC03 */
+#define WLAN_CIPHER_SUITE_CCMP		0x000FAC04
+#define WLAN_CIPHER_SUITE_WEP104	0x000FAC05
+
+#define WLAN_MAX_KEY_LEN		32
+
+#endif /* IEEE80211_H */
diff --git a/include/linux/input-polldev.h b/include/linux/input-polldev.h
new file mode 100644
index 0000000..597a007
--- /dev/null
+++ b/include/linux/input-polldev.h
@@ -0,0 +1,46 @@
+#ifndef _INPUT_POLLDEV_H
+#define _INPUT_POLLDEV_H
+
+/*
+ * Copyright (c) 2007 Dmitry Torokhov
+ *
+ * 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/input.h>
+#include <linux/workqueue.h>
+
+/**
+ * struct input_polled_dev - simple polled input device
+ * @private: private driver data
+ * @flush: driver-supplied method that flushes device's state upon
+ *	opening (optional)
+ * @poll: driver-supplied method that polls the device and posts
+ *	input events (mandatory).
+ * @poll_interval: specifies how often the poll() method shoudl be called.
+ * @input: input device structire associated with the polled device.
+ *	Must be properly initialized by the driver (id, name, phys, bits).
+ *
+ * Polled input device provides a skeleton for supporting simple input
+ * devices that do not raise interrupts but have to be periodically
+ * scanned or polled to detect changes in their state.
+ */
+struct input_polled_dev {
+	void *private;
+
+	void (*flush)(struct input_polled_dev *dev);
+	void (*poll)(struct input_polled_dev *dev);
+	unsigned int poll_interval; /* msec */
+
+	struct input_dev *input;
+	struct delayed_work work;
+};
+
+struct input_polled_dev *input_allocate_polled_device(void);
+void input_free_polled_device(struct input_polled_dev *dev);
+int input_register_polled_device(struct input_polled_dev *dev);
+void input_unregister_polled_device(struct input_polled_dev *dev);
+
+#endif
diff --git a/include/linux/input.h b/include/linux/input.h
index bde65c8..439954d 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -506,6 +506,7 @@
 #define KEY_VOICEMAIL		0x1ac
 #define KEY_ADDRESSBOOK		0x1ad
 #define KEY_MESSENGER		0x1ae
+#define KEY_DISPLAYTOGGLE	0x1af	/* Turn display (LCD) on and off */
 
 #define KEY_DEL_EOL		0x1c0
 #define KEY_DEL_EOS		0x1c1
@@ -676,6 +677,7 @@
 #define BUS_I2C			0x18
 #define BUS_HOST		0x19
 #define BUS_GSC			0x1A
+#define BUS_ATARI		0x1B
 
 /*
  * Values describing the status of a force-feedback effect
@@ -913,33 +915,6 @@
 #define BIT(x)	(1UL<<((x)%BITS_PER_LONG))
 #define LONG(x) ((x)/BITS_PER_LONG)
 
-#define INPUT_KEYCODE(dev, scancode) ((dev->keycodesize == 1) ? ((u8*)dev->keycode)[scancode] : \
-	((dev->keycodesize == 2) ? ((u16*)dev->keycode)[scancode] : (((u32*)dev->keycode)[scancode])))
-
-#define SET_INPUT_KEYCODE(dev, scancode, val)			\
-		({	unsigned __old;				\
-		switch (dev->keycodesize) {			\
-			case 1: {				\
-				u8 *k = (u8 *)dev->keycode;	\
-				__old = k[scancode];		\
-				k[scancode] = val;		\
-				break;				\
-			}					\
-			case 2: {				\
-				u16 *k = (u16 *)dev->keycode;	\
-				__old = k[scancode];		\
-				k[scancode] = val;		\
-				break;				\
-			}					\
-			default: {				\
-				u32 *k = (u32 *)dev->keycode;	\
-				__old = k[scancode];		\
-				k[scancode] = val;		\
-				break;				\
-			}					\
-		}						\
-		__old; })
-
 struct input_dev {
 
 	void *private;
@@ -962,6 +937,8 @@
 	unsigned int keycodemax;
 	unsigned int keycodesize;
 	void *keycode;
+	int (*setkeycode)(struct input_dev *dev, int scancode, int keycode);
+	int (*getkeycode)(struct input_dev *dev, int scancode, int *keycode);
 
 	struct ff_device *ff;
 
@@ -996,6 +973,9 @@
 	unsigned int users;
 
 	struct class_device cdev;
+	union {			/* temporarily so while we switching to struct device */
+		struct device *parent;
+	} dev;
 
 	struct list_head	h_list;
 	struct list_head	node;
@@ -1074,7 +1054,7 @@
 	void *private;
 
 	void (*event)(struct input_handle *handle, unsigned int type, unsigned int code, int value);
-	struct input_handle* (*connect)(struct input_handler *handler, struct input_dev *dev, const struct input_device_id *id);
+	int (*connect)(struct input_handler *handler, struct input_dev *dev, const struct input_device_id *id);
 	void (*disconnect)(struct input_handle *handle);
 	void (*start)(struct input_handle *handle);
 
@@ -1104,7 +1084,7 @@
 };
 
 #define to_dev(n) container_of(n,struct input_dev,node)
-#define to_handler(n) container_of(n,struct input_handler,node);
+#define to_handler(n) container_of(n,struct input_handler,node)
 #define to_handle(n) container_of(n,struct input_handle,d_node)
 #define to_handle_h(n) container_of(n,struct input_handle,h_node)
 
@@ -1121,12 +1101,25 @@
 	class_device_put(&dev->cdev);
 }
 
+static inline void *input_get_drvdata(struct input_dev *dev)
+{
+	return dev->private;
+}
+
+static inline void input_set_drvdata(struct input_dev *dev, void *data)
+{
+	dev->private = data;
+}
+
 int input_register_device(struct input_dev *);
 void input_unregister_device(struct input_dev *);
 
 int input_register_handler(struct input_handler *);
 void input_unregister_handler(struct input_handler *);
 
+int input_register_handle(struct input_handle *);
+void input_unregister_handle(struct input_handle *);
+
 int input_grab_device(struct input_handle *);
 void input_release_device(struct input_handle *);
 
@@ -1168,6 +1161,8 @@
 	input_event(dev, EV_SYN, SYN_REPORT, 0);
 }
 
+void input_set_capability(struct input_dev *dev, unsigned int type, unsigned int code);
+
 static inline void input_set_abs_params(struct input_dev *dev, int axis, int min, int max, int fuzz, int flat)
 {
 	dev->absmin[axis] = min;
diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
index 838cf5a..0319f66 100644
--- a/include/linux/interrupt.h
+++ b/include/linux/interrupt.h
@@ -185,10 +185,14 @@
  * validator need to define the methods below in their asm/irq.h
  * files, under an #ifdef CONFIG_LOCKDEP section.
  */
-# ifndef CONFIG_LOCKDEP
+#ifndef CONFIG_LOCKDEP
 #  define disable_irq_nosync_lockdep(irq)	disable_irq_nosync(irq)
+#  define disable_irq_nosync_lockdep_irqsave(irq, flags) \
+						disable_irq_nosync(irq)
 #  define disable_irq_lockdep(irq)		disable_irq(irq)
 #  define enable_irq_lockdep(irq)		enable_irq(irq)
+#  define enable_irq_lockdep_irqrestore(irq, flags) \
+						enable_irq(irq)
 # endif
 
 #endif /* CONFIG_GENERIC_HARDIRQS */
diff --git a/include/linux/kobject.h b/include/linux/kobject.h
index eb0e63e..c288e41 100644
--- a/include/linux/kobject.h
+++ b/include/linux/kobject.h
@@ -124,7 +124,6 @@
 };
 
 struct kset {
-	struct subsystem	* subsys;
 	struct kobj_type	* ktype;
 	struct list_head	list;
 	spinlock_t		list_lock;
@@ -171,32 +170,23 @@
 #define set_kset_name(str)	.kset = { .kobj = { .name = str } }
 
 
-
-struct subsystem {
-	struct kset		kset;
-};
-
 #define decl_subsys(_name,_type,_uevent_ops) \
-struct subsystem _name##_subsys = { \
-	.kset = { \
-		.kobj = { .name = __stringify(_name) }, \
-		.ktype = _type, \
-		.uevent_ops =_uevent_ops, \
-	} \
+struct kset _name##_subsys = { \
+	.kobj = { .name = __stringify(_name) }, \
+	.ktype = _type, \
+	.uevent_ops =_uevent_ops, \
 }
 #define decl_subsys_name(_varname,_name,_type,_uevent_ops) \
-struct subsystem _varname##_subsys = { \
-	.kset = { \
-		.kobj = { .name = __stringify(_name) }, \
-		.ktype = _type, \
-		.uevent_ops =_uevent_ops, \
-	} \
+struct kset _varname##_subsys = { \
+	.kobj = { .name = __stringify(_name) }, \
+	.ktype = _type, \
+	.uevent_ops =_uevent_ops, \
 }
 
 /* The global /sys/kernel/ subsystem for people to chain off of */
-extern struct subsystem kernel_subsys;
+extern struct kset kernel_subsys;
 /* The global /sys/hypervisor/ subsystem  */
-extern struct subsystem hypervisor_subsys;
+extern struct kset hypervisor_subsys;
 
 /**
  * Helpers for setting the kset of registered objects.
@@ -214,7 +204,7 @@
  */
 
 #define kobj_set_kset_s(obj,subsys) \
-	(obj)->kobj.kset = &(subsys).kset
+	(obj)->kobj.kset = &(subsys)
 
 /**
  *	kset_set_kset_s(obj,subsys) - set kset for embedded kset.
@@ -228,7 +218,7 @@
  */
 
 #define kset_set_kset_s(obj,subsys) \
-	(obj)->kset.kobj.kset = &(subsys).kset
+	(obj)->kset.kobj.kset = &(subsys)
 
 /**
  *	subsys_set_kset(obj,subsys) - set kset for subsystem
@@ -241,29 +231,31 @@
  */
 
 #define subsys_set_kset(obj,_subsys) \
-	(obj)->subsys.kset.kobj.kset = &(_subsys).kset
+	(obj)->subsys.kobj.kset = &(_subsys)
 
-extern void subsystem_init(struct subsystem *);
-extern int __must_check subsystem_register(struct subsystem *);
-extern void subsystem_unregister(struct subsystem *);
+extern void subsystem_init(struct kset *);
+extern int __must_check subsystem_register(struct kset *);
+extern void subsystem_unregister(struct kset *);
 
-static inline struct subsystem * subsys_get(struct subsystem * s)
+static inline struct kset *subsys_get(struct kset *s)
 {
-	return s ? container_of(kset_get(&s->kset),struct subsystem,kset) : NULL;
+	if (s)
+		return kset_get(s);
+	return NULL;
 }
 
-static inline void subsys_put(struct subsystem * s)
+static inline void subsys_put(struct kset *s)
 {
-	kset_put(&s->kset);
+	kset_put(s);
 }
 
 struct subsys_attribute {
 	struct attribute attr;
-	ssize_t (*show)(struct subsystem *, char *);
-	ssize_t (*store)(struct subsystem *, const char *, size_t); 
+	ssize_t (*show)(struct kset *, char *);
+	ssize_t (*store)(struct kset *, const char *, size_t);
 };
 
-extern int __must_check subsys_create_file(struct subsystem * ,
+extern int __must_check subsys_create_file(struct kset *,
 					struct subsys_attribute *);
 
 #if defined(CONFIG_HOTPLUG)
diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h
index ac25b56..f6a81e0 100644
--- a/include/linux/lockd/lockd.h
+++ b/include/linux/lockd/lockd.h
@@ -88,7 +88,7 @@
 /*
  * Memory chunk for NLM client RPC request.
  */
-#define NLMCLNT_OHSIZE		(sizeof(utsname()->nodename)+10)
+#define NLMCLNT_OHSIZE		((__NEW_UTS_LEN) + 10u)
 struct nlm_rqst {
 	unsigned int		a_flags;	/* initial RPC task flags */
 	struct nlm_host *	a_host;		/* host handle */
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
index e45712ac..badf702 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -10,7 +10,7 @@
 #ifndef LINUX_MMC_CARD_H
 #define LINUX_MMC_CARD_H
 
-#include <linux/mmc/mmc.h>
+#include <linux/mmc/core.h>
 
 struct mmc_cid {
 	unsigned int		manfid;
@@ -41,6 +41,7 @@
 
 struct mmc_ext_csd {
 	unsigned int		hs_max_dtr;
+	unsigned int		sectors;
 };
 
 struct sd_scr {
@@ -60,18 +61,17 @@
  * MMC device
  */
 struct mmc_card {
-	struct list_head	node;		/* node in hosts devices list */
 	struct mmc_host		*host;		/* the host this device belongs to */
 	struct device		dev;		/* the device */
 	unsigned int		rca;		/* relative card address of device */
+	unsigned int		type;		/* card type */
+#define MMC_TYPE_MMC		0		/* MMC card */
+#define MMC_TYPE_SD		1		/* SD card */
 	unsigned int		state;		/* (our) card state */
 #define MMC_STATE_PRESENT	(1<<0)		/* present in sysfs */
-#define MMC_STATE_DEAD		(1<<1)		/* device no longer in stack */
-#define MMC_STATE_BAD		(1<<2)		/* unrecognised device */
-#define MMC_STATE_SDCARD	(1<<3)		/* is an SD card */
-#define MMC_STATE_READONLY	(1<<4)		/* card is read-only */
-#define MMC_STATE_HIGHSPEED	(1<<5)		/* card is in high speed mode */
-#define MMC_STATE_BLOCKADDR	(1<<6)		/* card uses block-addressing */
+#define MMC_STATE_READONLY	(1<<1)		/* card is read-only */
+#define MMC_STATE_HIGHSPEED	(1<<2)		/* card is in high speed mode */
+#define MMC_STATE_BLOCKADDR	(1<<3)		/* card uses block-addressing */
 	u32			raw_cid[4];	/* raw card CID */
 	u32			raw_csd[4];	/* raw card CSD */
 	u32			raw_scr[2];	/* raw card SCR */
@@ -82,18 +82,15 @@
 	struct sd_switch_caps	sw_caps;	/* switch (CMD6) caps */
 };
 
+#define mmc_card_mmc(c)		((c)->type == MMC_TYPE_MMC)
+#define mmc_card_sd(c)		((c)->type == MMC_TYPE_SD)
+
 #define mmc_card_present(c)	((c)->state & MMC_STATE_PRESENT)
-#define mmc_card_dead(c)	((c)->state & MMC_STATE_DEAD)
-#define mmc_card_bad(c)		((c)->state & MMC_STATE_BAD)
-#define mmc_card_sd(c)		((c)->state & MMC_STATE_SDCARD)
 #define mmc_card_readonly(c)	((c)->state & MMC_STATE_READONLY)
 #define mmc_card_highspeed(c)	((c)->state & MMC_STATE_HIGHSPEED)
 #define mmc_card_blockaddr(c)	((c)->state & MMC_STATE_BLOCKADDR)
 
 #define mmc_card_set_present(c)	((c)->state |= MMC_STATE_PRESENT)
-#define mmc_card_set_dead(c)	((c)->state |= MMC_STATE_DEAD)
-#define mmc_card_set_bad(c)	((c)->state |= MMC_STATE_BAD)
-#define mmc_card_set_sd(c)	((c)->state |= MMC_STATE_SDCARD)
 #define mmc_card_set_readonly(c) ((c)->state |= MMC_STATE_READONLY)
 #define mmc_card_set_highspeed(c) ((c)->state |= MMC_STATE_HIGHSPEED)
 #define mmc_card_set_blockaddr(c) ((c)->state |= MMC_STATE_BLOCKADDR)
@@ -119,11 +116,4 @@
 extern int mmc_register_driver(struct mmc_driver *);
 extern void mmc_unregister_driver(struct mmc_driver *);
 
-static inline int mmc_card_claim_host(struct mmc_card *card)
-{
-	return __mmc_claim_host(card->host, card);
-}
-
-#define mmc_card_release_host(c)	mmc_release_host((c)->host)
-
 #endif
diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h
new file mode 100644
index 0000000..04bbe12f
--- /dev/null
+++ b/include/linux/mmc/core.h
@@ -0,0 +1,112 @@
+/*
+ *  linux/include/linux/mmc/core.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.
+ */
+#ifndef LINUX_MMC_CORE_H
+#define LINUX_MMC_CORE_H
+
+#include <linux/interrupt.h>
+#include <linux/device.h>
+
+struct request;
+struct mmc_data;
+struct mmc_request;
+
+struct mmc_command {
+	u32			opcode;
+	u32			arg;
+	u32			resp[4];
+	unsigned int		flags;		/* expected response type */
+#define MMC_RSP_PRESENT	(1 << 0)
+#define MMC_RSP_136	(1 << 1)		/* 136 bit response */
+#define MMC_RSP_CRC	(1 << 2)		/* expect valid crc */
+#define MMC_RSP_BUSY	(1 << 3)		/* card may send busy */
+#define MMC_RSP_OPCODE	(1 << 4)		/* response contains opcode */
+#define MMC_CMD_MASK	(3 << 5)		/* command type */
+#define MMC_CMD_AC	(0 << 5)
+#define MMC_CMD_ADTC	(1 << 5)
+#define MMC_CMD_BC	(2 << 5)
+#define MMC_CMD_BCR	(3 << 5)
+
+/*
+ * These are the response types, and correspond to valid bit
+ * patterns of the above flags.  One additional valid pattern
+ * is all zeros, which means we don't expect a response.
+ */
+#define MMC_RSP_NONE	(0)
+#define MMC_RSP_R1	(MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE)
+#define MMC_RSP_R1B	(MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE|MMC_RSP_BUSY)
+#define MMC_RSP_R2	(MMC_RSP_PRESENT|MMC_RSP_136|MMC_RSP_CRC)
+#define MMC_RSP_R3	(MMC_RSP_PRESENT)
+#define MMC_RSP_R6	(MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE)
+#define MMC_RSP_R7	(MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE)
+
+#define mmc_resp_type(cmd)	((cmd)->flags & (MMC_RSP_PRESENT|MMC_RSP_136|MMC_RSP_CRC|MMC_RSP_BUSY|MMC_RSP_OPCODE))
+
+/*
+ * These are the command types.
+ */
+#define mmc_cmd_type(cmd)	((cmd)->flags & MMC_CMD_MASK)
+
+	unsigned int		retries;	/* max number of retries */
+	unsigned int		error;		/* command error */
+
+#define MMC_ERR_NONE	0
+#define MMC_ERR_TIMEOUT	1
+#define MMC_ERR_BADCRC	2
+#define MMC_ERR_FIFO	3
+#define MMC_ERR_FAILED	4
+#define MMC_ERR_INVALID	5
+
+	struct mmc_data		*data;		/* data segment associated with cmd */
+	struct mmc_request	*mrq;		/* associated request */
+};
+
+struct mmc_data {
+	unsigned int		timeout_ns;	/* data timeout (in ns, max 80ms) */
+	unsigned int		timeout_clks;	/* data timeout (in clocks) */
+	unsigned int		blksz;		/* data block size */
+	unsigned int		blocks;		/* number of blocks */
+	unsigned int		error;		/* data error */
+	unsigned int		flags;
+
+#define MMC_DATA_WRITE	(1 << 8)
+#define MMC_DATA_READ	(1 << 9)
+#define MMC_DATA_STREAM	(1 << 10)
+#define MMC_DATA_MULTI	(1 << 11)
+
+	unsigned int		bytes_xfered;
+
+	struct mmc_command	*stop;		/* stop command */
+	struct mmc_request	*mrq;		/* associated request */
+
+	unsigned int		sg_len;		/* size of scatter list */
+	struct scatterlist	*sg;		/* I/O scatter list */
+};
+
+struct mmc_request {
+	struct mmc_command	*cmd;
+	struct mmc_data		*data;
+	struct mmc_command	*stop;
+
+	void			*done_data;	/* completion data */
+	void			(*done)(struct mmc_request *);/* completion function */
+};
+
+struct mmc_host;
+struct mmc_card;
+
+extern int mmc_wait_for_req(struct mmc_host *, struct mmc_request *);
+extern int mmc_wait_for_cmd(struct mmc_host *, struct mmc_command *, int);
+extern int mmc_wait_for_app_cmd(struct mmc_host *, struct mmc_card *,
+	struct mmc_command *, int);
+
+extern void mmc_set_data_timeout(struct mmc_data *, const struct mmc_card *, int);
+
+extern void mmc_claim_host(struct mmc_host *host);
+extern void mmc_release_host(struct mmc_host *host);
+
+#endif
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index bfcef8a..b1350df 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -10,36 +10,13 @@
 #ifndef LINUX_MMC_HOST_H
 #define LINUX_MMC_HOST_H
 
-#include <linux/mmc/mmc.h>
+#include <linux/mmc/core.h>
 
 struct mmc_ios {
 	unsigned int	clock;			/* clock rate */
 	unsigned short	vdd;
 
-#define	MMC_VDD_150	0
-#define	MMC_VDD_155	1
-#define	MMC_VDD_160	2
-#define	MMC_VDD_165	3
-#define	MMC_VDD_170	4
-#define	MMC_VDD_180	5
-#define	MMC_VDD_190	6
-#define	MMC_VDD_200	7
-#define	MMC_VDD_210	8
-#define	MMC_VDD_220	9
-#define	MMC_VDD_230	10
-#define	MMC_VDD_240	11
-#define	MMC_VDD_250	12
-#define	MMC_VDD_260	13
-#define	MMC_VDD_270	14
-#define	MMC_VDD_280	15
-#define	MMC_VDD_290	16
-#define	MMC_VDD_300	17
-#define	MMC_VDD_310	18
-#define	MMC_VDD_320	19
-#define	MMC_VDD_330	20
-#define	MMC_VDD_340	21
-#define	MMC_VDD_350	22
-#define	MMC_VDD_360	23
+/* vdd stores the bit number of the selected voltage range from below. */
 
 	unsigned char	bus_mode;		/* command output mode */
 
@@ -88,6 +65,24 @@
 	unsigned int		f_max;
 	u32			ocr_avail;
 
+#define MMC_VDD_165_195		0x00000080	/* VDD voltage 1.65 - 1.95 */
+#define MMC_VDD_20_21		0x00000100	/* VDD voltage 2.0 ~ 2.1 */
+#define MMC_VDD_21_22		0x00000200	/* VDD voltage 2.1 ~ 2.2 */
+#define MMC_VDD_22_23		0x00000400	/* VDD voltage 2.2 ~ 2.3 */
+#define MMC_VDD_23_24		0x00000800	/* VDD voltage 2.3 ~ 2.4 */
+#define MMC_VDD_24_25		0x00001000	/* VDD voltage 2.4 ~ 2.5 */
+#define MMC_VDD_25_26		0x00002000	/* VDD voltage 2.5 ~ 2.6 */
+#define MMC_VDD_26_27		0x00004000	/* VDD voltage 2.6 ~ 2.7 */
+#define MMC_VDD_27_28		0x00008000	/* VDD voltage 2.7 ~ 2.8 */
+#define MMC_VDD_28_29		0x00010000	/* VDD voltage 2.8 ~ 2.9 */
+#define MMC_VDD_29_30		0x00020000	/* VDD voltage 2.9 ~ 3.0 */
+#define MMC_VDD_30_31		0x00040000	/* VDD voltage 3.0 ~ 3.1 */
+#define MMC_VDD_31_32		0x00080000	/* VDD voltage 3.1 ~ 3.2 */
+#define MMC_VDD_32_33		0x00100000	/* VDD voltage 3.2 ~ 3.3 */
+#define MMC_VDD_33_34		0x00200000	/* VDD voltage 3.3 ~ 3.4 */
+#define MMC_VDD_34_35		0x00400000	/* VDD voltage 3.4 ~ 3.5 */
+#define MMC_VDD_35_36		0x00800000	/* VDD voltage 3.5 ~ 3.6 */
+
 	unsigned long		caps;		/* Host capabilities */
 
 #define MMC_CAP_4_BIT_DATA	(1 << 0)	/* Can the host do 4 bit transfers */
@@ -106,6 +101,8 @@
 	unsigned int		max_blk_count;	/* maximum number of blocks in one req */
 
 	/* private data */
+	spinlock_t		lock;		/* lock for claim and bus ops */
+
 	struct mmc_ios		ios;		/* current io bus settings */
 	u32			ocr;		/* the current OCR setting */
 
@@ -113,15 +110,19 @@
 #define MMC_MODE_MMC		0
 #define MMC_MODE_SD		1
 
-	struct list_head	cards;		/* devices attached to this host */
+	struct mmc_card		*card;		/* device attached to this host */
 
 	wait_queue_head_t	wq;
-	spinlock_t		lock;		/* claimed lock */
 	unsigned int		claimed:1;	/* host exclusively claimed */
 
-	struct mmc_card		*card_selected;	/* the selected MMC card */
-
 	struct delayed_work	detect;
+#ifdef CONFIG_MMC_DEBUG
+	unsigned int		removed:1;	/* host is being removed */
+#endif
+
+	const struct mmc_bus_ops *bus_ops;	/* current bus driver */
+	unsigned int		bus_refs;	/* reference counter */
+	unsigned int		bus_dead:1;	/* bus has been released */
 
 	unsigned long		private[0] ____cacheline_aligned;
 };
diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h
index cdc54be..e3ed9b9 100644
--- a/include/linux/mmc/mmc.h
+++ b/include/linux/mmc/mmc.h
@@ -1,119 +1,257 @@
 /*
- *  linux/include/linux/mmc/mmc.h
+ * Header for MultiMediaCard (MMC)
  *
- * 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 2002 Hewlett-Packard Company
+ *
+ * Use consistent with the GNU GPL is permitted,
+ * provided that this copyright notice is
+ * preserved in its entirety in all copies and derived works.
+ *
+ * HEWLETT-PACKARD COMPANY MAKES NO WARRANTIES, EXPRESSED OR IMPLIED,
+ * AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS
+ * FITNESS FOR ANY PARTICULAR PURPOSE.
+ *
+ * Many thanks to Alessandro Rubini and Jonathan Corbet!
+ *
+ * Based strongly on code by:
+ *
+ * Author: Yong-iL Joh <tolkien@mizi.com>
+ * Date  : $Date: 2002/06/18 12:37:30 $
+ *
+ * Author:  Andrew Christian
+ *          15 May 2002
  */
-#ifndef MMC_H
-#define MMC_H
 
-#include <linux/list.h>
-#include <linux/interrupt.h>
-#include <linux/device.h>
+#ifndef MMC_MMC_H
+#define MMC_MMC_H
 
-struct request;
-struct mmc_data;
-struct mmc_request;
+/* Standard MMC commands (4.1)           type  argument     response */
+   /* class 1 */
+#define	MMC_GO_IDLE_STATE         0   /* bc                          */
+#define MMC_SEND_OP_COND          1   /* bcr  [31:0] OCR         R3  */
+#define MMC_ALL_SEND_CID          2   /* bcr                     R2  */
+#define MMC_SET_RELATIVE_ADDR     3   /* ac   [31:16] RCA        R1  */
+#define MMC_SET_DSR               4   /* bc   [31:16] RCA            */
+#define MMC_SWITCH                6   /* ac   [31:0] See below   R1b */
+#define MMC_SELECT_CARD           7   /* ac   [31:16] RCA        R1  */
+#define MMC_SEND_EXT_CSD          8   /* adtc                    R1  */
+#define MMC_SEND_CSD              9   /* ac   [31:16] RCA        R2  */
+#define MMC_SEND_CID             10   /* ac   [31:16] RCA        R2  */
+#define MMC_READ_DAT_UNTIL_STOP  11   /* adtc [31:0] dadr        R1  */
+#define MMC_STOP_TRANSMISSION    12   /* ac                      R1b */
+#define MMC_SEND_STATUS	         13   /* ac   [31:16] RCA        R1  */
+#define MMC_GO_INACTIVE_STATE    15   /* ac   [31:16] RCA            */
 
-struct mmc_command {
-	u32			opcode;
-	u32			arg;
-	u32			resp[4];
-	unsigned int		flags;		/* expected response type */
-#define MMC_RSP_PRESENT	(1 << 0)
-#define MMC_RSP_136	(1 << 1)		/* 136 bit response */
-#define MMC_RSP_CRC	(1 << 2)		/* expect valid crc */
-#define MMC_RSP_BUSY	(1 << 3)		/* card may send busy */
-#define MMC_RSP_OPCODE	(1 << 4)		/* response contains opcode */
-#define MMC_CMD_MASK	(3 << 5)		/* command type */
-#define MMC_CMD_AC	(0 << 5)
-#define MMC_CMD_ADTC	(1 << 5)
-#define MMC_CMD_BC	(2 << 5)
-#define MMC_CMD_BCR	(3 << 5)
+  /* class 2 */
+#define MMC_SET_BLOCKLEN         16   /* ac   [31:0] block len   R1  */
+#define MMC_READ_SINGLE_BLOCK    17   /* adtc [31:0] data addr   R1  */
+#define MMC_READ_MULTIPLE_BLOCK  18   /* adtc [31:0] data addr   R1  */
+
+  /* class 3 */
+#define MMC_WRITE_DAT_UNTIL_STOP 20   /* adtc [31:0] data addr   R1  */
+
+  /* class 4 */
+#define MMC_SET_BLOCK_COUNT      23   /* adtc [31:0] data addr   R1  */
+#define MMC_WRITE_BLOCK          24   /* adtc [31:0] data addr   R1  */
+#define MMC_WRITE_MULTIPLE_BLOCK 25   /* adtc                    R1  */
+#define MMC_PROGRAM_CID          26   /* adtc                    R1  */
+#define MMC_PROGRAM_CSD          27   /* adtc                    R1  */
+
+  /* class 6 */
+#define MMC_SET_WRITE_PROT       28   /* ac   [31:0] data addr   R1b */
+#define MMC_CLR_WRITE_PROT       29   /* ac   [31:0] data addr   R1b */
+#define MMC_SEND_WRITE_PROT      30   /* adtc [31:0] wpdata addr R1  */
+
+  /* class 5 */
+#define MMC_ERASE_GROUP_START    35   /* ac   [31:0] data addr   R1  */
+#define MMC_ERASE_GROUP_END      36   /* ac   [31:0] data addr   R1  */
+#define MMC_ERASE                38   /* ac                      R1b */
+
+  /* class 9 */
+#define MMC_FAST_IO              39   /* ac   <Complex>          R4  */
+#define MMC_GO_IRQ_STATE         40   /* bcr                     R5  */
+
+  /* class 7 */
+#define MMC_LOCK_UNLOCK          42   /* adtc                    R1b */
+
+  /* class 8 */
+#define MMC_APP_CMD              55   /* ac   [31:16] RCA        R1  */
+#define MMC_GEN_CMD              56   /* adtc [0] RD/WR          R1  */
 
 /*
- * These are the response types, and correspond to valid bit
- * patterns of the above flags.  One additional valid pattern
- * is all zeros, which means we don't expect a response.
+ * MMC_SWITCH argument format:
+ *
+ *	[31:26] Always 0
+ *	[25:24] Access Mode
+ *	[23:16] Location of target Byte in EXT_CSD
+ *	[15:08] Value Byte
+ *	[07:03] Always 0
+ *	[02:00] Command Set
  */
-#define MMC_RSP_NONE	(0)
-#define MMC_RSP_R1	(MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE)
-#define MMC_RSP_R1B	(MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE|MMC_RSP_BUSY)
-#define MMC_RSP_R2	(MMC_RSP_PRESENT|MMC_RSP_136|MMC_RSP_CRC)
-#define MMC_RSP_R3	(MMC_RSP_PRESENT)
-#define MMC_RSP_R6	(MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE)
-#define MMC_RSP_R7	(MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE)
-
-#define mmc_resp_type(cmd)	((cmd)->flags & (MMC_RSP_PRESENT|MMC_RSP_136|MMC_RSP_CRC|MMC_RSP_BUSY|MMC_RSP_OPCODE))
 
 /*
- * These are the command types.
+  MMC status in R1
+  Type
+  	e : error bit
+	s : status bit
+	r : detected and set for the actual command response
+	x : detected and set during command execution. the host must poll
+            the card by sending status command in order to read these bits.
+  Clear condition
+  	a : according to the card state
+	b : always related to the previous command. Reception of
+            a valid command will clear it (with a delay of one command)
+	c : clear by read
  */
-#define mmc_cmd_type(cmd)	((cmd)->flags & MMC_CMD_MASK)
 
-	unsigned int		retries;	/* max number of retries */
-	unsigned int		error;		/* command error */
+#define R1_OUT_OF_RANGE		(1 << 31)	/* er, c */
+#define R1_ADDRESS_ERROR	(1 << 30)	/* erx, c */
+#define R1_BLOCK_LEN_ERROR	(1 << 29)	/* er, c */
+#define R1_ERASE_SEQ_ERROR      (1 << 28)	/* er, c */
+#define R1_ERASE_PARAM		(1 << 27)	/* ex, c */
+#define R1_WP_VIOLATION		(1 << 26)	/* erx, c */
+#define R1_CARD_IS_LOCKED	(1 << 25)	/* sx, a */
+#define R1_LOCK_UNLOCK_FAILED	(1 << 24)	/* erx, c */
+#define R1_COM_CRC_ERROR	(1 << 23)	/* er, b */
+#define R1_ILLEGAL_COMMAND	(1 << 22)	/* er, b */
+#define R1_CARD_ECC_FAILED	(1 << 21)	/* ex, c */
+#define R1_CC_ERROR		(1 << 20)	/* erx, c */
+#define R1_ERROR		(1 << 19)	/* erx, c */
+#define R1_UNDERRUN		(1 << 18)	/* ex, c */
+#define R1_OVERRUN		(1 << 17)	/* ex, c */
+#define R1_CID_CSD_OVERWRITE	(1 << 16)	/* erx, c, CID/CSD overwrite */
+#define R1_WP_ERASE_SKIP	(1 << 15)	/* sx, c */
+#define R1_CARD_ECC_DISABLED	(1 << 14)	/* sx, a */
+#define R1_ERASE_RESET		(1 << 13)	/* sr, c */
+#define R1_STATUS(x)            (x & 0xFFFFE000)
+#define R1_CURRENT_STATE(x)    	((x & 0x00001E00) >> 9)	/* sx, b (4 bits) */
+#define R1_READY_FOR_DATA	(1 << 8)	/* sx, a */
+#define R1_APP_CMD		(1 << 5)	/* sr, c */
 
-#define MMC_ERR_NONE	0
-#define MMC_ERR_TIMEOUT	1
-#define MMC_ERR_BADCRC	2
-#define MMC_ERR_FIFO	3
-#define MMC_ERR_FAILED	4
-#define MMC_ERR_INVALID	5
+/* These are unpacked versions of the actual responses */
 
-	struct mmc_data		*data;		/* data segment associated with cmd */
-	struct mmc_request	*mrq;		/* associated request */
+struct _mmc_csd {
+	u8  csd_structure;
+	u8  spec_vers;
+	u8  taac;
+	u8  nsac;
+	u8  tran_speed;
+	u16 ccc;
+	u8  read_bl_len;
+	u8  read_bl_partial;
+	u8  write_blk_misalign;
+	u8  read_blk_misalign;
+	u8  dsr_imp;
+	u16 c_size;
+	u8  vdd_r_curr_min;
+	u8  vdd_r_curr_max;
+	u8  vdd_w_curr_min;
+	u8  vdd_w_curr_max;
+	u8  c_size_mult;
+	union {
+		struct { /* MMC system specification version 3.1 */
+			u8  erase_grp_size;
+			u8  erase_grp_mult;
+		} v31;
+		struct { /* MMC system specification version 2.2 */
+			u8  sector_size;
+			u8  erase_grp_size;
+		} v22;
+	} erase;
+	u8  wp_grp_size;
+	u8  wp_grp_enable;
+	u8  default_ecc;
+	u8  r2w_factor;
+	u8  write_bl_len;
+	u8  write_bl_partial;
+	u8  file_format_grp;
+	u8  copy;
+	u8  perm_write_protect;
+	u8  tmp_write_protect;
+	u8  file_format;
+	u8  ecc;
 };
 
-struct mmc_data {
-	unsigned int		timeout_ns;	/* data timeout (in ns, max 80ms) */
-	unsigned int		timeout_clks;	/* data timeout (in clocks) */
-	unsigned int		blksz;		/* data block size */
-	unsigned int		blocks;		/* number of blocks */
-	unsigned int		error;		/* data error */
-	unsigned int		flags;
+/*
+ * OCR bits are mostly in host.h
+ */
+#define MMC_CARD_BUSY	0x80000000	/* Card Power up status bit */
 
-#define MMC_DATA_WRITE	(1 << 8)
-#define MMC_DATA_READ	(1 << 9)
-#define MMC_DATA_STREAM	(1 << 10)
-#define MMC_DATA_MULTI	(1 << 11)
+/*
+ * Card Command Classes (CCC)
+ */
+#define CCC_BASIC		(1<<0)	/* (0) Basic protocol functions */
+					/* (CMD0,1,2,3,4,7,9,10,12,13,15) */
+#define CCC_STREAM_READ		(1<<1)	/* (1) Stream read commands */
+					/* (CMD11) */
+#define CCC_BLOCK_READ		(1<<2)	/* (2) Block read commands */
+					/* (CMD16,17,18) */
+#define CCC_STREAM_WRITE	(1<<3)	/* (3) Stream write commands */
+					/* (CMD20) */
+#define CCC_BLOCK_WRITE		(1<<4)	/* (4) Block write commands */
+					/* (CMD16,24,25,26,27) */
+#define CCC_ERASE		(1<<5)	/* (5) Ability to erase blocks */
+					/* (CMD32,33,34,35,36,37,38,39) */
+#define CCC_WRITE_PROT		(1<<6)	/* (6) Able to write protect blocks */
+					/* (CMD28,29,30) */
+#define CCC_LOCK_CARD		(1<<7)	/* (7) Able to lock down card */
+					/* (CMD16,CMD42) */
+#define CCC_APP_SPEC		(1<<8)	/* (8) Application specific */
+					/* (CMD55,56,57,ACMD*) */
+#define CCC_IO_MODE		(1<<9)	/* (9) I/O mode */
+					/* (CMD5,39,40,52,53) */
+#define CCC_SWITCH		(1<<10)	/* (10) High speed switch */
+					/* (CMD6,34,35,36,37,50) */
+					/* (11) Reserved */
+					/* (CMD?) */
 
-	unsigned int		bytes_xfered;
+/*
+ * CSD field definitions
+ */
 
-	struct mmc_command	*stop;		/* stop command */
-	struct mmc_request	*mrq;		/* associated request */
+#define CSD_STRUCT_VER_1_0  0           /* Valid for system specification 1.0 - 1.2 */
+#define CSD_STRUCT_VER_1_1  1           /* Valid for system specification 1.4 - 2.2 */
+#define CSD_STRUCT_VER_1_2  2           /* Valid for system specification 3.1 - 3.2 - 3.31 - 4.0 - 4.1 */
+#define CSD_STRUCT_EXT_CSD  3           /* Version is coded in CSD_STRUCTURE in EXT_CSD */
 
-	unsigned int		sg_len;		/* size of scatter list */
-	struct scatterlist	*sg;		/* I/O scatter list */
-};
+#define CSD_SPEC_VER_0      0           /* Implements system specification 1.0 - 1.2 */
+#define CSD_SPEC_VER_1      1           /* Implements system specification 1.4 */
+#define CSD_SPEC_VER_2      2           /* Implements system specification 2.0 - 2.2 */
+#define CSD_SPEC_VER_3      3           /* Implements system specification 3.1 - 3.2 - 3.31 */
+#define CSD_SPEC_VER_4      4           /* Implements system specification 4.0 - 4.1 */
 
-struct mmc_request {
-	struct mmc_command	*cmd;
-	struct mmc_data		*data;
-	struct mmc_command	*stop;
+/*
+ * EXT_CSD fields
+ */
 
-	void			*done_data;	/* completion data */
-	void			(*done)(struct mmc_request *);/* completion function */
-};
+#define EXT_CSD_BUS_WIDTH	183	/* R/W */
+#define EXT_CSD_HS_TIMING	185	/* R/W */
+#define EXT_CSD_CARD_TYPE	196	/* RO */
+#define EXT_CSD_SEC_CNT		212	/* RO, 4 bytes */
 
-struct mmc_host;
-struct mmc_card;
+/*
+ * EXT_CSD field definitions
+ */
 
-extern int mmc_wait_for_req(struct mmc_host *, struct mmc_request *);
-extern int mmc_wait_for_cmd(struct mmc_host *, struct mmc_command *, int);
-extern int mmc_wait_for_app_cmd(struct mmc_host *, unsigned int,
-	struct mmc_command *, int);
+#define EXT_CSD_CMD_SET_NORMAL		(1<<0)
+#define EXT_CSD_CMD_SET_SECURE		(1<<1)
+#define EXT_CSD_CMD_SET_CPSECURE	(1<<2)
 
-extern void mmc_set_data_timeout(struct mmc_data *, const struct mmc_card *, int);
+#define EXT_CSD_CARD_TYPE_26	(1<<0)	/* Card can run at 26MHz */
+#define EXT_CSD_CARD_TYPE_52	(1<<1)	/* Card can run at 52MHz */
 
-extern int __mmc_claim_host(struct mmc_host *host, struct mmc_card *card);
+#define EXT_CSD_BUS_WIDTH_1	0	/* Card is in 1 bit mode */
+#define EXT_CSD_BUS_WIDTH_4	1	/* Card is in 4 bit mode */
+#define EXT_CSD_BUS_WIDTH_8	2	/* Card is in 8 bit mode */
 
-static inline void mmc_claim_host(struct mmc_host *host)
-{
-	__mmc_claim_host(host, (struct mmc_card *)-1);
-}
+/*
+ * MMC_SWITCH access modes
+ */
 
-extern void mmc_release_host(struct mmc_host *host);
+#define MMC_SWITCH_MODE_CMD_SET		0x00	/* Change the command set */
+#define MMC_SWITCH_MODE_SET_BITS	0x01	/* Set bits which are 1 in value */
+#define MMC_SWITCH_MODE_CLEAR_BITS	0x02	/* Clear bits which are 1 in value */
+#define MMC_SWITCH_MODE_WRITE_BYTE	0x03	/* Set target to value */
 
-#endif
+#endif  /* MMC_MMC_PROTOCOL_H */
+
diff --git a/include/linux/mmc/protocol.h b/include/linux/mmc/protocol.h
deleted file mode 100644
index c90b676..0000000
--- a/include/linux/mmc/protocol.h
+++ /dev/null
@@ -1,327 +0,0 @@
-/*
- * Header for MultiMediaCard (MMC)
- *
- * Copyright 2002 Hewlett-Packard Company
- *
- * Use consistent with the GNU GPL is permitted,
- * provided that this copyright notice is
- * preserved in its entirety in all copies and derived works.
- *
- * HEWLETT-PACKARD COMPANY MAKES NO WARRANTIES, EXPRESSED OR IMPLIED,
- * AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS
- * FITNESS FOR ANY PARTICULAR PURPOSE.
- *
- * Many thanks to Alessandro Rubini and Jonathan Corbet!
- *
- * Based strongly on code by:
- *
- * Author: Yong-iL Joh <tolkien@mizi.com>
- * Date  : $Date: 2002/06/18 12:37:30 $
- *
- * Author:  Andrew Christian
- *          15 May 2002
- */
-
-#ifndef MMC_MMC_PROTOCOL_H
-#define MMC_MMC_PROTOCOL_H
-
-/* Standard MMC commands (4.1)           type  argument     response */
-   /* class 1 */
-#define	MMC_GO_IDLE_STATE         0   /* bc                          */
-#define MMC_SEND_OP_COND          1   /* bcr  [31:0] OCR         R3  */
-#define MMC_ALL_SEND_CID          2   /* bcr                     R2  */
-#define MMC_SET_RELATIVE_ADDR     3   /* ac   [31:16] RCA        R1  */
-#define MMC_SET_DSR               4   /* bc   [31:16] RCA            */
-#define MMC_SWITCH                6   /* ac   [31:0] See below   R1b */
-#define MMC_SELECT_CARD           7   /* ac   [31:16] RCA        R1  */
-#define MMC_SEND_EXT_CSD          8   /* adtc                    R1  */
-#define MMC_SEND_CSD              9   /* ac   [31:16] RCA        R2  */
-#define MMC_SEND_CID             10   /* ac   [31:16] RCA        R2  */
-#define MMC_READ_DAT_UNTIL_STOP  11   /* adtc [31:0] dadr        R1  */
-#define MMC_STOP_TRANSMISSION    12   /* ac                      R1b */
-#define MMC_SEND_STATUS	         13   /* ac   [31:16] RCA        R1  */
-#define MMC_GO_INACTIVE_STATE    15   /* ac   [31:16] RCA            */
-
-  /* class 2 */
-#define MMC_SET_BLOCKLEN         16   /* ac   [31:0] block len   R1  */
-#define MMC_READ_SINGLE_BLOCK    17   /* adtc [31:0] data addr   R1  */
-#define MMC_READ_MULTIPLE_BLOCK  18   /* adtc [31:0] data addr   R1  */
-
-  /* class 3 */
-#define MMC_WRITE_DAT_UNTIL_STOP 20   /* adtc [31:0] data addr   R1  */
-
-  /* class 4 */
-#define MMC_SET_BLOCK_COUNT      23   /* adtc [31:0] data addr   R1  */
-#define MMC_WRITE_BLOCK          24   /* adtc [31:0] data addr   R1  */
-#define MMC_WRITE_MULTIPLE_BLOCK 25   /* adtc                    R1  */
-#define MMC_PROGRAM_CID          26   /* adtc                    R1  */
-#define MMC_PROGRAM_CSD          27   /* adtc                    R1  */
-
-  /* class 6 */
-#define MMC_SET_WRITE_PROT       28   /* ac   [31:0] data addr   R1b */
-#define MMC_CLR_WRITE_PROT       29   /* ac   [31:0] data addr   R1b */
-#define MMC_SEND_WRITE_PROT      30   /* adtc [31:0] wpdata addr R1  */
-
-  /* class 5 */
-#define MMC_ERASE_GROUP_START    35   /* ac   [31:0] data addr   R1  */
-#define MMC_ERASE_GROUP_END      36   /* ac   [31:0] data addr   R1  */
-#define MMC_ERASE                38   /* ac                      R1b */
-
-  /* class 9 */
-#define MMC_FAST_IO              39   /* ac   <Complex>          R4  */
-#define MMC_GO_IRQ_STATE         40   /* bcr                     R5  */
-
-  /* class 7 */
-#define MMC_LOCK_UNLOCK          42   /* adtc                    R1b */
-
-  /* class 8 */
-#define MMC_APP_CMD              55   /* ac   [31:16] RCA        R1  */
-#define MMC_GEN_CMD              56   /* adtc [0] RD/WR          R1  */
-
-/* SD commands                           type  argument     response */
-  /* class 0 */
-/* This is basically the same command as for MMC with some quirks. */
-#define SD_SEND_RELATIVE_ADDR     3   /* bcr                     R6  */
-#define SD_SEND_IF_COND           8   /* bcr  [11:0] See below   R7  */
-
-  /* class 10 */
-#define SD_SWITCH                 6   /* adtc [31:0] See below   R1  */
-
-  /* Application commands */
-#define SD_APP_SET_BUS_WIDTH      6   /* ac   [1:0] bus width    R1  */
-#define SD_APP_SEND_NUM_WR_BLKS  22   /* adtc                    R1  */
-#define SD_APP_OP_COND           41   /* bcr  [31:0] OCR         R3  */
-#define SD_APP_SEND_SCR          51   /* adtc                    R1  */
-
-/*
- * MMC_SWITCH argument format:
- *
- *	[31:26] Always 0
- *	[25:24] Access Mode
- *	[23:16] Location of target Byte in EXT_CSD
- *	[15:08] Value Byte
- *	[07:03] Always 0
- *	[02:00] Command Set
- */
-
-/*
- * SD_SWITCH argument format:
- *
- *      [31] Check (0) or switch (1)
- *      [30:24] Reserved (0)
- *      [23:20] Function group 6
- *      [19:16] Function group 5
- *      [15:12] Function group 4
- *      [11:8] Function group 3
- *      [7:4] Function group 2
- *      [3:0] Function group 1
- */
-
-/*
- * SD_SEND_IF_COND argument format:
- *
- *	[31:12] Reserved (0)
- *	[11:8] Host Voltage Supply Flags
- *	[7:0] Check Pattern (0xAA)
- */
-
-/*
-  MMC status in R1
-  Type
-  	e : error bit
-	s : status bit
-	r : detected and set for the actual command response
-	x : detected and set during command execution. the host must poll
-            the card by sending status command in order to read these bits.
-  Clear condition
-  	a : according to the card state
-	b : always related to the previous command. Reception of
-            a valid command will clear it (with a delay of one command)
-	c : clear by read
- */
-
-#define R1_OUT_OF_RANGE		(1 << 31)	/* er, c */
-#define R1_ADDRESS_ERROR	(1 << 30)	/* erx, c */
-#define R1_BLOCK_LEN_ERROR	(1 << 29)	/* er, c */
-#define R1_ERASE_SEQ_ERROR      (1 << 28)	/* er, c */
-#define R1_ERASE_PARAM		(1 << 27)	/* ex, c */
-#define R1_WP_VIOLATION		(1 << 26)	/* erx, c */
-#define R1_CARD_IS_LOCKED	(1 << 25)	/* sx, a */
-#define R1_LOCK_UNLOCK_FAILED	(1 << 24)	/* erx, c */
-#define R1_COM_CRC_ERROR	(1 << 23)	/* er, b */
-#define R1_ILLEGAL_COMMAND	(1 << 22)	/* er, b */
-#define R1_CARD_ECC_FAILED	(1 << 21)	/* ex, c */
-#define R1_CC_ERROR		(1 << 20)	/* erx, c */
-#define R1_ERROR		(1 << 19)	/* erx, c */
-#define R1_UNDERRUN		(1 << 18)	/* ex, c */
-#define R1_OVERRUN		(1 << 17)	/* ex, c */
-#define R1_CID_CSD_OVERWRITE	(1 << 16)	/* erx, c, CID/CSD overwrite */
-#define R1_WP_ERASE_SKIP	(1 << 15)	/* sx, c */
-#define R1_CARD_ECC_DISABLED	(1 << 14)	/* sx, a */
-#define R1_ERASE_RESET		(1 << 13)	/* sr, c */
-#define R1_STATUS(x)            (x & 0xFFFFE000)
-#define R1_CURRENT_STATE(x)    	((x & 0x00001E00) >> 9)	/* sx, b (4 bits) */
-#define R1_READY_FOR_DATA	(1 << 8)	/* sx, a */
-#define R1_APP_CMD		(1 << 5)	/* sr, c */
-
-/* These are unpacked versions of the actual responses */
-
-struct _mmc_csd {
-	u8  csd_structure;
-	u8  spec_vers;
-	u8  taac;
-	u8  nsac;
-	u8  tran_speed;
-	u16 ccc;
-	u8  read_bl_len;
-	u8  read_bl_partial;
-	u8  write_blk_misalign;
-	u8  read_blk_misalign;
-	u8  dsr_imp;
-	u16 c_size;
-	u8  vdd_r_curr_min;
-	u8  vdd_r_curr_max;
-	u8  vdd_w_curr_min;
-	u8  vdd_w_curr_max;
-	u8  c_size_mult;
-	union {
-		struct { /* MMC system specification version 3.1 */
-			u8  erase_grp_size;
-			u8  erase_grp_mult;
-		} v31;
-		struct { /* MMC system specification version 2.2 */
-			u8  sector_size;
-			u8  erase_grp_size;
-		} v22;
-	} erase;
-	u8  wp_grp_size;
-	u8  wp_grp_enable;
-	u8  default_ecc;
-	u8  r2w_factor;
-	u8  write_bl_len;
-	u8  write_bl_partial;
-	u8  file_format_grp;
-	u8  copy;
-	u8  perm_write_protect;
-	u8  tmp_write_protect;
-	u8  file_format;
-	u8  ecc;
-};
-
-#define MMC_VDD_145_150	0x00000001	/* VDD voltage 1.45 - 1.50 */
-#define MMC_VDD_150_155	0x00000002	/* VDD voltage 1.50 - 1.55 */
-#define MMC_VDD_155_160	0x00000004	/* VDD voltage 1.55 - 1.60 */
-#define MMC_VDD_160_165	0x00000008	/* VDD voltage 1.60 - 1.65 */
-#define MMC_VDD_165_170	0x00000010	/* VDD voltage 1.65 - 1.70 */
-#define MMC_VDD_17_18	0x00000020	/* VDD voltage 1.7 - 1.8 */
-#define MMC_VDD_18_19	0x00000040	/* VDD voltage 1.8 - 1.9 */
-#define MMC_VDD_19_20	0x00000080	/* VDD voltage 1.9 - 2.0 */
-#define MMC_VDD_20_21	0x00000100	/* VDD voltage 2.0 ~ 2.1 */
-#define MMC_VDD_21_22	0x00000200	/* VDD voltage 2.1 ~ 2.2 */
-#define MMC_VDD_22_23	0x00000400	/* VDD voltage 2.2 ~ 2.3 */
-#define MMC_VDD_23_24	0x00000800	/* VDD voltage 2.3 ~ 2.4 */
-#define MMC_VDD_24_25	0x00001000	/* VDD voltage 2.4 ~ 2.5 */
-#define MMC_VDD_25_26	0x00002000	/* VDD voltage 2.5 ~ 2.6 */
-#define MMC_VDD_26_27	0x00004000	/* VDD voltage 2.6 ~ 2.7 */
-#define MMC_VDD_27_28	0x00008000	/* VDD voltage 2.7 ~ 2.8 */
-#define MMC_VDD_28_29	0x00010000	/* VDD voltage 2.8 ~ 2.9 */
-#define MMC_VDD_29_30	0x00020000	/* VDD voltage 2.9 ~ 3.0 */
-#define MMC_VDD_30_31	0x00040000	/* VDD voltage 3.0 ~ 3.1 */
-#define MMC_VDD_31_32	0x00080000	/* VDD voltage 3.1 ~ 3.2 */
-#define MMC_VDD_32_33	0x00100000	/* VDD voltage 3.2 ~ 3.3 */
-#define MMC_VDD_33_34	0x00200000	/* VDD voltage 3.3 ~ 3.4 */
-#define MMC_VDD_34_35	0x00400000	/* VDD voltage 3.4 ~ 3.5 */
-#define MMC_VDD_35_36	0x00800000	/* VDD voltage 3.5 ~ 3.6 */
-#define MMC_CARD_BUSY	0x80000000	/* Card Power up status bit */
-
-/*
- * Card Command Classes (CCC)
- */
-#define CCC_BASIC		(1<<0)	/* (0) Basic protocol functions */
-					/* (CMD0,1,2,3,4,7,9,10,12,13,15) */
-#define CCC_STREAM_READ		(1<<1)	/* (1) Stream read commands */
-					/* (CMD11) */
-#define CCC_BLOCK_READ		(1<<2)	/* (2) Block read commands */
-					/* (CMD16,17,18) */
-#define CCC_STREAM_WRITE	(1<<3)	/* (3) Stream write commands */
-					/* (CMD20) */
-#define CCC_BLOCK_WRITE		(1<<4)	/* (4) Block write commands */
-					/* (CMD16,24,25,26,27) */
-#define CCC_ERASE		(1<<5)	/* (5) Ability to erase blocks */
-					/* (CMD32,33,34,35,36,37,38,39) */
-#define CCC_WRITE_PROT		(1<<6)	/* (6) Able to write protect blocks */
-					/* (CMD28,29,30) */
-#define CCC_LOCK_CARD		(1<<7)	/* (7) Able to lock down card */
-					/* (CMD16,CMD42) */
-#define CCC_APP_SPEC		(1<<8)	/* (8) Application specific */
-					/* (CMD55,56,57,ACMD*) */
-#define CCC_IO_MODE		(1<<9)	/* (9) I/O mode */
-					/* (CMD5,39,40,52,53) */
-#define CCC_SWITCH		(1<<10)	/* (10) High speed switch */
-					/* (CMD6,34,35,36,37,50) */
-					/* (11) Reserved */
-					/* (CMD?) */
-
-/*
- * CSD field definitions
- */
-
-#define CSD_STRUCT_VER_1_0  0           /* Valid for system specification 1.0 - 1.2 */
-#define CSD_STRUCT_VER_1_1  1           /* Valid for system specification 1.4 - 2.2 */
-#define CSD_STRUCT_VER_1_2  2           /* Valid for system specification 3.1 - 3.2 - 3.31 - 4.0 - 4.1 */
-#define CSD_STRUCT_EXT_CSD  3           /* Version is coded in CSD_STRUCTURE in EXT_CSD */
-
-#define CSD_SPEC_VER_0      0           /* Implements system specification 1.0 - 1.2 */
-#define CSD_SPEC_VER_1      1           /* Implements system specification 1.4 */
-#define CSD_SPEC_VER_2      2           /* Implements system specification 2.0 - 2.2 */
-#define CSD_SPEC_VER_3      3           /* Implements system specification 3.1 - 3.2 - 3.31 */
-#define CSD_SPEC_VER_4      4           /* Implements system specification 4.0 - 4.1 */
-
-/*
- * EXT_CSD fields
- */
-
-#define EXT_CSD_BUS_WIDTH	183	/* R/W */
-#define EXT_CSD_HS_TIMING	185	/* R/W */
-#define EXT_CSD_CARD_TYPE	196	/* RO */
-
-/*
- * EXT_CSD field definitions
- */
-
-#define EXT_CSD_CMD_SET_NORMAL		(1<<0)
-#define EXT_CSD_CMD_SET_SECURE		(1<<1)
-#define EXT_CSD_CMD_SET_CPSECURE	(1<<2)
-
-#define EXT_CSD_CARD_TYPE_26	(1<<0)	/* Card can run at 26MHz */
-#define EXT_CSD_CARD_TYPE_52	(1<<1)	/* Card can run at 52MHz */
-
-#define EXT_CSD_BUS_WIDTH_1	0	/* Card is in 1 bit mode */
-#define EXT_CSD_BUS_WIDTH_4	1	/* Card is in 4 bit mode */
-#define EXT_CSD_BUS_WIDTH_8	2	/* Card is in 8 bit mode */
-
-/*
- * MMC_SWITCH access modes
- */
-
-#define MMC_SWITCH_MODE_CMD_SET		0x00	/* Change the command set */
-#define MMC_SWITCH_MODE_SET_BITS	0x01	/* Set bits which are 1 in value */
-#define MMC_SWITCH_MODE_CLEAR_BITS	0x02	/* Clear bits which are 1 in value */
-#define MMC_SWITCH_MODE_WRITE_BYTE	0x03	/* Set target to value */
-
-/*
- * SCR field definitions
- */
-
-#define SCR_SPEC_VER_0      0           /* Implements system specification 1.0 - 1.01 */
-#define SCR_SPEC_VER_1      1           /* Implements system specification 1.10 */
-#define SCR_SPEC_VER_2      2           /* Implements system specification 2.00 */
-
-/*
- * SD bus widths
- */
-#define SD_BUS_WIDTH_1      0
-#define SD_BUS_WIDTH_4      2
-
-#endif  /* MMC_MMC_PROTOCOL_H */
-
diff --git a/include/linux/mmc/sd.h b/include/linux/mmc/sd.h
new file mode 100644
index 0000000..f310062
--- /dev/null
+++ b/include/linux/mmc/sd.h
@@ -0,0 +1,83 @@
+/*
+ *  include/linux/mmc/sd.h
+ *
+ *  Copyright (C) 2005-2007 Pierre Ossman, 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.
+ */
+
+#ifndef MMC_SD_H
+#define MMC_SD_H
+
+/* SD commands                           type  argument     response */
+  /* class 0 */
+/* This is basically the same command as for MMC with some quirks. */
+#define SD_SEND_RELATIVE_ADDR     3   /* bcr                     R6  */
+#define SD_SEND_IF_COND           8   /* bcr  [11:0] See below   R7  */
+
+  /* class 10 */
+#define SD_SWITCH                 6   /* adtc [31:0] See below   R1  */
+
+  /* Application commands */
+#define SD_APP_SET_BUS_WIDTH      6   /* ac   [1:0] bus width    R1  */
+#define SD_APP_SEND_NUM_WR_BLKS  22   /* adtc                    R1  */
+#define SD_APP_OP_COND           41   /* bcr  [31:0] OCR         R3  */
+#define SD_APP_SEND_SCR          51   /* adtc                    R1  */
+
+/*
+ * SD_SWITCH argument format:
+ *
+ *      [31] Check (0) or switch (1)
+ *      [30:24] Reserved (0)
+ *      [23:20] Function group 6
+ *      [19:16] Function group 5
+ *      [15:12] Function group 4
+ *      [11:8] Function group 3
+ *      [7:4] Function group 2
+ *      [3:0] Function group 1
+ */
+
+/*
+ * SD_SEND_IF_COND argument format:
+ *
+ *	[31:12] Reserved (0)
+ *	[11:8] Host Voltage Supply Flags
+ *	[7:0] Check Pattern (0xAA)
+ */
+
+/*
+ * SCR field definitions
+ */
+
+#define SCR_SPEC_VER_0		0	/* Implements system specification 1.0 - 1.01 */
+#define SCR_SPEC_VER_1		1	/* Implements system specification 1.10 */
+#define SCR_SPEC_VER_2		2	/* Implements system specification 2.00 */
+
+/*
+ * SD bus widths
+ */
+#define SD_BUS_WIDTH_1		0
+#define SD_BUS_WIDTH_4		2
+
+/*
+ * SD_SWITCH mode
+ */
+#define SD_SWITCH_CHECK		0
+#define SD_SWITCH_SET		1
+
+/*
+ * SD_SWITCH function groups
+ */
+#define SD_SWITCH_GRP_ACCESS	0
+
+/*
+ * SD_SWITCH access modes
+ */
+#define SD_SWITCH_ACCESS_DEF	0
+#define SD_SWITCH_ACCESS_HS	1
+
+#endif
+
diff --git a/include/linux/module.h b/include/linux/module.h
index 95679eb..f0b0faf4 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -568,7 +568,7 @@
 #ifdef CONFIG_SYSFS
 struct module;
 
-extern struct subsystem module_subsys;
+extern struct kset module_subsys;
 
 int mod_sysfs_init(struct module *mod);
 int mod_sysfs_setup(struct module *mod,
diff --git a/include/linux/msi.h b/include/linux/msi.h
index e38fe682..94bb46d 100644
--- a/include/linux/msi.h
+++ b/include/linux/msi.h
@@ -1,6 +1,8 @@
 #ifndef LINUX_MSI_H
 #define LINUX_MSI_H
 
+#include <linux/list.h>
+
 struct msi_msg {
 	u32	address_lo;	/* low 32 bits of msi message address */
 	u32	address_hi;	/* high 32 bits of msi message address */
@@ -24,10 +26,8 @@
 		unsigned default_irq;	/* default pre-assigned irq	  */
 	}msi_attrib;
 
-	struct {
-		__u16	head;
-		__u16	tail;
-	}link;
+	unsigned int irq;
+	struct list_head list;
 
 	void __iomem *mask_base;
 	struct pci_dev *dev;
@@ -41,6 +41,9 @@
  */
 int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc);
 void arch_teardown_msi_irq(unsigned int irq);
+extern int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type);
+extern void arch_teardown_msi_irqs(struct pci_dev *dev);
+extern int arch_msi_check_device(struct pci_dev* dev, int nvec, int type);
 
 
 #endif /* LINUX_MSI_H */
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index ac0c92b..3044622 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -304,7 +304,7 @@
 
 	unsigned long		state;
 
-	struct net_device	*next;
+	struct list_head	dev_list;
 	
 	/* The device initialization function. Called only once. */
 	int			(*init)(struct net_device *dev);
@@ -575,13 +575,36 @@
 #include <linux/notifier.h>
 
 extern struct net_device		loopback_dev;		/* The loopback */
-extern struct net_device		*dev_base;		/* All devices */
+extern struct list_head			dev_base_head;		/* All devices */
 extern rwlock_t				dev_base_lock;		/* Device list lock */
 
+#define for_each_netdev(d)		\
+		list_for_each_entry(d, &dev_base_head, dev_list)
+#define for_each_netdev_safe(d, n)	\
+		list_for_each_entry_safe(d, n, &dev_base_head, dev_list)
+#define for_each_netdev_continue(d)		\
+		list_for_each_entry_continue(d, &dev_base_head, dev_list)
+#define net_device_entry(lh)	list_entry(lh, struct net_device, dev_list)
+
+static inline struct net_device *next_net_device(struct net_device *dev)
+{
+	struct list_head *lh;
+
+	lh = dev->dev_list.next;
+	return lh == &dev_base_head ? NULL : net_device_entry(lh);
+}
+
+static inline struct net_device *first_net_device(void)
+{
+	return list_empty(&dev_base_head) ? NULL :
+		net_device_entry(dev_base_head.next);
+}
+
 extern int 			netdev_boot_setup_check(struct net_device *dev);
 extern unsigned long		netdev_boot_base(const char *prefix, int unit);
 extern struct net_device    *dev_getbyhwaddr(unsigned short type, char *hwaddr);
 extern struct net_device *dev_getfirstbyhwtype(unsigned short type);
+extern struct net_device *__dev_getfirstbyhwtype(unsigned short type);
 extern void		dev_add_pack(struct packet_type *pt);
 extern void		dev_remove_pack(struct packet_type *pt);
 extern void		__dev_remove_pack(struct packet_type *pt);
diff --git a/include/linux/netfilter/nf_conntrack_proto_gre.h b/include/linux/netfilter/nf_conntrack_proto_gre.h
index 4e6bbce..535e4219 100644
--- a/include/linux/netfilter/nf_conntrack_proto_gre.h
+++ b/include/linux/netfilter/nf_conntrack_proto_gre.h
@@ -87,24 +87,6 @@
 /* delete keymap entries */
 void nf_ct_gre_keymap_destroy(struct nf_conn *ct);
 
-/* get pointer to gre key, if present */
-static inline __be32 *gre_key(struct gre_hdr *greh)
-{
-	if (!greh->key)
-		return NULL;
-	if (greh->csum || greh->routing)
-		return (__be32 *)(greh+sizeof(*greh)+4);
-	return (__be32 *)(greh+sizeof(*greh));
-}
-
-/* get pointer ot gre csum, if present */
-static inline __sum16 *gre_csum(struct gre_hdr *greh)
-{
-	if (!greh->csum)
-		return NULL;
-	return (__sum16 *)(greh+sizeof(*greh));
-}
-
 extern void nf_ct_gre_keymap_flush(void);
 extern void nf_nat_need_gre(void);
 
diff --git a/include/linux/netfilter_bridge.h b/include/linux/netfilter_bridge.h
index 1906003..533ee35 100644
--- a/include/linux/netfilter_bridge.h
+++ b/include/linux/netfilter_bridge.h
@@ -55,18 +55,25 @@
   	return 0;
 }
 
+static inline unsigned int nf_bridge_encap_header_len(const struct sk_buff *skb)
+{
+	switch (skb->protocol) {
+	case __constant_htons(ETH_P_8021Q):
+		return VLAN_HLEN;
+	case __constant_htons(ETH_P_PPP_SES):
+		return PPPOE_SES_HLEN;
+	default:
+		return 0;
+	}
+}
+
 /* This is called by the IP fragmenting code and it ensures there is
  * enough room for the encapsulating header (if there is one). */
-static inline int nf_bridge_pad(const struct sk_buff *skb)
+static inline unsigned int nf_bridge_pad(const struct sk_buff *skb)
 {
-	int padding = 0;
-
-	if (skb->nf_bridge && skb->protocol == htons(ETH_P_8021Q))
-		padding = VLAN_HLEN;
-	else if (skb->nf_bridge && skb->protocol == htons(ETH_P_PPP_SES))
-		padding = PPPOE_SES_HLEN;
-
-	return padding;
+	if (skb->nf_bridge)
+		return nf_bridge_encap_header_len(skb);
+	return 0;
 }
 
 struct bridge_skb_cb {
diff --git a/include/linux/netlink.h b/include/linux/netlink.h
index f41688f..2e23353 100644
--- a/include/linux/netlink.h
+++ b/include/linux/netlink.h
@@ -31,7 +31,7 @@
 {
 	sa_family_t	nl_family;	/* AF_NETLINK	*/
 	unsigned short	nl_pad;		/* zero		*/
-	__u32		nl_pid;		/* process pid	*/
+	__u32		nl_pid;		/* port ID	*/
        	__u32		nl_groups;	/* multicast groups mask */
 };
 
@@ -41,7 +41,7 @@
 	__u16		nlmsg_type;	/* Message content */
 	__u16		nlmsg_flags;	/* Additional flags */
 	__u32		nlmsg_seq;	/* Sequence number */
-	__u32		nlmsg_pid;	/* Sending process PID */
+	__u32		nlmsg_pid;	/* Sending process port ID */
 };
 
 /* Flags values */
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index e9ae0c6..0543439 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -455,7 +455,7 @@
 /*
  * Allocate nfs_write_data structures
  */
-extern struct nfs_write_data *nfs_writedata_alloc(size_t len);
+extern struct nfs_write_data *nfs_writedata_alloc(unsigned int npages);
 
 /*
  * linux/fs/nfs/read.c
@@ -469,7 +469,7 @@
 /*
  * Allocate nfs_read_data structures
  */
-extern struct nfs_read_data *nfs_readdata_alloc(size_t len);
+extern struct nfs_read_data *nfs_readdata_alloc(unsigned int npages);
 
 /*
  * linux/fs/nfs3proc.c
diff --git a/include/linux/nfs_mount.h b/include/linux/nfs_mount.h
index 659c754..cc8b9c5 100644
--- a/include/linux/nfs_mount.h
+++ b/include/linux/nfs_mount.h
@@ -61,6 +61,7 @@
 #define NFS_MOUNT_NOACL		0x0800	/* 4 */
 #define NFS_MOUNT_STRICTLOCK	0x1000	/* reserved for NFSv4 */
 #define NFS_MOUNT_SECFLAVOUR	0x2000	/* 5 */
+#define NFS_MOUNT_NORDIRPLUS	0x4000	/* 5 */
 #define NFS_MOUNT_FLAGMASK	0xFFFF
 
 #endif
diff --git a/include/linux/nfs_page.h b/include/linux/nfs_page.h
index 16b0266..41afab6 100644
--- a/include/linux/nfs_page.h
+++ b/include/linux/nfs_page.h
@@ -21,8 +21,7 @@
 /*
  * Valid flags for the radix tree
  */
-#define NFS_PAGE_TAG_DIRTY	0
-#define NFS_PAGE_TAG_WRITEBACK	1
+#define NFS_PAGE_TAG_WRITEBACK	0
 
 /*
  * Valid flags for a dirty buffer
@@ -39,7 +38,7 @@
 	struct page		*wb_page;	/* page to read in/write out */
 	struct nfs_open_context	*wb_context;	/* File state context info */
 	atomic_t		wb_complete;	/* i/os we're waiting for */
-	unsigned long		wb_index;	/* Offset >> PAGE_CACHE_SHIFT */
+	pgoff_t			wb_index;	/* Offset >> PAGE_CACHE_SHIFT */
 	unsigned int		wb_offset,	/* Offset & ~PAGE_CACHE_MASK */
 				wb_pgbase,	/* Start of page data */
 				wb_bytes;	/* Length of request */
@@ -48,6 +47,19 @@
 	struct nfs_writeverf	wb_verf;	/* Commit cookie */
 };
 
+struct nfs_pageio_descriptor {
+	struct list_head	pg_list;
+	unsigned long		pg_bytes_written;
+	size_t			pg_count;
+	size_t			pg_bsize;
+	unsigned int		pg_base;
+
+	struct inode		*pg_inode;
+	int			(*pg_doio)(struct inode *, struct list_head *, unsigned int, size_t, int);
+	int 			pg_ioflags;
+	int			pg_error;
+};
+
 #define NFS_WBACK_BUSY(req)	(test_bit(PG_BUSY,&(req)->wb_flags))
 
 extern	struct nfs_page *nfs_create_request(struct nfs_open_context *ctx,
@@ -59,13 +71,16 @@
 extern	void nfs_release_request(struct nfs_page *req);
 
 
-extern	long nfs_scan_dirty(struct address_space *mapping,
-				struct writeback_control *wbc,
-				struct list_head *dst);
 extern	int nfs_scan_list(struct nfs_inode *nfsi, struct list_head *head, struct list_head *dst,
-			  unsigned long idx_start, unsigned int npages);
-extern	int nfs_coalesce_requests(struct list_head *, struct list_head *,
-				  unsigned int);
+			  pgoff_t idx_start, unsigned int npages);
+extern	void nfs_pageio_init(struct nfs_pageio_descriptor *desc,
+			     struct inode *inode,
+			     int (*doio)(struct inode *, struct list_head *, unsigned int, size_t, int),
+			     size_t bsize,
+			     int how);
+extern	int nfs_pageio_add_request(struct nfs_pageio_descriptor *,
+				   struct nfs_page *);
+extern	void nfs_pageio_complete(struct nfs_pageio_descriptor *desc);
 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);
diff --git a/include/linux/nubus.h b/include/linux/nubus.h
index 870e66a..cdb3e9b 100644
--- a/include/linux/nubus.h
+++ b/include/linux/nubus.h
@@ -28,18 +28,18 @@
 };
 
 enum nubus_type_network {
-	NUBUS_TYPE_ETHERNET 	 = 0x0001,
-	NUBUS_TYPE_RS232    	 = 0x0002
+	NUBUS_TYPE_ETHERNET      = 0x0001,
+	NUBUS_TYPE_RS232         = 0x0002
 };
 
 enum nubus_type_display {
-	NUBUS_TYPE_VIDEO 	 = 0x0001
+	NUBUS_TYPE_VIDEO         = 0x0001
 };
 
 enum nubus_type_cpu {
-	NUBUS_TYPE_68020 	 = 0x0003,
-	NUBUS_TYPE_68030 	 = 0x0004,
-	NUBUS_TYPE_68040 	 = 0x0005
+	NUBUS_TYPE_68020         = 0x0003,
+	NUBUS_TYPE_68030         = 0x0004,
+	NUBUS_TYPE_68040         = 0x0005
 };
 
 /* Known <Cat,Type,SW,HW> tuples: (according to TattleTech and Slots)
@@ -56,6 +56,7 @@
  *
  *  SONIC comm-slot/on-board and DuoDock Ethernet: <4,1,1,272>
  *  SONIC LC-PDS Ethernet (Dayna, but like Apple 16-bit, sort of): <4,1,1,271>
+ *  Apple SONIC LC-PDS Ethernet ("Apple Ethernet LC Twisted-Pair Card"): <4,1,0,281>
  *  Sonic Systems Ethernet A-Series Card: <4,1,268,256>
  *  Asante MacCon NuBus-A: <4,1,260,256> (alpha-1.0,1.1 revision)
  *   ROM on the above card: <2,1,0,0>
@@ -80,24 +81,26 @@
 /* Add known DrSW values here */
 enum nubus_drsw {
 	/* NUBUS_CAT_DISPLAY */
-	NUBUS_DRSW_APPLE       	= 0x0001,
-	NUBUS_DRSW_APPLE_HIRES 	= 0x0013, /* MacII HiRes card driver */
+	NUBUS_DRSW_APPLE        = 0x0001,
+	NUBUS_DRSW_APPLE_HIRES  = 0x0013, /* MacII HiRes card driver */
 	
 	/* NUBUS_CAT_NETWORK */
-	NUBUS_DRSW_CABLETRON   	= 0x0001,
-	NUBUS_DRSW_SONIC_LC    	= 0x0001,
-	NUBUS_DRSW_KINETICS    	= 0x0103,
-	NUBUS_DRSW_ASANTE      	= 0x0104,
-	NUBUS_DRSW_DAYNA       	= 0x010b,
-	NUBUS_DRSW_FARALLON    	= 0x010c,
-	NUBUS_DRSW_APPLE_SN    	= 0x010f,
-	NUBUS_DRSW_DAYNA2	= 0x0115,
+	NUBUS_DRSW_3COM         = 0x0000,
+	NUBUS_DRSW_CABLETRON    = 0x0001,
+	NUBUS_DRSW_SONIC_LC     = 0x0001,
+	NUBUS_DRSW_KINETICS     = 0x0103,
+	NUBUS_DRSW_ASANTE       = 0x0104,
+	NUBUS_DRSW_TECHWORKS    = 0x0109,
+	NUBUS_DRSW_DAYNA        = 0x010b,
+	NUBUS_DRSW_FARALLON     = 0x010c,
+	NUBUS_DRSW_APPLE_SN     = 0x010f,
+	NUBUS_DRSW_DAYNA2       = 0x0115,
 	NUBUS_DRSW_FOCUS        = 0x011a,
 	NUBUS_DRSW_ASANTE_CS    = 0x011d, /* use asante SMC9194 driver */
-	NUBUS_DRSW_DAYNA_LC	= 0x011e,
+	NUBUS_DRSW_DAYNA_LC     = 0x011e,
 
 	/* NUBUS_CAT_CPU */
-	NUBUS_DRSW_NONE        	= 0x0000,
+	NUBUS_DRSW_NONE         = 0x0000,
 };
 
 /* DrHW: Uniquely identifies the hardware interface to a board (or at
@@ -107,27 +110,48 @@
 /* Add known DrHW values here */
 enum nubus_drhw {
 	/* NUBUS_CAT_DISPLAY */
-	NUBUS_DRHW_APPLE_TFB	= 0x0001, /* Toby frame buffer card */
-	NUBUS_DRHW_APPLE_HRVC	= 0x0013, /* Mac II High Res Video card */
-	NUBUS_DRHW_APPLE_RBV1   = 0x0018, /* IIci RBV video */
-	NUBUS_DRHW_APPLE_MDC    = 0x0019, /* Macintosh Display Card */
-	NUBUS_DRHW_APPLE_SONORA = 0x0022, /* Sonora built-in video */
-	NUBUS_DRHW_APPLE_JET 	= 0x0029, /* Jet framebuffer (DuoDock) */
+	NUBUS_DRHW_APPLE_TFB      = 0x0001, /* Toby frame buffer card */
+	NUBUS_DRHW_APPLE_WVC      = 0x0006, /* Apple Workstation Video Card */
+	NUBUS_DRHW_SIGMA_CLRMAX   = 0x0007, /* Sigma Design ColorMax */
+	NUBUS_DRHW_APPLE_SE30     = 0x0009, /* Apple SE/30 video */
+	NUBUS_DRHW_APPLE_HRVC     = 0x0013, /* Mac II High-Res Video Card */
+	NUBUS_DRHW_APPLE_PVC      = 0x0017, /* Mac II Portrait Video Card */
+	NUBUS_DRHW_APPLE_RBV1     = 0x0018, /* IIci RBV video */
+	NUBUS_DRHW_APPLE_MDC      = 0x0019, /* Macintosh Display Card */
+	NUBUS_DRHW_APPLE_SONORA   = 0x0022, /* Sonora built-in video */
+	NUBUS_DRHW_APPLE_24AC     = 0x002b, /* Mac 24AC Video Card */
 	NUBUS_DRHW_APPLE_VALKYRIE = 0x002e,
-	NUBUS_DRHW_THUNDER24	= 0x02cb, /* SuperMac Thunder/24 */
+	NUBUS_DRHW_APPLE_JET      = 0x0029, /* Jet framebuffer (DuoDock) */
+	NUBUS_DRHW_SMAC_GFX       = 0x0105, /* SuperMac GFX */
+	NUBUS_DRHW_RASTER_CB264   = 0x013B, /* RasterOps ColorBoard 264 */
+	NUBUS_DRHW_MICRON_XCEED   = 0x0146, /* Micron Exceed color */
+	NUBUS_DRHW_RDIUS_GSC      = 0x0153, /* Radius GS/C */
+	NUBUS_DRHW_SMAC_SPEC8     = 0x017B, /* SuperMac Spectrum/8 */
+	NUBUS_DRHW_SMAC_SPEC24    = 0x017C, /* SuperMac Spectrum/24 */
+	NUBUS_DRHW_RASTER_CB364   = 0x026F, /* RasterOps ColorBoard 364 */
+	NUBUS_DRHW_RDIUS_DCGX     = 0x027C, /* Radius DirectColor/GX */
+	NUBUS_DRHW_RDIUS_PC8      = 0x0291, /* Radius PrecisionColor 8 */
+	NUBUS_DRHW_LAPIS_PCS8     = 0x0292, /* Lapis ProColorServer 8 */
+	NUBUS_DRHW_RASTER_24LXI   = 0x02A0, /* RasterOps 8/24 XLi */
+	NUBUS_DRHW_RASTER_PBPGT   = 0x02A5, /* RasterOps PaintBoard Prism GT */
+	NUBUS_DRHW_EMACH_FSX      = 0x02AE, /* E-Machines Futura SX */
+	NUBUS_DRHW_SMAC_THUND24   = 0x02CB, /* SuperMac Thunder/24 */
+	NUBUS_DRHW_RDIUS_PC24XP   = 0x0406, /* Radius PrecisionColor 24Xp */
+	NUBUS_DRHW_RDIUS_PC24X    = 0x040A, /* Radius PrecisionColor 24X */
+	NUBUS_DRHW_RDIUS_PC8XJ    = 0x040B, /* Radius PrecisionColor 8XJ */
 	
 	/* NUBUS_CAT_NETWORK */
-	NUBUS_DRHW_INTERLAN     = 0x0100,
-	NUBUS_DRHW_SMC9194      = 0x0101,
-	NUBUS_DRHW_KINETICS     = 0x0106,
-	NUBUS_DRHW_CABLETRON    = 0x0109,
-	NUBUS_DRHW_ASANTE_LC    = 0x010f,
-	NUBUS_DRHW_SONIC        = 0x0110,
-	NUBUS_DRHW_SONIC_NB	= 0x0118,
-	NUBUS_DRHW_SONIC_LC	= 0x0119,
-	
-	/* NUBUS_CAT_COMMUNICATIONS */
-	NUBUS_DRHW_DOVEFAX	= 0x0100,
+	NUBUS_DRHW_INTERLAN       = 0x0100,
+	NUBUS_DRHW_SMC9194        = 0x0101,
+	NUBUS_DRHW_KINETICS       = 0x0106,
+	NUBUS_DRHW_CABLETRON      = 0x0109,
+	NUBUS_DRHW_ASANTE_LC      = 0x010f,
+	NUBUS_DRHW_SONIC          = 0x0110,
+	NUBUS_DRHW_TECHWORKS      = 0x0112,
+	NUBUS_DRHW_APPLE_SONIC_NB = 0x0118,
+	NUBUS_DRHW_APPLE_SONIC_LC = 0x0119,
+	NUBUS_DRHW_FOCUS          = 0x011c,
+	NUBUS_DRHW_SONNET         = 0x011d,
 };
 
 /* Resource IDs: These are the identifiers for the various weird and
@@ -153,17 +177,17 @@
 
 /* Category-specific resources. */
 enum nubus_board_res_id {
-	NUBUS_RESID_BOARDID	 = 0x0020,
+	NUBUS_RESID_BOARDID      = 0x0020,
 	NUBUS_RESID_PRAMINITDATA = 0x0021,
-	NUBUS_RESID_PRIMARYINIT	 = 0x0022,
+	NUBUS_RESID_PRIMARYINIT  = 0x0022,
 	NUBUS_RESID_TIMEOUTCONST = 0x0023,
-	NUBUS_RESID_VENDORINFO	 = 0x0024,
-	NUBUS_RESID_BOARDFLAGS	 = 0x0025,
-	NUBUS_RESID_SECONDINIT	 = 0x0026,
+	NUBUS_RESID_VENDORINFO   = 0x0024,
+	NUBUS_RESID_BOARDFLAGS   = 0x0025,
+	NUBUS_RESID_SECONDINIT   = 0x0026,
 
 	/* Not sure why Apple put these next two in here */
-	NUBUS_RESID_VIDNAMES 	 = 0x0041,
-	NUBUS_RESID_VIDMODES 	 = 0x007e
+	NUBUS_RESID_VIDNAMES     = 0x0041,
+	NUBUS_RESID_VIDMODES     = 0x007e
 };
 
 /* Fields within the vendor info directory */
@@ -185,13 +209,13 @@
 };
 
 enum nubus_display_res_id {
-	NUBUS_RESID_GAMMADIR	= 0x0040,
-	NUBUS_RESID_FIRSTMODE	= 0x0080,
-	NUBUS_RESID_SECONDMODE	= 0x0081,
-	NUBUS_RESID_THIRDMODE	= 0x0082,
-	NUBUS_RESID_FOURTHMODE	= 0x0083,
-	NUBUS_RESID_FIFTHMODE	= 0x0084,
-	NUBUS_RESID_SIXTHMODE	= 0x0085
+	NUBUS_RESID_GAMMADIR    = 0x0040,
+	NUBUS_RESID_FIRSTMODE   = 0x0080,
+	NUBUS_RESID_SECONDMODE  = 0x0081,
+	NUBUS_RESID_THIRDMODE   = 0x0082,
+	NUBUS_RESID_FOURTHMODE  = 0x0083,
+	NUBUS_RESID_FIFTHMODE   = 0x0084,
+	NUBUS_RESID_SIXTHMODE   = 0x0085
 };
 
 struct nubus_dir
@@ -214,7 +238,7 @@
 	struct nubus_board* next;
 	struct nubus_dev* first_dev;
 	
-        /* Only 9-E actually exist, though 0-8 are also theoretically
+	/* Only 9-E actually exist, though 0-8 are also theoretically
 	   possible, and 0 is a special case which represents the
 	   motherboard and onboard peripherals (Ethernet, video) */
 	int slot;
diff --git a/include/linux/parser.h b/include/linux/parser.h
index fa33328..26b2bdf 100644
--- a/include/linux/parser.h
+++ b/include/linux/parser.h
@@ -11,7 +11,7 @@
 /* associates an integer enumerator with a pattern string. */
 struct match_token {
 	int token;
-	char *pattern;
+	const char *pattern;
 };
 
 typedef struct match_token match_table_t[];
@@ -29,5 +29,5 @@
 int match_int(substring_t *, int *result);
 int match_octal(substring_t *, int *result);
 int match_hex(substring_t *, int *result);
-void match_strcpy(char *, substring_t *);
-char *match_strdup(substring_t *);
+void match_strcpy(char *, const substring_t *);
+char *match_strdup(const substring_t *);
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 9724910..fbf3766 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -96,6 +96,19 @@
 	pci_channel_io_perm_failure = (__force pci_channel_state_t) 3,
 };
 
+typedef unsigned int __bitwise pcie_reset_state_t;
+
+enum pcie_reset_state {
+	/* Reset is NOT asserted (Use to deassert reset) */
+	pcie_deassert_reset = (__force pcie_reset_state_t) 1,
+
+	/* Use #PERST to reset PCI-E device */
+	pcie_warm_reset = (__force pcie_reset_state_t) 2,
+
+	/* Use PCI-E Hot Reset to reset device */
+	pcie_hot_reset = (__force pcie_reset_state_t) 3
+};
+
 typedef unsigned short __bitwise pci_bus_flags_t;
 enum pci_bus_flags {
 	PCI_BUS_FLAGS_NO_MSI = (__force pci_bus_flags_t) 1,
@@ -176,10 +189,12 @@
 	int rom_attr_enabled;		/* has display of the rom attribute been enabled? */
 	struct bin_attribute *res_attr[DEVICE_COUNT_RESOURCE]; /* sysfs file for resources */
 #ifdef CONFIG_PCI_MSI
-	unsigned int first_msi_irq;
+	struct list_head msi_list;
 #endif
 };
 
+extern struct pci_dev *alloc_pci_dev(void);
+
 #define pci_dev_g(n) list_entry(n, struct pci_dev, global_list)
 #define pci_dev_b(n) list_entry(n, struct pci_dev, bus_list)
 #define	to_pci_dev(n) container_of(n, struct pci_dev, dev)
@@ -392,12 +407,6 @@
 	.vendor = PCI_ANY_ID, .device = PCI_ANY_ID, \
 	.subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID
 
-/*
- * pci_module_init is obsolete, this stays here till we fix up all usages of it
- * in the tree.
- */
-#define pci_module_init	pci_register_driver
-
 /**
  * PCI_VDEVICE - macro used to describe a specific pci device in short form
  * @vend: the vendor name
@@ -532,6 +541,7 @@
 
 void pci_disable_device(struct pci_dev *dev);
 void pci_set_master(struct pci_dev *dev);
+int pci_set_pcie_reset_state(struct pci_dev *dev, enum pcie_reset_state state);
 #define HAVE_PCI_SET_MWI
 int __must_check pci_set_mwi(struct pci_dev *dev);
 void pci_clear_mwi(struct pci_dev *dev);
@@ -730,6 +740,9 @@
 static inline pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state) { return PCI_D0; }
 static inline int pci_enable_wake(struct pci_dev *dev, pci_power_t state, int enable) { return 0; }
 
+static inline int pci_request_regions(struct pci_dev *dev, const char *res_name) { return -EIO; }
+static inline void pci_release_regions(struct pci_dev *dev) { }
+
 #define pci_dma_burst_advice(pdev, strat, strategy_parameter) do { } while (0)
 
 static inline void pci_block_user_cfg_access(struct pci_dev *dev) { }
diff --git a/include/linux/pci_hotplug.h b/include/linux/pci_hotplug.h
index a675a05..ab4cb6e 100644
--- a/include/linux/pci_hotplug.h
+++ b/include/linux/pci_hotplug.h
@@ -174,7 +174,7 @@
 extern int pci_hp_deregister		(struct hotplug_slot *slot);
 extern int __must_check pci_hp_change_slot_info	(struct hotplug_slot *slot,
 						 struct hotplug_slot_info *info);
-extern struct subsystem pci_hotplug_slots_subsys;
+extern struct kset pci_hotplug_slots_subsys;
 
 /* PCI Setting Record (Type 0) */
 struct hpp_type0 {
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index 1b0ddbb..ae849f0 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -1213,11 +1213,13 @@
 #define PCI_DEVICE_ID_NVIDIA_NVENET_16              0x03E5
 #define PCI_DEVICE_ID_NVIDIA_NVENET_17              0x03E6
 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA      0x03E7
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SMBUS	    0x03EB
 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_IDE       0x03EC
 #define PCI_DEVICE_ID_NVIDIA_NVENET_18              0x03EE
 #define PCI_DEVICE_ID_NVIDIA_NVENET_19              0x03EF
 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA2     0x03F6
 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA3     0x03F7
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_SMBUS	    0x0446
 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_IDE	    0x0448
 #define PCI_DEVICE_ID_NVIDIA_NVENET_20              0x0450
 #define PCI_DEVICE_ID_NVIDIA_NVENET_21              0x0451
@@ -1924,6 +1926,7 @@
 #define PCI_DEVICE_ID_TIGON3_5752	0x1600
 #define PCI_DEVICE_ID_TIGON3_5752M	0x1601
 #define PCI_DEVICE_ID_NX2_5709		0x1639
+#define PCI_DEVICE_ID_NX2_5709S		0x163a
 #define PCI_DEVICE_ID_TIGON3_5700	0x1644
 #define PCI_DEVICE_ID_TIGON3_5701	0x1645
 #define PCI_DEVICE_ID_TIGON3_5702	0x1646
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 253a2b9..e7367c74 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -197,7 +197,7 @@
  *	@tstamp: Time we arrived
  *	@dev: Device we arrived on/are leaving by
  *	@iif: ifindex of device we arrived on
- *	@h: Transport layer header
+ *	@transport_header: Transport layer header
  *	@network_header: Network layer header
  *	@mac_header: Link layer header
  *	@dst: destination entry
diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
index c7a78eef2..6661142 100644
--- a/include/linux/sunrpc/clnt.h
+++ b/include/linux/sunrpc/clnt.h
@@ -84,7 +84,8 @@
 	u32			p_proc;		/* RPC procedure number */
 	kxdrproc_t		p_encode;	/* XDR encode function */
 	kxdrproc_t		p_decode;	/* XDR decode function */
-	unsigned int		p_bufsiz;	/* req. buffer size */
+	unsigned int		p_arglen;	/* argument hdr length (u32) */
+	unsigned int		p_replen;	/* reply hdr length (u32) */
 	unsigned int		p_count;	/* call count */
 	unsigned int		p_timer;	/* Which RTT timer to use */
 	u32			p_statidx;	/* Which procedure to account */
@@ -121,8 +122,8 @@
 int		rpc_shutdown_client(struct rpc_clnt *);
 int		rpc_destroy_client(struct rpc_clnt *);
 void		rpc_release_client(struct rpc_clnt *);
-void		rpc_getport(struct rpc_task *);
-int		rpc_register(u32, u32, int, unsigned short, int *);
+int		rpcb_register(u32, u32, int, unsigned short, int *);
+void		rpcb_getport(struct rpc_task *);
 
 void		rpc_call_setup(struct rpc_task *, struct rpc_message *, int);
 
@@ -144,7 +145,7 @@
 /*
  * Helper function for NFSroot support
  */
-int		rpc_getport_external(struct sockaddr_in *, __u32, __u32, int);
+int		rpcb_getport_external(struct sockaddr_in *, __u32, __u32, int);
 
 #endif /* __KERNEL__ */
 #endif /* _LINUX_SUNRPC_CLNT_H */
diff --git a/include/linux/sunrpc/debug.h b/include/linux/sunrpc/debug.h
index b7c7307..3912cf1 100644
--- a/include/linux/sunrpc/debug.h
+++ b/include/linux/sunrpc/debug.h
@@ -17,7 +17,7 @@
 #define RPCDBG_DEBUG		0x0004
 #define RPCDBG_NFS		0x0008
 #define RPCDBG_AUTH		0x0010
-#define RPCDBG_PMAP		0x0020
+#define RPCDBG_BIND		0x0020
 #define RPCDBG_SCHED		0x0040
 #define RPCDBG_TRANS		0x0080
 #define RPCDBG_SVCSOCK		0x0100
diff --git a/include/linux/sunrpc/msg_prot.h b/include/linux/sunrpc/msg_prot.h
index 606cb21..784d4c3 100644
--- a/include/linux/sunrpc/msg_prot.h
+++ b/include/linux/sunrpc/msg_prot.h
@@ -78,10 +78,6 @@
 	RPCSEC_GSS_CTXPROBLEM = 14
 };
 
-#define RPC_PMAP_PROGRAM	100000
-#define RPC_PMAP_VERSION	2
-#define RPC_PMAP_PORT		111
-
 #define RPC_MAXNETNAMELEN	256
 
 /*
diff --git a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h
index 3069ecc..2047fb2 100644
--- a/include/linux/sunrpc/sched.h
+++ b/include/linux/sunrpc/sched.h
@@ -264,7 +264,7 @@
 void		rpc_wake_up_status(struct rpc_wait_queue *, int);
 void		rpc_delay(struct rpc_task *, unsigned long);
 void *		rpc_malloc(struct rpc_task *, size_t);
-void		rpc_free(struct rpc_task *);
+void		rpc_free(void *);
 int		rpciod_up(void);
 void		rpciod_down(void);
 int		__rpc_wait_for_completion_task(struct rpc_task *task, int (*)(void *));
diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
index f780e72..fa89ce6 100644
--- a/include/linux/sunrpc/xprt.h
+++ b/include/linux/sunrpc/xprt.h
@@ -84,7 +84,9 @@
 	struct list_head	rq_list;
 
 	__u32 *			rq_buffer;	/* XDR encode buffer */
-	size_t			rq_bufsize;
+	size_t			rq_bufsize,
+				rq_callsize,
+				rq_rcvsize;
 
 	struct xdr_buf		rq_private_buf;		/* The receive buffer
 							 * used in the softirq.
@@ -112,7 +114,7 @@
 	void		(*set_port)(struct rpc_xprt *xprt, unsigned short port);
 	void		(*connect)(struct rpc_task *task);
 	void *		(*buf_alloc)(struct rpc_task *task, size_t size);
-	void		(*buf_free)(struct rpc_task *task);
+	void		(*buf_free)(void *buffer);
 	int		(*send_request)(struct rpc_task *task);
 	void		(*set_retrans_timeout)(struct rpc_task *task);
 	void		(*timer)(struct rpc_task *task);
@@ -150,6 +152,7 @@
 	unsigned long		state;		/* transport state */
 	unsigned char		shutdown   : 1,	/* being shut down */
 				resvport   : 1; /* use a reserved port */
+	unsigned int		bind_index;	/* bind function index */
 
 	/*
 	 * Connection of transports
diff --git a/include/linux/tifm.h b/include/linux/tifm.h
index 3deb0a6..2a19698 100644
--- a/include/linux/tifm.h
+++ b/include/linux/tifm.h
@@ -14,16 +14,16 @@
 
 #include <linux/spinlock.h>
 #include <linux/interrupt.h>
-#include <linux/wait.h>
 #include <linux/delay.h>
 #include <linux/pci.h>
-#include <linux/kthread.h>
+#include <linux/workqueue.h>
 
 /* Host registers (relative to pci base address): */
 enum {
 	FM_SET_INTERRUPT_ENABLE   = 0x008,
 	FM_CLEAR_INTERRUPT_ENABLE = 0x00c,
-	FM_INTERRUPT_STATUS       = 0x014 };
+	FM_INTERRUPT_STATUS       = 0x014
+};
 
 /* Socket registers (relative to socket base address): */
 enum {
@@ -58,14 +58,8 @@
 	SOCK_MS_DATA                   = 0x188,
 	SOCK_MS_STATUS                 = 0x18c,
 	SOCK_MS_SYSTEM                 = 0x190,
-	SOCK_FIFO_ACCESS               = 0x200 };
-
-
-#define TIFM_IRQ_ENABLE           0x80000000
-#define TIFM_IRQ_SOCKMASK(x)      (x)
-#define TIFM_IRQ_CARDMASK(x)      ((x) << 8)
-#define TIFM_IRQ_FIFOMASK(x)      ((x) << 16)
-#define TIFM_IRQ_SETALL           0xffffffff
+	SOCK_FIFO_ACCESS               = 0x200
+};
 
 #define TIFM_CTRL_LED             0x00000040
 #define TIFM_CTRL_FAST_CLK        0x00000100
@@ -73,63 +67,76 @@
 #define TIFM_SOCK_STATE_OCCUPIED  0x00000008
 #define TIFM_SOCK_STATE_POWERED   0x00000080
 
-#define TIFM_FIFO_ENABLE          0x00000001 /* Meaning of this constant is unverified */
+#define TIFM_FIFO_ENABLE          0x00000001
+#define TIFM_FIFO_READY           0x00000001
 #define TIFM_FIFO_INT_SETALL      0x0000ffff
-#define TIFM_FIFO_INTMASK         0x00000005 /* Meaning of this constant is unverified */
+#define TIFM_FIFO_INTMASK         0x00000005
 
-#define TIFM_DMA_RESET            0x00000002 /* Meaning of this constant is unverified */
-#define TIFM_DMA_TX               0x00008000 /* Meaning of this constant is unverified */
-#define TIFM_DMA_EN               0x00000001 /* Meaning of this constant is unverified */
+#define TIFM_DMA_RESET            0x00000002
+#define TIFM_DMA_TX               0x00008000
+#define TIFM_DMA_EN               0x00000001
+#define TIFM_DMA_TSIZE            0x0000007f
 
-typedef enum {FM_NULL = 0, FM_XD = 0x01, FM_MS = 0x02, FM_SD = 0x03} tifm_media_id;
+#define TIFM_TYPE_XD 1
+#define TIFM_TYPE_MS 2
+#define TIFM_TYPE_SD 3
+
+struct tifm_device_id {
+	unsigned char type;
+};
 
 struct tifm_driver;
 struct tifm_dev {
-	char __iomem            *addr;
-	spinlock_t              lock;
-	tifm_media_id           media_id;
-	unsigned int            socket_id;
+	char __iomem  *addr;
+	spinlock_t    lock;
+	unsigned char type;
+	unsigned int  socket_id;
 
-	void                    (*signal_irq)(struct tifm_dev *sock,
-					      unsigned int sock_irq_status);
+	void          (*card_event)(struct tifm_dev *sock);
+	void          (*data_event)(struct tifm_dev *sock);
 
-	struct tifm_driver      *drv;
-	struct device           dev;
+	struct device dev;
 };
 
 struct tifm_driver {
-	tifm_media_id        *id_table;
-	int                  (*probe)(struct tifm_dev *dev);
-	void                 (*remove)(struct tifm_dev *dev);
-	int                  (*suspend)(struct tifm_dev *dev,
-                                        pm_message_t state);
-	int                  (*resume)(struct tifm_dev *dev);
+	struct tifm_device_id *id_table;
+	int                   (*probe)(struct tifm_dev *dev);
+	void                  (*remove)(struct tifm_dev *dev);
+	int                   (*suspend)(struct tifm_dev *dev,
+					 pm_message_t state);
+	int                   (*resume)(struct tifm_dev *dev);
 
-	struct device_driver driver;
+	struct device_driver  driver;
 };
 
 struct tifm_adapter {
-	char __iomem            *addr;
-	spinlock_t              lock;
-	unsigned int            irq_status;
-	unsigned int            socket_change_set;
-	wait_queue_head_t       change_set_notify;
-	unsigned int            id;
-	unsigned int            num_sockets;
-	struct tifm_dev         **sockets;
-	struct task_struct      *media_switcher;
-	struct class_device     cdev;
-	struct device           *dev;
+	char __iomem        *addr;
+	spinlock_t          lock;
+	unsigned int        irq_status;
+	unsigned int        socket_change_set;
+	unsigned int        id;
+	unsigned int        num_sockets;
+	struct completion   *finish_me;
 
-	void                    (*eject)(struct tifm_adapter *fm, struct tifm_dev *sock);
+	struct work_struct  media_switcher;
+	struct class_device cdev;
+
+	void                (*eject)(struct tifm_adapter *fm,
+				     struct tifm_dev *sock);
+
+	struct tifm_dev     *sockets[0];
 };
 
-struct tifm_adapter *tifm_alloc_adapter(void);
-void tifm_free_device(struct device *dev);
-void tifm_free_adapter(struct tifm_adapter *fm);
-int tifm_add_adapter(struct tifm_adapter *fm, int (*mediathreadfn)(void *data));
+struct tifm_adapter *tifm_alloc_adapter(unsigned int num_sockets,
+					struct device *dev);
+int tifm_add_adapter(struct tifm_adapter *fm);
 void tifm_remove_adapter(struct tifm_adapter *fm);
-struct tifm_dev *tifm_alloc_device(struct tifm_adapter *fm);
+void tifm_free_adapter(struct tifm_adapter *fm);
+
+void tifm_free_device(struct device *dev);
+struct tifm_dev *tifm_alloc_device(struct tifm_adapter *fm, unsigned int id,
+				   unsigned char type);
+
 int tifm_register_driver(struct tifm_driver *drv);
 void tifm_unregister_driver(struct tifm_driver *drv);
 void tifm_eject(struct tifm_dev *sock);
@@ -137,11 +144,11 @@
 		int direction);
 void tifm_unmap_sg(struct tifm_dev *sock, struct scatterlist *sg, int nents,
 		   int direction);
-
+void tifm_queue_work(struct work_struct *work);
 
 static inline void *tifm_get_drvdata(struct tifm_dev *dev)
 {
-        return dev_get_drvdata(&dev->dev);
+	return dev_get_drvdata(&dev->dev);
 }
 
 static inline void tifm_set_drvdata(struct tifm_dev *dev, void *data)
@@ -149,8 +156,4 @@
 	dev_set_drvdata(&dev->dev, data);
 }
 
-struct tifm_device_id {
-	tifm_media_id media_id;
-};
-
 #endif
diff --git a/include/linux/writeback.h b/include/linux/writeback.h
index 0c78f7f..daa6c12 100644
--- a/include/linux/writeback.h
+++ b/include/linux/writeback.h
@@ -59,6 +59,8 @@
 	unsigned for_reclaim:1;		/* Invoked from the page allocator */
 	unsigned for_writepages:1;	/* This is a writepages() call */
 	unsigned range_cyclic:1;	/* range_start is cyclic */
+
+	void *fs_private;		/* For use by ->writepages() */
 };
 
 /*
diff --git a/include/linux/xfrm.h b/include/linux/xfrm.h
index a5d53e0..b58adc5 100644
--- a/include/linux/xfrm.h
+++ b/include/linux/xfrm.h
@@ -243,17 +243,6 @@
 #define XFRM_AE_MAX (__XFRM_AE_MAX - 1)
 };
 
-/* SAD Table filter flags  */
-enum xfrm_sad_ftype_t {
-	XFRM_SAD_UNSPEC,
-	XFRM_SAD_HMASK=1,
-	XFRM_SAD_HMAX=2,
-	XFRM_SAD_CNT=4,
-	__XFRM_SAD_MAX
-
-#define XFRM_SAD_MAX (__XFRM_SAD_MAX - 1)
-};
-
 struct xfrm_userpolicy_type {
 	__u8		type;
 	__u16		reserved1;
@@ -287,44 +276,41 @@
 
 enum xfrm_sadattr_type_t {
 	XFRMA_SAD_UNSPEC,
-	XFRMA_SADHMASK,
-	XFRMA_SADHMAX,
-	XFRMA_SADCNT,
+	XFRMA_SAD_CNT,
+	XFRMA_SAD_HINFO,
 	__XFRMA_SAD_MAX
 
 #define XFRMA_SAD_MAX (__XFRMA_SAD_MAX - 1)
 };
 
-/* SPD Table filter flags  */
-enum xfrm_spd_ftype_t {
-	XFRM_SPD_UNSPEC,
-	XFRM_SPD_HMASK=1,
-	XFRM_SPD_HMAX=2,
-	XFRM_SPD_ICNT=4,
-	XFRM_SPD_OCNT=8,
-	XFRM_SPD_FCNT=16,
-	XFRM_SPD_ISCNT=32,
-	XFRM_SPD_OSCNT=64,
-	XFRM_SPD_FSCNT=128,
-	__XFRM_SPD_MAX
-
-#define XFRM_SPD_MAX (__XFRM_SPD_MAX - 1)
+struct xfrmu_sadhinfo {
+	__u32 sadhcnt; /* current hash bkts */
+	__u32 sadhmcnt; /* max allowed hash bkts */
 };
+
 enum xfrm_spdattr_type_t {
 	XFRMA_SPD_UNSPEC,
-	XFRMA_SPDHMASK,
-	XFRMA_SPDHMAX,
-	XFRMA_SPDICNT,
-	XFRMA_SPDOCNT,
-	XFRMA_SPDFCNT,
-	XFRMA_SPDISCNT,
-	XFRMA_SPDOSCNT,
-	XFRMA_SPDFSCNT,
+	XFRMA_SPD_INFO,
+	XFRMA_SPD_HINFO,
 	__XFRMA_SPD_MAX
 
 #define XFRMA_SPD_MAX (__XFRMA_SPD_MAX - 1)
 };
 
+struct xfrmu_spdinfo {
+	__u32 incnt;
+	__u32 outcnt;
+	__u32 fwdcnt;
+	__u32 inscnt;
+	__u32 outscnt;
+	__u32 fwdscnt;
+};
+
+struct xfrmu_spdhinfo {
+	__u32 spdhcnt;
+	__u32 spdhmcnt;
+};
+
 struct xfrm_usersa_info {
 	struct xfrm_selector		sel;
 	struct xfrm_id			id;
diff --git a/include/media/ovcamchip.h b/include/media/ovcamchip.h
index 0f43451..05b9569 100644
--- a/include/media/ovcamchip.h
+++ b/include/media/ovcamchip.h
@@ -16,7 +16,6 @@
 
 #include <linux/videodev.h>
 #include <media/v4l2-common.h>
-#include <linux/i2c.h>
 
 /* --------------------------------- */
 /*           ENUMERATIONS            */
diff --git a/include/media/tuner.h b/include/media/tuner.h
index a41ac411..6dcf3c4 100644
--- a/include/media/tuner.h
+++ b/include/media/tuner.h
@@ -23,6 +23,7 @@
 #define _TUNER_H
 
 #include <linux/videodev2.h>
+#include <linux/i2c.h>
 #include <media/tuner-types.h>
 
 extern int tuner_debug;
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index f70afef..4fa5dfe 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -204,9 +204,9 @@
 {
 	struct ip6_flowlabel	*next;
 	__be32			label;
+	atomic_t		users;
 	struct in6_addr		dst;
 	struct ipv6_txoptions	*opt;
-	atomic_t		users;
 	unsigned long		linger;
 	u8			share;
 	u32			owner;
@@ -291,7 +291,7 @@
 
 static inline int ipv6_addr_cmp(const struct in6_addr *a1, const struct in6_addr *a2)
 {
-	return memcmp((const void *) a1, (const void *) a2, sizeof(struct in6_addr));
+	return memcmp(a1, a2, sizeof(struct in6_addr));
 }
 
 static inline int
@@ -308,7 +308,7 @@
 
 static inline void ipv6_addr_copy(struct in6_addr *a1, const struct in6_addr *a2)
 {
-	memcpy((void *) a1, (const void *) a2, sizeof(struct in6_addr));
+	memcpy(a1, a2, sizeof(struct in6_addr));
 }
 
 static inline void ipv6_addr_prefix(struct in6_addr *pfx, 
@@ -319,16 +319,12 @@
 	int o = plen >> 3,
 	    b = plen & 0x7;
 
+	memset(pfx->s6_addr, 0, sizeof(pfx->s6_addr));
 	memcpy(pfx->s6_addr, addr, o);
-	if (b != 0) {
+	if (b != 0)
 		pfx->s6_addr[o] = addr->s6_addr[o] & (0xff00 >> b);
-		o++;
-	}
-	if (o < 16)
-		memset(pfx->s6_addr + o, 0, 16 - o);
 }
 
-#ifndef __HAVE_ARCH_ADDR_SET
 static inline void ipv6_addr_set(struct in6_addr *addr, 
 				     __be32 w1, __be32 w2,
 				     __be32 w3, __be32 w4)
@@ -338,7 +334,6 @@
 	addr->s6_addr32[2] = w3;
 	addr->s6_addr32[3] = w4;
 }
-#endif
 
 static inline int ipv6_addr_equal(const struct in6_addr *a1,
 				  const struct in6_addr *a2)
diff --git a/include/net/iucv/af_iucv.h b/include/net/iucv/af_iucv.h
index 04d1abb..f9bd11b 100644
--- a/include/net/iucv/af_iucv.h
+++ b/include/net/iucv/af_iucv.h
@@ -28,6 +28,7 @@
 	IUCV_LISTEN,
 	IUCV_SEVERED,
 	IUCV_DISCONN,
+	IUCV_CLOSING,
 	IUCV_CLOSED
 };
 
@@ -62,6 +63,7 @@
 	struct sock		*parent;
 	struct iucv_path	*path;
 	struct sk_buff_head	send_skb_q;
+	struct sk_buff_head	backlog_skb_q;
 	unsigned int		send_tag;
 };
 
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
new file mode 100644
index 0000000..a7f122b
--- /dev/null
+++ b/include/net/mac80211.h
@@ -0,0 +1,1045 @@
+/*
+ * Low-level hardware driver -- IEEE 802.11 driver (80211.o) interface
+ * Copyright 2002-2005, Devicescape Software, Inc.
+ * Copyright 2006-2007	Jiri Benc <jbenc@suse.cz>
+ *
+ * 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 MAC80211_H
+#define MAC80211_H
+
+#include <linux/kernel.h>
+#include <linux/if_ether.h>
+#include <linux/skbuff.h>
+#include <linux/wireless.h>
+#include <linux/device.h>
+#include <linux/ieee80211.h>
+#include <net/wireless.h>
+#include <net/cfg80211.h>
+
+/* Note! Only ieee80211_tx_status_irqsafe() and ieee80211_rx_irqsafe() can be
+ * called in hardware interrupt context. The low-level driver must not call any
+ * other functions in hardware interrupt context. If there is a need for such
+ * call, the low-level driver should first ACK the interrupt and perform the
+ * IEEE 802.11 code call after this, e.g., from a scheduled tasklet (in
+ * software interrupt context).
+ */
+
+/*
+ * Frame format used when passing frame between low-level hardware drivers
+ * and IEEE 802.11 driver the same as used in the wireless media, i.e.,
+ * buffers start with IEEE 802.11 header and include the same octets that
+ * are sent over air.
+ *
+ * If hardware uses IEEE 802.3 headers (and perform 802.3 <-> 802.11
+ * conversion in firmware), upper layer 802.11 code needs to be changed to
+ * support this.
+ *
+ * If the receive frame format is not the same as the real frame sent
+ * on the wireless media (e.g., due to padding etc.), upper layer 802.11 code
+ * could be updated to provide support for such format assuming this would
+ * optimize the performance, e.g., by removing need to re-allocation and
+ * copying of the data.
+ */
+
+#define IEEE80211_CHAN_W_SCAN 0x00000001
+#define IEEE80211_CHAN_W_ACTIVE_SCAN 0x00000002
+#define IEEE80211_CHAN_W_IBSS 0x00000004
+
+/* Channel information structure. Low-level driver is expected to fill in chan,
+ * freq, and val fields. Other fields will be filled in by 80211.o based on
+ * hostapd information and low-level driver does not need to use them. The
+ * limits for each channel will be provided in 'struct ieee80211_conf' when
+ * configuring the low-level driver with hw->config callback. If a device has
+ * a default regulatory domain, IEEE80211_HW_DEFAULT_REG_DOMAIN_CONFIGURED
+ * can be set to let the driver configure all fields */
+struct ieee80211_channel {
+	short chan; /* channel number (IEEE 802.11) */
+	short freq; /* frequency in MHz */
+	int val; /* hw specific value for the channel */
+	int flag; /* flag for hostapd use (IEEE80211_CHAN_*) */
+	unsigned char power_level;
+	unsigned char antenna_max;
+};
+
+#define IEEE80211_RATE_ERP 0x00000001
+#define IEEE80211_RATE_BASIC 0x00000002
+#define IEEE80211_RATE_PREAMBLE2 0x00000004
+#define IEEE80211_RATE_SUPPORTED 0x00000010
+#define IEEE80211_RATE_OFDM 0x00000020
+#define IEEE80211_RATE_CCK 0x00000040
+#define IEEE80211_RATE_TURBO 0x00000080
+#define IEEE80211_RATE_MANDATORY 0x00000100
+
+#define IEEE80211_RATE_CCK_2 (IEEE80211_RATE_CCK | IEEE80211_RATE_PREAMBLE2)
+#define IEEE80211_RATE_MODULATION(f) \
+	(f & (IEEE80211_RATE_CCK | IEEE80211_RATE_OFDM))
+
+/* Low-level driver should set PREAMBLE2, OFDM, CCK, and TURBO flags.
+ * BASIC, SUPPORTED, ERP, and MANDATORY flags are set in 80211.o based on the
+ * configuration. */
+struct ieee80211_rate {
+	int rate; /* rate in 100 kbps */
+	int val; /* hw specific value for the rate */
+	int flags; /* IEEE80211_RATE_ flags */
+	int val2; /* hw specific value for the rate when using short preamble
+		   * (only when IEEE80211_RATE_PREAMBLE2 flag is set, i.e., for
+		   * 2, 5.5, and 11 Mbps) */
+	signed char min_rssi_ack;
+	unsigned char min_rssi_ack_delta;
+
+	/* following fields are set by 80211.o and need not be filled by the
+	 * low-level driver */
+	int rate_inv; /* inverse of the rate (LCM(all rates) / rate) for
+		       * optimizing channel utilization estimates */
+};
+
+/* 802.11g is backwards-compatible with 802.11b, so a wlan card can
+ * actually be both in 11b and 11g modes at the same time. */
+enum {
+	MODE_IEEE80211A, /* IEEE 802.11a */
+	MODE_IEEE80211B, /* IEEE 802.11b only */
+	MODE_ATHEROS_TURBO, /* Atheros Turbo mode (2x.11a at 5 GHz) */
+	MODE_IEEE80211G, /* IEEE 802.11g (and 802.11b compatibility) */
+	MODE_ATHEROS_TURBOG, /* Atheros Turbo mode (2x.11g at 2.4 GHz) */
+
+	/* keep last */
+	NUM_IEEE80211_MODES
+};
+
+struct ieee80211_hw_mode {
+	int mode; /* MODE_IEEE80211... */
+	int num_channels; /* Number of channels (below) */
+	struct ieee80211_channel *channels; /* Array of supported channels */
+	int num_rates; /* Number of rates (below) */
+	struct ieee80211_rate *rates; /* Array of supported rates */
+
+	struct list_head list; /* Internal, don't touch */
+};
+
+struct ieee80211_tx_queue_params {
+	int aifs; /* 0 .. 255; -1 = use default */
+	int cw_min; /* 2^n-1: 1, 3, 7, .. , 1023; 0 = use default */
+	int cw_max; /* 2^n-1: 1, 3, 7, .. , 1023; 0 = use default */
+	int burst_time; /* maximum burst time in 0.1 ms (i.e., 10 = 1 ms);
+			 * 0 = disabled */
+};
+
+struct ieee80211_tx_queue_stats_data {
+	unsigned int len; /* num packets in queue */
+	unsigned int limit; /* queue len (soft) limit */
+	unsigned int count; /* total num frames sent */
+};
+
+enum {
+	IEEE80211_TX_QUEUE_DATA0,
+	IEEE80211_TX_QUEUE_DATA1,
+	IEEE80211_TX_QUEUE_DATA2,
+	IEEE80211_TX_QUEUE_DATA3,
+	IEEE80211_TX_QUEUE_DATA4,
+	IEEE80211_TX_QUEUE_SVP,
+
+	NUM_TX_DATA_QUEUES,
+
+/* due to stupidity in the sub-ioctl userspace interface, the items in
+ * this struct need to have fixed values. As soon as it is removed, we can
+ * fix these entries. */
+	IEEE80211_TX_QUEUE_AFTER_BEACON = 6,
+	IEEE80211_TX_QUEUE_BEACON = 7
+};
+
+struct ieee80211_tx_queue_stats {
+	struct ieee80211_tx_queue_stats_data data[NUM_TX_DATA_QUEUES];
+};
+
+struct ieee80211_low_level_stats {
+	unsigned int dot11ACKFailureCount;
+	unsigned int dot11RTSFailureCount;
+	unsigned int dot11FCSErrorCount;
+	unsigned int dot11RTSSuccessCount;
+};
+
+/* Transmit control fields. This data structure is passed to low-level driver
+ * with each TX frame. The low-level driver is responsible for configuring
+ * the hardware to use given values (depending on what is supported). */
+#define HW_KEY_IDX_INVALID -1
+
+struct ieee80211_tx_control {
+	int tx_rate; /* Transmit rate, given as the hw specific value for the
+		      * rate (from struct ieee80211_rate) */
+	int rts_cts_rate; /* Transmit rate for RTS/CTS frame, given as the hw
+			   * specific value for the rate (from
+			   * struct ieee80211_rate) */
+
+#define IEEE80211_TXCTL_REQ_TX_STATUS	(1<<0)/* request TX status callback for
+						* this frame */
+#define IEEE80211_TXCTL_DO_NOT_ENCRYPT	(1<<1) /* send this frame without
+						* encryption; e.g., for EAPOL
+						* frames */
+#define IEEE80211_TXCTL_USE_RTS_CTS	(1<<2) /* use RTS-CTS before sending
+						* frame */
+#define IEEE80211_TXCTL_USE_CTS_PROTECT	(1<<3) /* use CTS protection for the
+						* frame (e.g., for combined
+						* 802.11g / 802.11b networks) */
+#define IEEE80211_TXCTL_NO_ACK		(1<<4) /* tell the low level not to
+						* wait for an ack */
+#define IEEE80211_TXCTL_RATE_CTRL_PROBE	(1<<5)
+#define IEEE80211_TXCTL_CLEAR_DST_MASK	(1<<6)
+#define IEEE80211_TXCTL_REQUEUE		(1<<7)
+#define IEEE80211_TXCTL_FIRST_FRAGMENT	(1<<8) /* this is a first fragment of
+						* the frame */
+#define IEEE80211_TXCTL_TKIP_NEW_PHASE1_KEY (1<<9)
+	u32 flags;			       /* tx control flags defined
+						* above */
+	u8 retry_limit;		/* 1 = only first attempt, 2 = one retry, .. */
+	u8 power_level;		/* per-packet transmit power level, in dBm */
+	u8 antenna_sel_tx; 	/* 0 = default/diversity, 1 = Ant0, 2 = Ant1 */
+	s8 key_idx;		/* -1 = do not encrypt, >= 0 keyidx from
+				 * hw->set_key() */
+	u8 icv_len;		/* length of the ICV/MIC field in octets */
+	u8 iv_len;		/* length of the IV field in octets */
+	u8 tkip_key[16];	/* generated phase2/phase1 key for hw TKIP */
+	u8 queue;		/* hardware queue to use for this frame;
+				 * 0 = highest, hw->queues-1 = lowest */
+	u8 sw_retry_attempt;	/* number of times hw has tried to
+				 * transmit frame (not incl. hw retries) */
+
+	struct ieee80211_rate *rate;		/* internal 80211.o rate */
+	struct ieee80211_rate *rts_rate;	/* internal 80211.o rate
+						 * for RTS/CTS */
+	int alt_retry_rate; /* retry rate for the last retries, given as the
+			     * hw specific value for the rate (from
+			     * struct ieee80211_rate). To be used to limit
+			     * packet dropping when probing higher rates, if hw
+			     * supports multiple retry rates. -1 = not used */
+	int type;	/* internal */
+	int ifindex;	/* internal */
+};
+
+/* Receive status. The low-level driver should provide this information
+ * (the subset supported by hardware) to the 802.11 code with each received
+ * frame. */
+struct ieee80211_rx_status {
+	u64 mactime;
+	int freq; /* receive frequency in Mhz */
+	int channel;
+	int phymode;
+	int ssi;
+	int signal; /* used as qual in statistics reporting */
+	int noise;
+	int antenna;
+	int rate;
+#define RX_FLAG_MMIC_ERROR	(1<<0)
+#define RX_FLAG_DECRYPTED	(1<<1)
+#define RX_FLAG_RADIOTAP	(1<<2)
+	int flag;
+};
+
+/* Transmit status. The low-level driver should provide this information
+ * (the subset supported by hardware) to the 802.11 code for each transmit
+ * frame. */
+struct ieee80211_tx_status {
+	/* copied ieee80211_tx_control structure */
+	struct ieee80211_tx_control control;
+
+#define IEEE80211_TX_STATUS_TX_FILTERED	(1<<0)
+#define IEEE80211_TX_STATUS_ACK		(1<<1) /* whether the TX frame was ACKed */
+	u32 flags;		/* tx staus flags defined above */
+
+	int ack_signal; /* measured signal strength of the ACK frame */
+	int excessive_retries;
+	int retry_count;
+
+	int queue_length;      /* information about TX queue */
+	int queue_number;
+};
+
+
+/**
+ * struct ieee80211_conf - configuration of the device
+ *
+ * This struct indicates how the driver shall configure the hardware.
+ *
+ * @radio_enabled: when zero, driver is required to switch off the radio.
+ */
+struct ieee80211_conf {
+	int channel;			/* IEEE 802.11 channel number */
+	int freq;			/* MHz */
+	int channel_val;		/* hw specific value for the channel */
+
+	int phymode;			/* MODE_IEEE80211A, .. */
+	struct ieee80211_channel *chan;
+	struct ieee80211_hw_mode *mode;
+	unsigned int regulatory_domain;
+	int radio_enabled;
+
+	int beacon_int;
+
+#define IEEE80211_CONF_SHORT_SLOT_TIME	(1<<0) /* use IEEE 802.11g Short Slot
+						* Time */
+#define IEEE80211_CONF_SSID_HIDDEN	(1<<1) /* do not broadcast the ssid */
+#define IEEE80211_CONF_RADIOTAP		(1<<2) /* use radiotap if supported
+						  check this bit at RX time */
+	u32 flags;			/* configuration flags defined above */
+
+	u8 power_level;			/* transmit power limit for current
+					 * regulatory domain; in dBm */
+	u8 antenna_max;			/* maximum antenna gain */
+	short tx_power_reduction; /* in 0.1 dBm */
+
+	/* 0 = default/diversity, 1 = Ant0, 2 = Ant1 */
+	u8 antenna_sel_tx;
+	u8 antenna_sel_rx;
+
+	int antenna_def;
+	int antenna_mode;
+
+	/* Following five fields are used for IEEE 802.11H */
+	unsigned int radar_detect;
+	unsigned int spect_mgmt;
+	/* All following fields are currently unused. */
+	unsigned int quiet_duration; /* duration of quiet period */
+	unsigned int quiet_offset; /* how far into the beacon is the quiet
+				    * period */
+	unsigned int quiet_period;
+	u8 radar_firpwr_threshold;
+	u8 radar_rssi_threshold;
+	u8 pulse_height_threshold;
+	u8 pulse_rssi_threshold;
+	u8 pulse_inband_threshold;
+};
+
+/**
+ * enum ieee80211_if_types - types of 802.11 network interfaces
+ *
+ * @IEEE80211_IF_TYPE_AP: interface in AP mode.
+ * @IEEE80211_IF_TYPE_MGMT: special interface for communication with hostap
+ *	daemon. Drivers should never see this type.
+ * @IEEE80211_IF_TYPE_STA: interface in STA (client) mode.
+ * @IEEE80211_IF_TYPE_IBSS: interface in IBSS (ad-hoc) mode.
+ * @IEEE80211_IF_TYPE_MNTR: interface in monitor (rfmon) mode.
+ * @IEEE80211_IF_TYPE_WDS: interface in WDS mode.
+ * @IEEE80211_IF_TYPE_VLAN: not used.
+ */
+enum ieee80211_if_types {
+	IEEE80211_IF_TYPE_AP = 0x00000000,
+	IEEE80211_IF_TYPE_MGMT = 0x00000001,
+	IEEE80211_IF_TYPE_STA = 0x00000002,
+	IEEE80211_IF_TYPE_IBSS = 0x00000003,
+	IEEE80211_IF_TYPE_MNTR = 0x00000004,
+	IEEE80211_IF_TYPE_WDS = 0x5A580211,
+	IEEE80211_IF_TYPE_VLAN = 0x00080211,
+};
+
+/**
+ * struct ieee80211_if_init_conf - initial configuration of an interface
+ *
+ * @if_id: internal interface ID. This number has no particular meaning to
+ *	drivers and the only allowed usage is to pass it to
+ *	ieee80211_beacon_get() and ieee80211_get_buffered_bc() functions.
+ *	This field is not valid for monitor interfaces
+ *	(interfaces of %IEEE80211_IF_TYPE_MNTR type).
+ * @type: one of &enum ieee80211_if_types constants. Determines the type of
+ *	added/removed interface.
+ * @mac_addr: pointer to MAC address of the interface. This pointer is valid
+ *	until the interface is removed (i.e. it cannot be used after
+ *	remove_interface() callback was called for this interface).
+ *
+ * This structure is used in add_interface() and remove_interface()
+ * callbacks of &struct ieee80211_hw.
+ */
+struct ieee80211_if_init_conf {
+	int if_id;
+	int type;
+	void *mac_addr;
+};
+
+/**
+ * struct ieee80211_if_conf - configuration of an interface
+ *
+ * @type: type of the interface. This is always the same as was specified in
+ *	&struct ieee80211_if_init_conf. The type of an interface never changes
+ *	during the life of the interface; this field is present only for
+ *	convenience.
+ * @bssid: BSSID of the network we are associated to/creating.
+ * @ssid: used (together with @ssid_len) by drivers for hardware that
+ *	generate beacons independently. The pointer is valid only during the
+ *	config_interface() call, so copy the value somewhere if you need
+ *	it.
+ * @ssid_len: length of the @ssid field.
+ * @generic_elem: used (together with @generic_elem_len) by drivers for
+ *	hardware that generate beacons independently. The pointer is valid
+ *	only during the config_interface() call, so copy the value somewhere
+ *	if you need it.
+ * @generic_elem_len: length of the generic element.
+ * @beacon: beacon template. Valid only if @host_gen_beacon_template in
+ *	&struct ieee80211_hw is set. The driver is responsible of freeing
+ *	the sk_buff.
+ * @beacon_control: tx_control for the beacon template, this field is only
+ *	valid when the @beacon field was set.
+ *
+ * This structure is passed to the config_interface() callback of
+ * &struct ieee80211_hw.
+ */
+struct ieee80211_if_conf {
+	int type;
+	u8 *bssid;
+	u8 *ssid;
+	size_t ssid_len;
+	u8 *generic_elem;
+	size_t generic_elem_len;
+	struct sk_buff *beacon;
+	struct ieee80211_tx_control *beacon_control;
+};
+
+typedef enum { ALG_NONE, ALG_WEP, ALG_TKIP, ALG_CCMP, ALG_NULL }
+ieee80211_key_alg;
+
+
+struct ieee80211_key_conf {
+
+	int hw_key_idx;			/* filled + used by low-level driver */
+	ieee80211_key_alg alg;
+	int keylen;
+
+#define IEEE80211_KEY_FORCE_SW_ENCRYPT (1<<0) /* to be cleared by low-level
+						 driver */
+#define IEEE80211_KEY_DEFAULT_TX_KEY   (1<<1) /* This key is the new default TX
+						 key (used only for broadcast
+						 keys). */
+#define IEEE80211_KEY_DEFAULT_WEP_ONLY (1<<2) /* static WEP is the only
+						 configured security policy;
+						 this allows some low-level
+						 drivers to determine when
+						 hwaccel can be used */
+	u32 flags; /* key configuration flags defined above */
+
+	s8 keyidx;			/* WEP key index */
+	u8 key[0];
+};
+
+#define IEEE80211_SEQ_COUNTER_RX	0
+#define IEEE80211_SEQ_COUNTER_TX	1
+
+typedef enum {
+	SET_KEY, DISABLE_KEY, REMOVE_ALL_KEYS,
+} set_key_cmd;
+
+/* This is driver-visible part of the per-hw state the stack keeps. */
+struct ieee80211_hw {
+	/* points to the cfg80211 wiphy for this piece. Note
+	 * that you must fill in the perm_addr and dev fields
+	 * of this structure, use the macros provided below. */
+	struct wiphy *wiphy;
+
+	/* assigned by mac80211, don't write */
+	struct ieee80211_conf conf;
+
+	/* Single thread workqueue available for driver use
+	 * Allocated by mac80211 on registration */
+	struct workqueue_struct *workqueue;
+
+	/* Pointer to the private area that was
+	 * allocated with this struct for you. */
+	void *priv;
+
+	/* The rest is information about your hardware */
+
+	/* TODO: frame_type 802.11/802.3, sw_encryption requirements */
+
+	/* Some wireless LAN chipsets generate beacons in the hardware/firmware
+	 * and others rely on host generated beacons. This option is used to
+	 * configure the upper layer IEEE 802.11 module to generate beacons.
+	 * The low-level driver can use ieee80211_beacon_get() to fetch the
+	 * next beacon frame. */
+#define IEEE80211_HW_HOST_GEN_BEACON (1<<0)
+
+	/* The device needs to be supplied with a beacon template only. */
+#define IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE (1<<1)
+
+	/* Some devices handle decryption internally and do not
+	 * indicate whether the frame was encrypted (unencrypted frames
+	 * will be dropped by the hardware, unless specifically allowed
+	 * through) */
+#define IEEE80211_HW_DEVICE_HIDES_WEP (1<<2)
+
+	/* Whether RX frames passed to ieee80211_rx() include FCS in the end */
+#define IEEE80211_HW_RX_INCLUDES_FCS (1<<3)
+
+	/* Some wireless LAN chipsets buffer broadcast/multicast frames for
+	 * power saving stations in the hardware/firmware and others rely on
+	 * the host system for such buffering. This option is used to
+	 * configure the IEEE 802.11 upper layer to buffer broadcast/multicast
+	 * frames when there are power saving stations so that low-level driver
+	 * can fetch them with ieee80211_get_buffered_bc(). */
+#define IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING (1<<4)
+
+#define IEEE80211_HW_WEP_INCLUDE_IV (1<<5)
+
+	/* will data nullfunc frames get proper TX status callback */
+#define IEEE80211_HW_DATA_NULLFUNC_ACK (1<<6)
+
+	/* Force software encryption for TKIP packets if WMM is enabled. */
+#define IEEE80211_HW_NO_TKIP_WMM_HWACCEL (1<<7)
+
+	/* Some devices handle Michael MIC internally and do not include MIC in
+	 * the received packets passed up. device_strips_mic must be set
+	 * for such devices. The 'encryption' frame control bit is expected to
+	 * be still set in the IEEE 802.11 header with this option unlike with
+	 * the device_hides_wep configuration option.
+	 */
+#define IEEE80211_HW_DEVICE_STRIPS_MIC (1<<8)
+
+	/* Device is capable of performing full monitor mode even during
+	 * normal operation. */
+#define IEEE80211_HW_MONITOR_DURING_OPER (1<<9)
+
+	/* Device does not need BSSID filter set to broadcast in order to
+	 * receive all probe responses while scanning */
+#define IEEE80211_HW_NO_PROBE_FILTERING (1<<10)
+
+	/* Channels are already configured to the default regulatory domain
+	 * specified in the device's EEPROM */
+#define IEEE80211_HW_DEFAULT_REG_DOMAIN_CONFIGURED (1<<11)
+
+	/* calculate Michael MIC for an MSDU when doing hwcrypto */
+#define IEEE80211_HW_TKIP_INCLUDE_MMIC (1<<12)
+	/* Do TKIP phase1 key mixing in stack to support cards only do
+	 * phase2 key mixing when doing hwcrypto */
+#define IEEE80211_HW_TKIP_REQ_PHASE1_KEY (1<<13)
+	/* Do TKIP phase1 and phase2 key mixing in stack and send the generated
+	 * per-packet RC4 key with each TX frame when doing hwcrypto */
+#define IEEE80211_HW_TKIP_REQ_PHASE2_KEY (1<<14)
+
+	u32 flags;			/* hardware flags defined above */
+
+	/* Set to the size of a needed device specific skb headroom for TX skbs. */
+	unsigned int extra_tx_headroom;
+
+	/* This is the time in us to change channels
+	 */
+	int channel_change_time;
+	/* Maximum values for various statistics.
+	 * Leave at 0 to indicate no support. Use negative numbers for dBm. */
+	s8 max_rssi;
+	s8 max_signal;
+	s8 max_noise;
+
+	/* Number of available hardware TX queues for data packets.
+	 * WMM requires at least four queues. */
+	int queues;
+};
+
+static inline void SET_IEEE80211_DEV(struct ieee80211_hw *hw, struct device *dev)
+{
+	set_wiphy_dev(hw->wiphy, dev);
+}
+
+static inline void SET_IEEE80211_PERM_ADDR(struct ieee80211_hw *hw, u8 *addr)
+{
+	memcpy(hw->wiphy->perm_addr, addr, ETH_ALEN);
+}
+
+/* Configuration block used by the low-level driver to tell the 802.11 code
+ * about supported hardware features and to pass function pointers to callback
+ * functions. */
+struct ieee80211_ops {
+	/* Handler that 802.11 module calls for each transmitted frame.
+	 * skb contains the buffer starting from the IEEE 802.11 header.
+	 * The low-level driver should send the frame out based on
+	 * configuration in the TX control data.
+	 * Must be atomic. */
+	int (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb,
+		  struct ieee80211_tx_control *control);
+
+	/* Handler for performing hardware reset. */
+	int (*reset)(struct ieee80211_hw *hw);
+
+	/* Handler that is called when any netdevice attached to the hardware
+	 * device is set UP for the first time. This can be used, e.g., to
+	 * enable interrupts and beacon sending. */
+	int (*open)(struct ieee80211_hw *hw);
+
+	/* Handler that is called when the last netdevice attached to the
+	 * hardware device is set DOWN. This can be used, e.g., to disable
+	 * interrupts and beacon sending. */
+	int (*stop)(struct ieee80211_hw *hw);
+
+	/* Handler for asking a driver if a new interface can be added (or,
+	 * more exactly, set UP). If the handler returns zero, the interface
+	 * is added. Driver should perform any initialization it needs prior
+	 * to returning zero. By returning non-zero addition of the interface
+	 * is inhibited. Unless monitor_during_oper is set, it is guaranteed
+	 * that monitor interfaces and normal interfaces are mutually
+	 * exclusive. The open() handler is called after add_interface()
+	 * if this is the first device added. At least one of the open()
+	 * open() and add_interface() callbacks has to be assigned. If
+	 * add_interface() is NULL, one STA interface is permitted only. */
+	int (*add_interface)(struct ieee80211_hw *hw,
+			     struct ieee80211_if_init_conf *conf);
+
+	/* Notify a driver that an interface is going down. The stop() handler
+	 * is called prior to this if this is a last interface. */
+	void (*remove_interface)(struct ieee80211_hw *hw,
+				 struct ieee80211_if_init_conf *conf);
+
+	/* Handler for configuration requests. IEEE 802.11 code calls this
+	 * function to change hardware configuration, e.g., channel. */
+	int (*config)(struct ieee80211_hw *hw, struct ieee80211_conf *conf);
+
+	/* Handler for configuration requests related to interfaces (e.g.
+	 * BSSID). */
+	int (*config_interface)(struct ieee80211_hw *hw,
+				int if_id, struct ieee80211_if_conf *conf);
+
+	/* ieee80211 drivers do not have access to the &struct net_device
+	 * that is (are) connected with their device. Hence (and because
+	 * we need to combine the multicast lists and flags for multiple
+	 * virtual interfaces), they cannot assign set_multicast_list.
+	 * The parameters here replace dev->flags and dev->mc_count,
+	 * dev->mc_list is replaced by calling ieee80211_get_mc_list_item.
+	 * Must be atomic. */
+	void (*set_multicast_list)(struct ieee80211_hw *hw,
+				   unsigned short flags, int mc_count);
+
+	/* Set TIM bit handler. If the hardware/firmware takes care of beacon
+	 * generation, IEEE 802.11 code uses this function to tell the
+	 * low-level to set (or clear if set==0) TIM bit for the given aid. If
+	 * host system is used to generate beacons, this handler is not used
+	 * and low-level driver should set it to NULL.
+	 * Must be atomic. */
+	int (*set_tim)(struct ieee80211_hw *hw, int aid, int set);
+
+	/* Set encryption key. IEEE 802.11 module calls this function to set
+	 * encryption keys. addr is ff:ff:ff:ff:ff:ff for default keys and
+	 * station hwaddr for individual keys. aid of the station is given
+	 * to help low-level driver in selecting which key->hw_key_idx to use
+	 * for this key. TX control data will use the hw_key_idx selected by
+	 * the low-level driver.
+	 * Must be atomic. */
+	int (*set_key)(struct ieee80211_hw *hw, set_key_cmd cmd,
+		       u8 *addr, struct ieee80211_key_conf *key, int aid);
+
+	/* Set TX key index for default/broadcast keys. This is needed in cases
+	 * where wlan card is doing full WEP/TKIP encapsulation (wep_include_iv
+	 * is not set), in other cases, this function pointer can be set to
+	 * NULL since the IEEE 802. 11 module takes care of selecting the key
+	 * index for each TX frame. */
+	int (*set_key_idx)(struct ieee80211_hw *hw, int idx);
+
+	/* Enable/disable IEEE 802.1X. This item requests wlan card to pass
+	 * unencrypted EAPOL-Key frames even when encryption is configured.
+	 * If the wlan card does not require such a configuration, this
+	 * function pointer can be set to NULL. */
+	int (*set_ieee8021x)(struct ieee80211_hw *hw, int use_ieee8021x);
+
+	/* Set port authorization state (IEEE 802.1X PAE) to be authorized
+	 * (authorized=1) or unauthorized (authorized=0). This function can be
+	 * used if the wlan hardware or low-level driver implements PAE.
+	 * 80211.o module will anyway filter frames based on authorization
+	 * state, so this function pointer can be NULL if low-level driver does
+	 * not require event notification about port state changes.
+	 * Currently unused. */
+	int (*set_port_auth)(struct ieee80211_hw *hw, u8 *addr,
+			     int authorized);
+
+	/* Ask the hardware to service the scan request, no need to start
+	 * the scan state machine in stack. */
+	int (*hw_scan)(struct ieee80211_hw *hw, u8 *ssid, size_t len);
+
+	/* return low-level statistics */
+	int (*get_stats)(struct ieee80211_hw *hw,
+			 struct ieee80211_low_level_stats *stats);
+
+	/* For devices that generate their own beacons and probe response
+	 * or association responses this updates the state of privacy_invoked
+	 * returns 0 for success or an error number */
+	int (*set_privacy_invoked)(struct ieee80211_hw *hw,
+				   int privacy_invoked);
+
+	/* For devices that have internal sequence counters, allow 802.11
+	 * code to access the current value of a counter */
+	int (*get_sequence_counter)(struct ieee80211_hw *hw,
+				    u8* addr, u8 keyidx, u8 txrx,
+				    u32* iv32, u16* iv16);
+
+	/* Configuration of RTS threshold (if device needs it) */
+	int (*set_rts_threshold)(struct ieee80211_hw *hw, u32 value);
+
+	/* Configuration of fragmentation threshold.
+	 * Assign this if the device does fragmentation by itself,
+	 * if this method is assigned then the stack will not do
+	 * fragmentation. */
+	int (*set_frag_threshold)(struct ieee80211_hw *hw, u32 value);
+
+	/* Configuration of retry limits (if device needs it) */
+	int (*set_retry_limit)(struct ieee80211_hw *hw,
+			       u32 short_retry, u32 long_retr);
+
+	/* Number of STAs in STA table notification (NULL = disabled).
+	 * Must be atomic. */
+	void (*sta_table_notification)(struct ieee80211_hw *hw,
+				       int num_sta);
+
+	/* Configure TX queue parameters (EDCF (aifs, cw_min, cw_max),
+	 * bursting) for a hardware TX queue.
+	 * queue = IEEE80211_TX_QUEUE_*.
+	 * Must be atomic. */
+	int (*conf_tx)(struct ieee80211_hw *hw, int queue,
+		       const struct ieee80211_tx_queue_params *params);
+
+	/* Get statistics of the current TX queue status. This is used to get
+	 * number of currently queued packets (queue length), maximum queue
+	 * size (limit), and total number of packets sent using each TX queue
+	 * (count).
+	 * Currently unused. */
+	int (*get_tx_stats)(struct ieee80211_hw *hw,
+			    struct ieee80211_tx_queue_stats *stats);
+
+	/* Get the current TSF timer value from firmware/hardware. Currently,
+	 * this is only used for IBSS mode debugging and, as such, is not a
+	 * required function.
+	 * Must be atomic. */
+	u64 (*get_tsf)(struct ieee80211_hw *hw);
+
+	/* Reset the TSF timer and allow firmware/hardware to synchronize with
+	 * other STAs in the IBSS. This is only used in IBSS mode. This
+	 * function is optional if the firmware/hardware takes full care of
+	 * TSF synchronization. */
+	void (*reset_tsf)(struct ieee80211_hw *hw);
+
+	/* Setup beacon data for IBSS beacons. Unlike access point (Master),
+	 * IBSS uses a fixed beacon frame which is configured using this
+	 * function. This handler is required only for IBSS mode. */
+	int (*beacon_update)(struct ieee80211_hw *hw,
+			     struct sk_buff *skb,
+			     struct ieee80211_tx_control *control);
+
+	/* Determine whether the last IBSS beacon was sent by us. This is
+	 * needed only for IBSS mode and the result of this function is used to
+	 * determine whether to reply to Probe Requests. */
+	int (*tx_last_beacon)(struct ieee80211_hw *hw);
+};
+
+/* Allocate a new hardware device. This must be called once for each
+ * hardware device. The returned pointer must be used to refer to this
+ * device when calling other functions. 802.11 code allocates a private data
+ * area for the low-level driver. The size of this area is given as
+ * priv_data_len.
+ */
+struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
+					const struct ieee80211_ops *ops);
+
+/* Register hardware device to the IEEE 802.11 code and kernel. Low-level
+ * drivers must call this function before using any other IEEE 802.11
+ * function except ieee80211_register_hwmode. */
+int ieee80211_register_hw(struct ieee80211_hw *hw);
+
+/* driver can use this and ieee80211_get_rx_led_name to get the
+ * name of the registered LEDs after ieee80211_register_hw
+ * was called.
+ * This is useful to set the default trigger on the LED class
+ * device that your driver should export for each LED the device
+ * has, that way the default behaviour will be as expected but
+ * the user can still change it/turn off the LED etc.
+ */
+#ifdef CONFIG_MAC80211_LEDS
+extern char *__ieee80211_get_tx_led_name(struct ieee80211_hw *hw);
+extern char *__ieee80211_get_rx_led_name(struct ieee80211_hw *hw);
+#endif
+static inline char *ieee80211_get_tx_led_name(struct ieee80211_hw *hw)
+{
+#ifdef CONFIG_MAC80211_LEDS
+	return __ieee80211_get_tx_led_name(hw);
+#else
+	return NULL;
+#endif
+}
+
+static inline char *ieee80211_get_rx_led_name(struct ieee80211_hw *hw)
+{
+#ifdef CONFIG_MAC80211_LEDS
+	return __ieee80211_get_rx_led_name(hw);
+#else
+	return NULL;
+#endif
+}
+
+/* Register a new hardware PHYMODE capability to the stack. */
+int ieee80211_register_hwmode(struct ieee80211_hw *hw,
+			      struct ieee80211_hw_mode *mode);
+
+/* Unregister a hardware device. This function instructs 802.11 code to free
+ * allocated resources and unregister netdevices from the kernel. */
+void ieee80211_unregister_hw(struct ieee80211_hw *hw);
+
+/* Free everything that was allocated including private data of a driver. */
+void ieee80211_free_hw(struct ieee80211_hw *hw);
+
+/* Receive frame callback function. The low-level driver uses this function to
+ * send received frames to the IEEE 802.11 code. Receive buffer (skb) must
+ * start with IEEE 802.11 header. */
+void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb,
+		    struct ieee80211_rx_status *status);
+void ieee80211_rx_irqsafe(struct ieee80211_hw *hw,
+			  struct sk_buff *skb,
+			  struct ieee80211_rx_status *status);
+
+/* Transmit status callback function. The low-level driver must call this
+ * function to report transmit status for all the TX frames that had
+ * req_tx_status set in the transmit control fields. In addition, this should
+ * be called at least for all unicast frames to provide information for TX rate
+ * control algorithm. In order to maintain all statistics, this function is
+ * recommended to be called after each frame, including multicast/broadcast, is
+ * sent. */
+void ieee80211_tx_status(struct ieee80211_hw *hw,
+			 struct sk_buff *skb,
+			 struct ieee80211_tx_status *status);
+void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw,
+				 struct sk_buff *skb,
+				 struct ieee80211_tx_status *status);
+
+/**
+ * ieee80211_beacon_get - beacon generation function
+ * @hw: pointer obtained from ieee80211_alloc_hw().
+ * @if_id: interface ID from &struct ieee80211_if_init_conf.
+ * @control: will be filled with information needed to send this beacon.
+ *
+ * If the beacon frames are generated by the host system (i.e., not in
+ * hardware/firmware), the low-level driver uses this function to receive
+ * the next beacon frame from the 802.11 code. The low-level is responsible
+ * for calling this function before beacon data is needed (e.g., based on
+ * hardware interrupt). Returned skb is used only once and low-level driver
+ * is responsible of freeing it.
+ */
+struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
+				     int if_id,
+				     struct ieee80211_tx_control *control);
+
+/**
+ * ieee80211_rts_get - RTS frame generation function
+ * @hw: pointer obtained from ieee80211_alloc_hw().
+ * @frame: pointer to the frame that is going to be protected by the RTS.
+ * @frame_len: the frame length (in octets).
+ * @frame_txctl: &struct ieee80211_tx_control of the frame.
+ * @rts: The buffer where to store the RTS frame.
+ *
+ * If the RTS frames are generated by the host system (i.e., not in
+ * hardware/firmware), the low-level driver uses this function to receive
+ * the next RTS frame from the 802.11 code. The low-level is responsible
+ * for calling this function before and RTS frame is needed.
+ */
+void ieee80211_rts_get(struct ieee80211_hw *hw,
+		       const void *frame, size_t frame_len,
+		       const struct ieee80211_tx_control *frame_txctl,
+		       struct ieee80211_rts *rts);
+
+/**
+ * ieee80211_rts_duration - Get the duration field for an RTS frame
+ * @hw: pointer obtained from ieee80211_alloc_hw().
+ * @frame_len: the length of the frame that is going to be protected by the RTS.
+ * @frame_txctl: &struct ieee80211_tx_control of the frame.
+ *
+ * If the RTS is generated in firmware, but the host system must provide
+ * the duration field, the low-level driver uses this function to receive
+ * the duration field value in little-endian byteorder.
+ */
+__le16 ieee80211_rts_duration(struct ieee80211_hw *hw,
+			      size_t frame_len,
+			      const struct ieee80211_tx_control *frame_txctl);
+
+/**
+ * ieee80211_ctstoself_get - CTS-to-self frame generation function
+ * @hw: pointer obtained from ieee80211_alloc_hw().
+ * @frame: pointer to the frame that is going to be protected by the CTS-to-self.
+ * @frame_len: the frame length (in octets).
+ * @frame_txctl: &struct ieee80211_tx_control of the frame.
+ * @cts: The buffer where to store the CTS-to-self frame.
+ *
+ * If the CTS-to-self frames are generated by the host system (i.e., not in
+ * hardware/firmware), the low-level driver uses this function to receive
+ * the next CTS-to-self frame from the 802.11 code. The low-level is responsible
+ * for calling this function before and CTS-to-self frame is needed.
+ */
+void ieee80211_ctstoself_get(struct ieee80211_hw *hw,
+			     const void *frame, size_t frame_len,
+			     const struct ieee80211_tx_control *frame_txctl,
+			     struct ieee80211_cts *cts);
+
+/**
+ * ieee80211_ctstoself_duration - Get the duration field for a CTS-to-self frame
+ * @hw: pointer obtained from ieee80211_alloc_hw().
+ * @frame_len: the length of the frame that is going to be protected by the CTS-to-self.
+ * @frame_txctl: &struct ieee80211_tx_control of the frame.
+ *
+ * If the CTS-to-self is generated in firmware, but the host system must provide
+ * the duration field, the low-level driver uses this function to receive
+ * the duration field value in little-endian byteorder.
+ */
+__le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw,
+				    size_t frame_len,
+				    const struct ieee80211_tx_control *frame_txctl);
+
+/**
+ * ieee80211_generic_frame_duration - Calculate the duration field for a frame
+ * @hw: pointer obtained from ieee80211_alloc_hw().
+ * @frame_len: the length of the frame.
+ * @rate: the rate (in 100kbps) at which the frame is going to be transmitted.
+ *
+ * Calculate the duration field of some generic frame, given its
+ * length and transmission rate (in 100kbps).
+ */
+__le16 ieee80211_generic_frame_duration(struct ieee80211_hw *hw,
+					size_t frame_len,
+					int rate);
+
+/**
+ * ieee80211_get_buffered_bc - accessing buffered broadcast and multicast frames
+ * @hw: pointer as obtained from ieee80211_alloc_hw().
+ * @if_id: interface ID from &struct ieee80211_if_init_conf.
+ * @control: will be filled with information needed to send returned frame.
+ *
+ * Function for accessing buffered broadcast and multicast frames. If
+ * hardware/firmware does not implement buffering of broadcast/multicast
+ * frames when power saving is used, 802.11 code buffers them in the host
+ * memory. The low-level driver uses this function to fetch next buffered
+ * frame. In most cases, this is used when generating beacon frame. This
+ * function returns a pointer to the next buffered skb or NULL if no more
+ * buffered frames are available.
+ *
+ * Note: buffered frames are returned only after DTIM beacon frame was
+ * generated with ieee80211_beacon_get() and the low-level driver must thus
+ * call ieee80211_beacon_get() first. ieee80211_get_buffered_bc() returns
+ * NULL if the previous generated beacon was not DTIM, so the low-level driver
+ * does not need to check for DTIM beacons separately and should be able to
+ * use common code for all beacons.
+ */
+struct sk_buff *
+ieee80211_get_buffered_bc(struct ieee80211_hw *hw, int if_id,
+			  struct ieee80211_tx_control *control);
+
+/* Low level drivers that have their own MLME and MAC indicate
+ * the aid for an associating station with this call */
+int ieee80211_set_aid_for_sta(struct ieee80211_hw *hw,
+			      u8 *peer_address, u16 aid);
+
+
+/* Given an sk_buff with a raw 802.11 header at the data pointer this function
+ * returns the 802.11 header length in bytes (not including encryption
+ * headers). If the data in the sk_buff is too short to contain a valid 802.11
+ * header the function returns 0.
+ */
+int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb);
+
+/* Like ieee80211_get_hdrlen_from_skb() but takes a FC in CPU order. */
+int ieee80211_get_hdrlen(u16 fc);
+
+/**
+ * ieee80211_wake_queue - wake specific queue
+ * @hw: pointer as obtained from ieee80211_alloc_hw().
+ * @queue: queue number (counted from zero).
+ *
+ * Drivers should use this function instead of netif_wake_queue.
+ */
+void ieee80211_wake_queue(struct ieee80211_hw *hw, int queue);
+
+/**
+ * ieee80211_stop_queue - stop specific queue
+ * @hw: pointer as obtained from ieee80211_alloc_hw().
+ * @queue: queue number (counted from zero).
+ *
+ * Drivers should use this function instead of netif_stop_queue.
+ */
+void ieee80211_stop_queue(struct ieee80211_hw *hw, int queue);
+
+/**
+ * ieee80211_start_queues - start all queues
+ * @hw: pointer to as obtained from ieee80211_alloc_hw().
+ *
+ * Drivers should use this function instead of netif_start_queue.
+ */
+void ieee80211_start_queues(struct ieee80211_hw *hw);
+
+/**
+ * ieee80211_stop_queues - stop all queues
+ * @hw: pointer as obtained from ieee80211_alloc_hw().
+ *
+ * Drivers should use this function instead of netif_stop_queue.
+ */
+void ieee80211_stop_queues(struct ieee80211_hw *hw);
+
+/**
+ * ieee80211_wake_queues - wake all queues
+ * @hw: pointer as obtained from ieee80211_alloc_hw().
+ *
+ * Drivers should use this function instead of netif_wake_queue.
+ */
+void ieee80211_wake_queues(struct ieee80211_hw *hw);
+
+/**
+ * ieee80211_get_mc_list_item - iteration over items in multicast list
+ * @hw: pointer as obtained from ieee80211_alloc_hw().
+ * @prev: value returned by previous call to ieee80211_get_mc_list_item() or
+ *	NULL to start a new iteration.
+ * @ptr: pointer to buffer of void * type for internal usage of
+ *	ieee80211_get_mc_list_item().
+ *
+ * Iterates over items in multicast list of given device. To get the first
+ * item, pass NULL in @prev and in *@ptr. In subsequent calls, pass the
+ * value returned by previous call in @prev. Don't alter *@ptr during
+ * iteration. When there are no more items, NULL is returned.
+ */
+struct dev_mc_list *
+ieee80211_get_mc_list_item(struct ieee80211_hw *hw,
+			   struct dev_mc_list *prev,
+			   void **ptr);
+
+/* called by driver to notify scan status completed */
+void ieee80211_scan_completed(struct ieee80211_hw *hw);
+
+/* Function to indicate Radar Detection. The low level driver must call this
+ * function to indicate the presence of radar in the current channel.
+ * Additionally the radar type also could be sent */
+int  ieee80211_radar_status(struct ieee80211_hw *hw, int channel,
+			    int radar, int radar_type);
+
+/* return a pointer to the source address (SA) */
+static inline u8 *ieee80211_get_SA(struct ieee80211_hdr *hdr)
+{
+	u8 *raw = (u8 *) hdr;
+	u8 tofrom = (*(raw+1)) & 3; /* get the TODS and FROMDS bits */
+
+	switch (tofrom) {
+		case 2:
+			return hdr->addr3;
+		case 3:
+			return hdr->addr4;
+	}
+	return hdr->addr2;
+}
+
+/* return a pointer to the destination address (DA) */
+static inline u8 *ieee80211_get_DA(struct ieee80211_hdr *hdr)
+{
+	u8 *raw = (u8 *) hdr;
+	u8 to_ds = (*(raw+1)) & 1; /* get the TODS bit */
+
+	if (to_ds)
+		return hdr->addr3;
+	return hdr->addr1;
+}
+
+static inline int ieee80211_get_morefrag(struct ieee80211_hdr *hdr)
+{
+	return (le16_to_cpu(hdr->frame_control) &
+		IEEE80211_FCTL_MOREFRAGS) != 0;
+}
+
+#define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x"
+#define MAC_ARG(x) ((u8*)(x))[0], ((u8*)(x))[1], ((u8*)(x))[2], \
+		   ((u8*)(x))[3], ((u8*)(x))[4], ((u8*)(x))[5]
+
+#endif /* MAC80211_H */
diff --git a/include/net/sctp/command.h b/include/net/sctp/command.h
index 6114c4f..f56c8d6 100644
--- a/include/net/sctp/command.h
+++ b/include/net/sctp/command.h
@@ -100,6 +100,8 @@
 	SCTP_CMD_T3_RTX_TIMERS_STOP, /* Stops T3-rtx pending timers */
 	SCTP_CMD_FORCE_PRIM_RETRAN,  /* Forces retrans. over primary path. */
 	SCTP_CMD_SET_SK_ERR,	 /* Set sk_err */
+	SCTP_CMD_ASSOC_CHANGE,	 /* generate and send assoc_change event */
+	SCTP_CMD_ADAPTATION_IND, /* generate and send adaptation event */
 	SCTP_CMD_LAST
 } sctp_verb_t;
 
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
index 28af680..dda72bf 100644
--- a/include/net/sctp/sctp.h
+++ b/include/net/sctp/sctp.h
@@ -378,11 +378,15 @@
 
 int sctp_v6_init(void);
 void sctp_v6_exit(void);
+int sctp_v6_add_protocol(void);
+void sctp_v6_del_protocol(void);
 
 #else /* #ifdef defined(CONFIG_IPV6) */
 
 static inline int sctp_v6_init(void) { return 0; }
 static inline void sctp_v6_exit(void) { return; }
+static inline int sctp_v6_add_protocol(void) { return 0; }
+static inline void sctp_v6_del_protocol(void) { return; }
 
 #endif /* #if defined(CONFIG_IPV6) */
 
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 7b4fff9..5e81984 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -1857,6 +1857,7 @@
 int sctp_assoc_set_bind_addr_from_cookie(struct sctp_association *,
 					 struct sctp_cookie*,
 					 gfp_t gfp);
+int sctp_assoc_set_id(struct sctp_association *, gfp_t);
 
 int sctp_cmp_addr_exact(const union sctp_addr *ss1,
 			const union sctp_addr *ss2);
diff --git a/include/net/tcp.h b/include/net/tcp.h
index ef8f9d4..e22b4f0 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -736,7 +736,8 @@
 
 static inline void tcp_sync_left_out(struct tcp_sock *tp)
 {
-	BUG_ON(tp->sacked_out + tp->lost_out > tp->packets_out);
+	BUG_ON(tp->rx_opt.sack_ok &&
+	       (tp->sacked_out + tp->lost_out > tp->packets_out));
 	tp->left_out = tp->sacked_out + tp->lost_out;
 }
 
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 66c2d3e..39ef925 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -416,25 +416,6 @@
 	u32	secid;
 };
 
-/* SAD metadata, add more later */
-struct xfrm_sadinfo
-{
-	u32 sadhcnt; /* current hash bkts */
-	u32 sadhmcnt; /* max allowed hash bkts */
-	u32 sadcnt; /* current running count */
-};
-
-struct xfrm_spdinfo
-{
-	u32 incnt;
-	u32 outcnt;
-	u32 fwdcnt;
-	u32 inscnt;
-	u32 outscnt;
-	u32 fwdscnt;
-	u32 spdhcnt;
-	u32 spdhmcnt;
-};
 #ifdef CONFIG_AUDITSYSCALL
 extern void xfrm_audit_log(uid_t auid, u32 secid, int type, int result,
 		    struct xfrm_policy *xp, struct xfrm_state *x);
@@ -964,11 +945,29 @@
 	return -ENOSYS;
 }
 #endif
+
+struct xfrmk_sadinfo {
+	u32 sadhcnt; /* current hash bkts */
+	u32 sadhmcnt; /* max allowed hash bkts */
+	u32 sadcnt; /* current running count */
+};
+
+struct xfrmk_spdinfo {
+	u32 incnt;
+	u32 outcnt;
+	u32 fwdcnt;
+	u32 inscnt;
+	u32 outscnt;
+	u32 fwdscnt;
+	u32 spdhcnt;
+	u32 spdhmcnt;
+};
+
 extern struct xfrm_state *xfrm_find_acq_byseq(u32 seq);
 extern int xfrm_state_delete(struct xfrm_state *x);
 extern void xfrm_state_flush(u8 proto, struct xfrm_audit *audit_info);
-extern void xfrm_sad_getinfo(struct xfrm_sadinfo *si);
-extern void xfrm_spd_getinfo(struct xfrm_spdinfo *si);
+extern void xfrm_sad_getinfo(struct xfrmk_sadinfo *si);
+extern void xfrm_spd_getinfo(struct xfrmk_spdinfo *si);
 extern int xfrm_replay_check(struct xfrm_state *x, __be32 seq);
 extern void xfrm_replay_advance(struct xfrm_state *x, __be32 seq);
 extern void xfrm_replay_notify(struct xfrm_state *x, int event);
diff --git a/include/rdma/ib_mad.h b/include/rdma/ib_mad.h
index 585d28e..739fa4d 100644
--- a/include/rdma/ib_mad.h
+++ b/include/rdma/ib_mad.h
@@ -39,8 +39,6 @@
 #if !defined( IB_MAD_H )
 #define IB_MAD_H
 
-#include <linux/pci.h>
-
 #include <rdma/ib_verbs.h>
 
 /* Management base version */
diff --git a/include/scsi/iscsi_proto.h b/include/scsi/iscsi_proto.h
index 4a44278..8d1e4e8 100644
--- a/include/scsi/iscsi_proto.h
+++ b/include/scsi/iscsi_proto.h
@@ -588,7 +588,17 @@
 #define VALUE_MAXLEN		255
 #define TARGET_NAME_MAXLEN	VALUE_MAXLEN
 
-#define DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH	8192
+#define ISCSI_DEF_MAX_RECV_SEG_LEN		8192
+#define ISCSI_MIN_MAX_RECV_SEG_LEN		512
+#define ISCSI_MAX_MAX_RECV_SEG_LEN		16777215
+
+#define ISCSI_DEF_FIRST_BURST_LEN		65536
+#define ISCSI_MIN_FIRST_BURST_LEN		512
+#define ISCSI_MAX_FIRST_BURST_LEN		16777215
+
+#define ISCSI_DEF_MAX_BURST_LEN			262144
+#define ISCSI_MIN_MAX_BURST_LEN			512
+#define ISCSI_MAX_MAX_BURST_LEN			16777215
 
 /************************* RFC 3720 End *****************************/
 
diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h
index 5c0e979..9f8f80a 100644
--- a/include/scsi/scsi.h
+++ b/include/scsi/scsi.h
@@ -203,6 +203,7 @@
 
 /*
  *  DEVICE TYPES
+ *  Please keep them in 0x%02x format for $MODALIAS to work
  */
 
 #define TYPE_DISK           0x00
diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h
index d6948d0..a2e0c10 100644
--- a/include/scsi/scsi_cmnd.h
+++ b/include/scsi/scsi_cmnd.h
@@ -73,9 +73,6 @@
 	unsigned short use_sg;	/* Number of pieces of scatter-gather */
 	unsigned short sglist_len;	/* size of malloc'd scatter-gather list */
 
-	/* offset in cmd we are at (for multi-transfer tgt cmds) */
-	unsigned offset;
-
 	unsigned underflow;	/* Return error if less than
 				   this amount is transferred */
 
diff --git a/include/scsi/scsi_dbg.h b/include/scsi/scsi_dbg.h
index 3bbbfbe..5a43a4c 100644
--- a/include/scsi/scsi_dbg.h
+++ b/include/scsi/scsi_dbg.h
@@ -5,14 +5,16 @@
 struct scsi_sense_hdr;
 
 extern void scsi_print_command(struct scsi_cmnd *);
-extern void scsi_print_sense_hdr(const char *, struct scsi_sense_hdr *);
 extern void __scsi_print_command(unsigned char *);
-extern void scsi_print_sense(const char *, struct scsi_cmnd *);
+extern void scsi_show_extd_sense(unsigned char, unsigned char);
+extern void scsi_show_sense_hdr(struct scsi_sense_hdr *);
+extern void scsi_print_sense_hdr(const char *, struct scsi_sense_hdr *);
+extern void scsi_print_sense(char *, struct scsi_cmnd *);
 extern void __scsi_print_sense(const char *name,
 			       const unsigned char *sense_buffer,
 			       int sense_len);
-extern void scsi_print_driverbyte(int);
-extern void scsi_print_hostbyte(int);
+extern void scsi_show_result(int);
+extern void scsi_print_result(struct scsi_cmnd *);
 extern void scsi_print_status(unsigned char);
 extern const char *scsi_sense_key_string(unsigned char);
 extern const char *scsi_extd_sense_format(unsigned char, unsigned char);
diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
index 9dd37e2..2f3c5b8b 100644
--- a/include/scsi/scsi_device.h
+++ b/include/scsi/scsi_device.h
@@ -5,6 +5,7 @@
 #include <linux/list.h>
 #include <linux/spinlock.h>
 #include <linux/workqueue.h>
+#include <linux/blkdev.h>
 #include <asm/atomic.h>
 
 struct request_queue;
@@ -119,6 +120,7 @@
 	unsigned use_192_bytes_for_3f:1; /* ask for 192 bytes from page 0x3f */
 	unsigned no_start_on_add:1;	/* do not issue start on add */
 	unsigned allow_restart:1; /* issue START_UNIT in error handler */
+	unsigned manage_start_stop:1;	/* Let HLD (sd) manage start/stop */
 	unsigned no_uld_attach:1; /* disable connecting to upper level drivers */
 	unsigned select_no_atn:1;
 	unsigned fix_capacity:1;	/* READ_CAPACITY is too high by 1 */
@@ -154,8 +156,11 @@
 #define sdev_printk(prefix, sdev, fmt, a...)	\
 	dev_printk(prefix, &(sdev)->sdev_gendev, fmt, ##a)
 
-#define scmd_printk(prefix, scmd, fmt, a...)	\
-	dev_printk(prefix, &(scmd)->device->sdev_gendev, fmt, ##a)
+#define scmd_printk(prefix, scmd, fmt, a...)				\
+        (scmd)->request->rq_disk ?					\
+	sdev_printk(prefix, (scmd)->device, "[%s] " fmt,		\
+		    (scmd)->request->rq_disk->disk_name, ##a) :		\
+	sdev_printk(prefix, (scmd)->device, fmt, ##a)
 
 enum scsi_target_state {
 	STARGET_RUNNING = 1,
@@ -353,4 +358,9 @@
 		return 0;
 	return sdev->inquiry[56] & 0x02;
 }
+
+#define MODULE_ALIAS_SCSI_DEVICE(type) \
+	MODULE_ALIAS("scsi:t-" __stringify(type) "*")
+#define SCSI_DEVICE_MODALIAS_FMT "scsi:t-0x%02x"
+
 #endif /* _SCSI_SCSI_DEVICE_H */
diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
index 7f1f411..68f461b 100644
--- a/include/scsi/scsi_host.h
+++ b/include/scsi/scsi_host.h
@@ -129,6 +129,11 @@
 	 * the LLD. When the driver is finished processing the command
 	 * the done callback is invoked.
 	 *
+	 * This is called to inform the LLD to transfer
+	 * cmd->request_bufflen bytes. The cmd->use_sg speciefies the
+	 * number of scatterlist entried in the command and
+	 * cmd->request_buffer contains the scatterlist.
+	 *
 	 * return values: see queuecommand
 	 *
 	 * If the LLD accepts the cmd, it should set the result to an
@@ -139,20 +144,6 @@
 	/* TODO: rename */
 	int (* transfer_response)(struct scsi_cmnd *,
 				  void (*done)(struct scsi_cmnd *));
-	/*
-	 * This is called to inform the LLD to transfer cmd->request_bufflen
-	 * bytes of the cmd at cmd->offset in the cmd. The cmd->use_sg
-	 * speciefies the number of scatterlist entried in the command
-	 * and cmd->request_buffer contains the scatterlist.
-	 *
-	 * If the command cannot be processed in one transfer_data call
-	 * becuase a scatterlist within the LLD's limits cannot be
-	 * created then transfer_data will be called multiple times.
-	 * It is initially called from process context, and later
-	 * calls are from the interrup context.
-	 */
-	int (* transfer_data)(struct scsi_cmnd *,
-			      void (*done)(struct scsi_cmnd *));
 
 	/* Used as callback for the completion of task management request. */
 	int (* tsk_mgmt_response)(u64 mid, int result);
@@ -335,6 +326,19 @@
 	int (*proc_info)(struct Scsi_Host *, char *, char **, off_t, int, int);
 
 	/*
+	 * This is an optional routine that allows the transport to become
+	 * involved when a scsi io timer fires. The return value tells the
+	 * timer routine how to finish the io timeout handling:
+	 * EH_HANDLED:		I fixed the error, please complete the command
+	 * EH_RESET_TIMER:	I need more time, reset the timer and
+	 *			begin counting again
+	 * EH_NOT_HANDLED	Begin normal error recovery
+	 *
+	 * Status: OPTIONAL
+	 */
+	enum scsi_eh_timer_return (* eh_timed_out)(struct scsi_cmnd *);
+
+	/*
 	 * suspend support
 	 */
 	int (*resume)(struct scsi_device *);
diff --git a/include/scsi/scsi_tgt_if.h b/include/scsi/scsi_tgt_if.h
index 07d6e77..4cf9dff 100644
--- a/include/scsi/scsi_tgt_if.h
+++ b/include/scsi/scsi_tgt_if.h
@@ -45,11 +45,13 @@
 		/* user-> kernel */
 		struct {
 			int host_no;
-			uint32_t len;
 			int result;
-			aligned_u64 uaddr;
-			uint8_t rw;
 			aligned_u64 tag;
+			aligned_u64 uaddr;
+			aligned_u64 sense_uaddr;
+			uint32_t len;
+			uint32_t sense_len;
+			uint8_t rw;
 		} cmd_rsp;
 		struct {
 			int host_no;
diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h
index 798f7c7..1e79730 100644
--- a/include/scsi/scsi_transport_fc.h
+++ b/include/scsi/scsi_transport_fc.h
@@ -108,6 +108,8 @@
 #define FC_PORTSPEED_2GBIT		2
 #define FC_PORTSPEED_4GBIT		4
 #define FC_PORTSPEED_10GBIT		8
+#define FC_PORTSPEED_8GBIT		0x10
+#define FC_PORTSPEED_16GBIT		0x20
 #define FC_PORTSPEED_NOT_NEGOTIATED	(1 << 15) /* Speed not established */
 
 /*
diff --git a/include/scsi/sd.h b/include/scsi/sd.h
new file mode 100644
index 0000000..5261488
--- /dev/null
+++ b/include/scsi/sd.h
@@ -0,0 +1,72 @@
+#ifndef _SCSI_DISK_H
+#define _SCSI_DISK_H
+
+/*
+ * More than enough for everybody ;)  The huge number of majors
+ * is a leftover from 16bit dev_t days, we don't really need that
+ * much numberspace.
+ */
+#define SD_MAJORS	16
+
+/*
+ * This is limited by the naming scheme enforced in sd_probe,
+ * add another character to it if you really need more disks.
+ */
+#define SD_MAX_DISKS	(((26 * 26) + 26 + 1) * 26)
+
+/*
+ * Time out in seconds for disks and Magneto-opticals (which are slower).
+ */
+#define SD_TIMEOUT		(30 * HZ)
+#define SD_MOD_TIMEOUT		(75 * HZ)
+
+/*
+ * Number of allowed retries
+ */
+#define SD_MAX_RETRIES		5
+#define SD_PASSTHROUGH_RETRIES	1
+
+/*
+ * Size of the initial data buffer for mode and read capacity data
+ */
+#define SD_BUF_SIZE		512
+
+struct scsi_disk {
+	struct scsi_driver *driver;	/* always &sd_template */
+	struct scsi_device *device;
+	struct class_device cdev;
+	struct gendisk	*disk;
+	unsigned int	openers;	/* protected by BKL for now, yuck */
+	sector_t	capacity;	/* size in 512-byte sectors */
+	u32		index;
+	u8		media_present;
+	u8		write_prot;
+	unsigned	WCE : 1;	/* state of disk WCE bit */
+	unsigned	RCD : 1;	/* state of disk RCD bit, unused */
+	unsigned	DPOFUA : 1;	/* state of disk DPOFUA bit */
+};
+#define to_scsi_disk(obj) container_of(obj,struct scsi_disk,cdev)
+
+static int  sd_revalidate_disk(struct gendisk *disk);
+static void sd_rw_intr(struct scsi_cmnd * SCpnt);
+static int  sd_probe(struct device *);
+static int  sd_remove(struct device *);
+static void sd_shutdown(struct device *dev);
+static int sd_suspend(struct device *dev, pm_message_t state);
+static int sd_resume(struct device *dev);
+static void sd_rescan(struct device *);
+static int  sd_init_command(struct scsi_cmnd *);
+static int  sd_issue_flush(struct device *, sector_t *);
+static void sd_prepare_flush(request_queue_t *, struct request *);
+static void sd_read_capacity(struct scsi_disk *sdkp, unsigned char *buffer);
+static void scsi_disk_release(struct class_device *cdev);
+static void sd_print_sense_hdr(struct scsi_disk *, struct scsi_sense_hdr *);
+static void sd_print_result(struct scsi_disk *, int);
+
+#define sd_printk(prefix, sdsk, fmt, a...)				\
+        (sdsk)->disk ?							\
+	sdev_printk(prefix, (sdsk)->device, "[%s] " fmt,		\
+		    (sdsk)->disk->disk_name, ##a) :			\
+	sdev_printk(prefix, (sdsk)->device, fmt, ##a)
+
+#endif /* _SCSI_DISK_H */
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c
index 0133f4f..615ce97 100644
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -11,6 +11,7 @@
  */
 
 #include <linux/irq.h>
+#include <linux/msi.h>
 #include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/kernel_stat.h>
@@ -185,6 +186,8 @@
 	desc = irq_desc + irq;
 	spin_lock_irqsave(&desc->lock, flags);
 	desc->msi_desc = entry;
+	if (entry)
+		entry->irq = irq;
 	spin_unlock_irqrestore(&desc->lock, flags);
 	return 0;
 }
diff --git a/kernel/ksysfs.c b/kernel/ksysfs.c
index e0ffe4ab..559deca 100644
--- a/kernel/ksysfs.c
+++ b/kernel/ksysfs.c
@@ -24,18 +24,18 @@
 
 #if defined(CONFIG_HOTPLUG) && defined(CONFIG_NET)
 /* current uevent sequence number */
-static ssize_t uevent_seqnum_show(struct subsystem *subsys, char *page)
+static ssize_t uevent_seqnum_show(struct kset *kset, char *page)
 {
 	return sprintf(page, "%llu\n", (unsigned long long)uevent_seqnum);
 }
 KERNEL_ATTR_RO(uevent_seqnum);
 
 /* uevent helper program, used during early boo */
-static ssize_t uevent_helper_show(struct subsystem *subsys, char *page)
+static ssize_t uevent_helper_show(struct kset *kset, char *page)
 {
 	return sprintf(page, "%s\n", uevent_helper);
 }
-static ssize_t uevent_helper_store(struct subsystem *subsys, const char *page, size_t count)
+static ssize_t uevent_helper_store(struct kset *kset, const char *page, size_t count)
 {
 	if (count+1 > UEVENT_HELPER_PATH_LEN)
 		return -ENOENT;
@@ -49,13 +49,13 @@
 #endif
 
 #ifdef CONFIG_KEXEC
-static ssize_t kexec_loaded_show(struct subsystem *subsys, char *page)
+static ssize_t kexec_loaded_show(struct kset *kset, char *page)
 {
 	return sprintf(page, "%d\n", !!kexec_image);
 }
 KERNEL_ATTR_RO(kexec_loaded);
 
-static ssize_t kexec_crash_loaded_show(struct subsystem *subsys, char *page)
+static ssize_t kexec_crash_loaded_show(struct kset *kset, char *page)
 {
 	return sprintf(page, "%d\n", !!kexec_crash_image);
 }
@@ -85,7 +85,7 @@
 {
 	int error = subsystem_register(&kernel_subsys);
 	if (!error)
-		error = sysfs_create_group(&kernel_subsys.kset.kobj,
+		error = sysfs_create_group(&kernel_subsys.kobj,
 					   &kernel_attr_group);
 
 	return error;
diff --git a/kernel/module.c b/kernel/module.c
index 4dc4a25..1eb8ca5 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -45,6 +45,8 @@
 #include <asm/cacheflush.h>
 #include <linux/license.h>
 
+extern int module_sysfs_initialized;
+
 #if 0
 #define DEBUGP printk
 #else
@@ -1117,8 +1119,8 @@
 {
 	int err;
 
-	if (!module_subsys.kset.subsys) {
-		printk(KERN_ERR "%s: module_subsys not initialized\n",
+	if (!module_sysfs_initialized) {
+		printk(KERN_ERR "%s: module sysfs not initialized\n",
 		       mod->name);
 		err = -EINVAL;
 		goto out;
@@ -2385,7 +2387,7 @@
 		struct kobject *mkobj;
 
 		/* Lookup built-in module entry in /sys/modules */
-		mkobj = kset_find_obj(&module_subsys.kset, drv->mod_name);
+		mkobj = kset_find_obj(&module_subsys, drv->mod_name);
 		if (mkobj) {
 			mk = container_of(mkobj, struct module_kobject, kobj);
 			/* remember our module structure */
diff --git a/kernel/params.c b/kernel/params.c
index 1fc4ac7..3121723 100644
--- a/kernel/params.c
+++ b/kernel/params.c
@@ -691,6 +691,7 @@
 };
 
 decl_subsys(module, &module_ktype, &module_uevent_ops);
+int module_sysfs_initialized;
 
 static struct kobj_type module_ktype = {
 	.sysfs_ops =	&module_sysfs_ops,
@@ -709,6 +710,7 @@
 			__FILE__, __LINE__, ret);
 		return ret;
 	}
+	module_sysfs_initialized = 1;
 
 	param_sysfs_builtin();
 
diff --git a/kernel/power/disk.c b/kernel/power/disk.c
index 02e4fb69..8df51c2 100644
--- a/kernel/power/disk.c
+++ b/kernel/power/disk.c
@@ -322,13 +322,13 @@
  *	supports it (as determined from pm_ops->pm_disk_mode).
  */
 
-static ssize_t disk_show(struct subsystem * subsys, char * buf)
+static ssize_t disk_show(struct kset *kset, char *buf)
 {
 	return sprintf(buf, "%s\n", pm_disk_modes[pm_disk_mode]);
 }
 
 
-static ssize_t disk_store(struct subsystem * s, const char * buf, size_t n)
+static ssize_t disk_store(struct kset *kset, const char *buf, size_t n)
 {
 	int error = 0;
 	int i;
@@ -373,13 +373,13 @@
 
 power_attr(disk);
 
-static ssize_t resume_show(struct subsystem * subsys, char *buf)
+static ssize_t resume_show(struct kset *kset, char *buf)
 {
 	return sprintf(buf,"%d:%d\n", MAJOR(swsusp_resume_device),
 		       MINOR(swsusp_resume_device));
 }
 
-static ssize_t resume_store(struct subsystem *subsys, const char *buf, size_t n)
+static ssize_t resume_store(struct kset *kset, const char *buf, size_t n)
 {
 	unsigned int maj, min;
 	dev_t res;
@@ -405,12 +405,12 @@
 
 power_attr(resume);
 
-static ssize_t image_size_show(struct subsystem * subsys, char *buf)
+static ssize_t image_size_show(struct kset *kset, char *buf)
 {
 	return sprintf(buf, "%lu\n", image_size);
 }
 
-static ssize_t image_size_store(struct subsystem * subsys, const char * buf, size_t n)
+static ssize_t image_size_store(struct kset *kset, const char *buf, size_t n)
 {
 	unsigned long size;
 
@@ -439,7 +439,7 @@
 
 static int __init pm_disk_init(void)
 {
-	return sysfs_create_group(&power_subsys.kset.kobj,&attr_group);
+	return sysfs_create_group(&power_subsys.kobj, &attr_group);
 }
 
 core_initcall(pm_disk_init);
diff --git a/kernel/power/main.c b/kernel/power/main.c
index 72419a3..b21c2a5 100644
--- a/kernel/power/main.c
+++ b/kernel/power/main.c
@@ -285,7 +285,7 @@
  *	proper enumerated value, and initiates a suspend transition.
  */
 
-static ssize_t state_show(struct subsystem * subsys, char * buf)
+static ssize_t state_show(struct kset *kset, char *buf)
 {
 	int i;
 	char * s = buf;
@@ -298,7 +298,7 @@
 	return (s - buf);
 }
 
-static ssize_t state_store(struct subsystem * subsys, const char * buf, size_t n)
+static ssize_t state_store(struct kset *kset, const char *buf, size_t n)
 {
 	suspend_state_t state = PM_SUSPEND_STANDBY;
 	const char * const *s;
@@ -325,13 +325,13 @@
 #ifdef CONFIG_PM_TRACE
 int pm_trace_enabled;
 
-static ssize_t pm_trace_show(struct subsystem * subsys, char * buf)
+static ssize_t pm_trace_show(struct kset *kset, char *buf)
 {
 	return sprintf(buf, "%d\n", pm_trace_enabled);
 }
 
 static ssize_t
-pm_trace_store(struct subsystem * subsys, const char * buf, size_t n)
+pm_trace_store(struct kset *kset, const char *buf, size_t n)
 {
 	int val;
 
@@ -365,7 +365,7 @@
 {
 	int error = subsystem_register(&power_subsys);
 	if (!error)
-		error = sysfs_create_group(&power_subsys.kset.kobj,&attr_group);
+		error = sysfs_create_group(&power_subsys.kobj,&attr_group);
 	return error;
 }
 
diff --git a/kernel/power/power.h b/kernel/power/power.h
index 1c6eef8..33bd94c 100644
--- a/kernel/power/power.h
+++ b/kernel/power/power.h
@@ -37,7 +37,7 @@
 	.store	= _name##_store,		\
 }
 
-extern struct subsystem power_subsys;
+extern struct kset power_subsys;
 
 /* Preferred image size in bytes (default 500 MB) */
 extern unsigned long image_size;
diff --git a/lib/iomap.c b/lib/iomap.c
index 4d43f37..a57d262 100644
--- a/lib/iomap.c
+++ b/lib/iomap.c
@@ -35,20 +35,28 @@
 #define PIO_RESERVED	0x40000UL
 #endif
 
+static void bad_io_access(unsigned long port, const char *access)
+{
+	static int count = 10;
+	if (count) {
+		count--;
+		printk(KERN_ERR "Bad IO access at port %lx (%s)\n", port, access);
+		WARN_ON(1);
+	}
+}
+
 /*
  * Ugly macros are a way of life.
  */
-#define VERIFY_PIO(port) BUG_ON((port & ~PIO_MASK) != PIO_OFFSET)
-
 #define IO_COND(addr, is_pio, is_mmio) do {			\
 	unsigned long port = (unsigned long __force)addr;	\
-	if (port < PIO_RESERVED) {				\
-		VERIFY_PIO(port);				\
+	if (port >= PIO_RESERVED) {				\
+		is_mmio;					\
+	} else if (port > PIO_OFFSET) {				\
 		port &= PIO_MASK;				\
 		is_pio;						\
-	} else {						\
-		is_mmio;					\
-	}							\
+	} else							\
+		bad_io_access(port, #is_pio );			\
 } while (0)
 
 #ifndef pio_read16be
@@ -64,22 +72,27 @@
 unsigned int fastcall ioread8(void __iomem *addr)
 {
 	IO_COND(addr, return inb(port), return readb(addr));
+	return 0xff;
 }
 unsigned int fastcall ioread16(void __iomem *addr)
 {
 	IO_COND(addr, return inw(port), return readw(addr));
+	return 0xffff;
 }
 unsigned int fastcall ioread16be(void __iomem *addr)
 {
 	IO_COND(addr, return pio_read16be(port), return mmio_read16be(addr));
+	return 0xffff;
 }
 unsigned int fastcall ioread32(void __iomem *addr)
 {
 	IO_COND(addr, return inl(port), return readl(addr));
+	return 0xffffffff;
 }
 unsigned int fastcall ioread32be(void __iomem *addr)
 {
 	IO_COND(addr, return pio_read32be(port), return mmio_read32be(addr));
+	return 0xffffffff;
 }
 EXPORT_SYMBOL(ioread8);
 EXPORT_SYMBOL(ioread16);
diff --git a/lib/kobject.c b/lib/kobject.c
index cecf2fb..fc5f3f6 100644
--- a/lib/kobject.c
+++ b/lib/kobject.c
@@ -582,22 +582,10 @@
 /**
  *	kset_add - add a kset object to the hierarchy.
  *	@k:	kset.
- *
- *	Simply, this adds the kset's embedded kobject to the 
- *	hierarchy. 
- *	We also try to make sure that the kset's embedded kobject
- *	has a parent before it is added. We only care if the embedded
- *	kobject is not part of a kset itself, since kobject_add()
- *	assigns a parent in that case. 
- *	If that is the case, and the kset has a controlling subsystem,
- *	then we set the kset's parent to be said subsystem. 
  */
 
 int kset_add(struct kset * k)
 {
-	if (!k->kobj.parent && !k->kobj.kset && k->subsys)
-		k->kobj.parent = &k->subsys->kset.kobj;
-
 	return kobject_add(&k->kobj);
 }
 
@@ -656,53 +644,28 @@
 	return ret;
 }
 
-
-void subsystem_init(struct subsystem * s)
+void subsystem_init(struct kset *s)
 {
-	kset_init(&s->kset);
+	kset_init(s);
 }
 
-/**
- *	subsystem_register - register a subsystem.
- *	@s:	the subsystem we're registering.
- *
- *	Once we register the subsystem, we want to make sure that 
- *	the kset points back to this subsystem.
- */
-
-int subsystem_register(struct subsystem * s)
+int subsystem_register(struct kset *s)
 {
-	int error;
-
-	if (!s)
-		return -EINVAL;
-
-	subsystem_init(s);
-	pr_debug("subsystem %s: registering\n",s->kset.kobj.name);
-
-	if (!(error = kset_add(&s->kset))) {
-		if (!s->kset.subsys)
-			s->kset.subsys = s;
-	}
-	return error;
+	return kset_register(s);
 }
 
-void subsystem_unregister(struct subsystem * s)
+void subsystem_unregister(struct kset *s)
 {
-	if (!s)
-		return;
-	pr_debug("subsystem %s: unregistering\n",s->kset.kobj.name);
-	kset_unregister(&s->kset);
+	kset_unregister(s);
 }
 
-
 /**
  *	subsystem_create_file - export sysfs attribute file.
  *	@s:	subsystem.
  *	@a:	subsystem attribute descriptor.
  */
 
-int subsys_create_file(struct subsystem * s, struct subsys_attribute * a)
+int subsys_create_file(struct kset *s, struct subsys_attribute *a)
 {
 	int error = 0;
 
@@ -710,28 +673,12 @@
 		return -EINVAL;
 
 	if (subsys_get(s)) {
-		error = sysfs_create_file(&s->kset.kobj,&a->attr);
+		error = sysfs_create_file(&s->kobj, &a->attr);
 		subsys_put(s);
 	}
 	return error;
 }
 
-
-/**
- *	subsystem_remove_file - remove sysfs attribute file.
- *	@s:	subsystem.
- *	@a:	attribute desciptor.
- */
-#if 0
-void subsys_remove_file(struct subsystem * s, struct subsys_attribute * a)
-{
-	if (subsys_get(s)) {
-		sysfs_remove_file(&s->kset.kobj,&a->attr);
-		subsys_put(s);
-	}
-}
-#endif  /*  0  */
-
 EXPORT_SYMBOL(kobject_init);
 EXPORT_SYMBOL(kobject_register);
 EXPORT_SYMBOL(kobject_unregister);
diff --git a/lib/parser.c b/lib/parser.c
index 7ad2a48..703c8c1 100644
--- a/lib/parser.c
+++ b/lib/parser.c
@@ -22,7 +22,7 @@
  * match extremely simple token=arg style patterns. If the pattern is found,
  * the location(s) of the arguments will be returned in the @args array.
  */
-static int match_one(char *s, char *p, substring_t args[])
+static int match_one(char *s, const char *p, substring_t args[])
 {
 	char *meta;
 	int argc = 0;
@@ -43,7 +43,7 @@
 		p = meta + 1;
 
 		if (isdigit(*p))
-			len = simple_strtoul(p, &p, 10);
+			len = simple_strtoul(p, (char **) &p, 10);
 		else if (*p == '%') {
 			if (*s++ != '%')
 				return 0;
@@ -102,7 +102,7 @@
  */
 int match_token(char *s, match_table_t table, substring_t args[])
 {
-	struct match_token *p;
+	const struct match_token *p;
 
 	for (p = table; !match_one(s, p->pattern, args) ; p++)
 		;
@@ -190,7 +190,7 @@
  * &substring_t @s to the c-style string @to. Caller guarantees that @to is
  * large enough to hold the characters of @s.
  */
-void match_strcpy(char *to, substring_t *s)
+void match_strcpy(char *to, const substring_t *s)
 {
 	memcpy(to, s->from, s->to - s->from);
 	to[s->to - s->from] = '\0';
@@ -204,7 +204,7 @@
  * the &substring_t @s. The caller is responsible for freeing the returned
  * string with kfree().
  */
-char *match_strdup(substring_t *s)
+char *match_strdup(const substring_t *s)
 {
 	char *p = kmalloc(s->to - s->from + 1, GFP_KERNEL);
 	if (p)
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index c0c7bb8..bd93c45 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -117,8 +117,7 @@
 	struct net_device *dev, *nxt;
 
 	rtnl_lock();
-	for (dev = dev_base; dev; dev = nxt) {
-		nxt = dev->next;
+	for_each_netdev_safe(dev, nxt) {
 		if (dev->priv_flags & IFF_802_1Q_VLAN) {
 			unregister_vlan_dev(VLAN_DEV_INFO(dev)->real_dev,
 					    VLAN_DEV_INFO(dev)->vlan_id);
diff --git a/net/8021q/vlanproc.c b/net/8021q/vlanproc.c
index 5e24f72..d216a64 100644
--- a/net/8021q/vlanproc.c
+++ b/net/8021q/vlanproc.c
@@ -237,13 +237,9 @@
  * The following few functions build the content of /proc/net/vlan/config
  */
 
-/* starting at dev, find a VLAN device */
-static struct net_device *vlan_skip(struct net_device *dev)
+static inline int is_vlan_dev(struct net_device *dev)
 {
-	while (dev && !(dev->priv_flags & IFF_802_1Q_VLAN))
-		dev = dev->next;
-
-	return dev;
+	return dev->priv_flags & IFF_802_1Q_VLAN;
 }
 
 /* start read of /proc/net/vlan/config */
@@ -257,19 +253,35 @@
 	if (*pos == 0)
 		return SEQ_START_TOKEN;
 
-	for (dev = vlan_skip(dev_base); dev && i < *pos;
-	     dev = vlan_skip(dev->next), ++i);
+	for_each_netdev(dev) {
+		if (!is_vlan_dev(dev))
+			continue;
 
-	return  (i == *pos) ? dev : NULL;
+		if (i++ == *pos)
+			return dev;
+	}
+
+	return  NULL;
 }
 
 static void *vlan_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 {
+	struct net_device *dev;
+
 	++*pos;
 
-	return vlan_skip((v == SEQ_START_TOKEN)
-			    ? dev_base
-			    : ((struct net_device *)v)->next);
+	dev = (struct net_device *)v;
+	if (v == SEQ_START_TOKEN)
+		dev = net_device_entry(&dev_base_head);
+
+	for_each_netdev_continue(dev) {
+		if (!is_vlan_dev(dev))
+			continue;
+
+		return dev;
+	}
+
+	return NULL;
 }
 
 static void vlan_seq_stop(struct seq_file *seq, void *v)
diff --git a/net/Kconfig b/net/Kconfig
index 2fc8e77..5b22278 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -220,6 +220,7 @@
 menu "Wireless"
 
 source "net/wireless/Kconfig"
+source "net/mac80211/Kconfig"
 source "net/ieee80211/Kconfig"
 
 endmenu
diff --git a/net/Makefile b/net/Makefile
index 6b74d41..9fdb60c 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -45,6 +45,8 @@
 obj-$(CONFIG_VLAN_8021Q)	+= 8021q/
 obj-$(CONFIG_IP_DCCP)		+= dccp/
 obj-$(CONFIG_IP_SCTP)		+= sctp/
+obj-y				+= wireless/
+obj-$(CONFIG_MAC80211)		+= mac80211/
 obj-$(CONFIG_IEEE80211)		+= ieee80211/
 obj-$(CONFIG_TIPC)		+= tipc/
 obj-$(CONFIG_NETLABEL)		+= netlabel/
@@ -53,5 +55,3 @@
 ifeq ($(CONFIG_NET),y)
 obj-$(CONFIG_SYSCTL)		+= sysctl_net.o
 endif
-
-obj-y				+= wireless/
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index 690573b..849deaf 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -475,11 +475,9 @@
 	struct net_device *dev, *nxt;
 
 	rtnl_lock();
-	for (dev = dev_base; dev; dev = nxt) {
-		nxt = dev->next;
+	for_each_netdev_safe(dev, nxt)
 		if (dev->priv_flags & IFF_EBRIDGE)
 			del_br(dev->priv);
-	}
 	rtnl_unlock();
 
 }
diff --git a/net/bridge/br_ioctl.c b/net/bridge/br_ioctl.c
index eda0fbf..bb15e9e 100644
--- a/net/bridge/br_ioctl.c
+++ b/net/bridge/br_ioctl.c
@@ -27,7 +27,9 @@
 	struct net_device *dev;
 	int i = 0;
 
-	for (dev = dev_base; dev && i < num; dev = dev->next) {
+	for_each_netdev(dev) {
+		if (i >= num)
+			break;
 		if (dev->priv_flags & IFF_EBRIDGE)
 			indices[i++] = dev->ifindex;
 	}
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
index 9b2986b..fa77987 100644
--- a/net/bridge/br_netfilter.c
+++ b/net/bridge/br_netfilter.c
@@ -142,14 +142,33 @@
 	return skb->nf_bridge;
 }
 
+static inline void nf_bridge_push_encap_header(struct sk_buff *skb)
+{
+	unsigned int len = nf_bridge_encap_header_len(skb);
+
+	skb_push(skb, len);
+	skb->network_header -= len;
+}
+
+static inline void nf_bridge_pull_encap_header(struct sk_buff *skb)
+{
+	unsigned int len = nf_bridge_encap_header_len(skb);
+
+	skb_pull(skb, len);
+	skb->network_header += len;
+}
+
+static inline void nf_bridge_pull_encap_header_rcsum(struct sk_buff *skb)
+{
+	unsigned int len = nf_bridge_encap_header_len(skb);
+
+	skb_pull_rcsum(skb, len);
+	skb->network_header += len;
+}
+
 static inline void nf_bridge_save_header(struct sk_buff *skb)
 {
-	int header_size = ETH_HLEN;
-
-	if (skb->protocol == htons(ETH_P_8021Q))
-		header_size += VLAN_HLEN;
-	else if (skb->protocol == htons(ETH_P_PPP_SES))
-		header_size += PPPOE_SES_HLEN;
+	int header_size = ETH_HLEN + nf_bridge_encap_header_len(skb);
 
 	skb_copy_from_linear_data_offset(skb, -header_size,
 					 skb->nf_bridge->data, header_size);
@@ -162,12 +181,7 @@
 int nf_bridge_copy_header(struct sk_buff *skb)
 {
 	int err;
-	int header_size = ETH_HLEN;
-
-	if (skb->protocol == htons(ETH_P_8021Q))
-		header_size += VLAN_HLEN;
-	else if (skb->protocol == htons(ETH_P_PPP_SES))
-		header_size += PPPOE_SES_HLEN;
+	int header_size = ETH_HLEN + nf_bridge_encap_header_len(skb);
 
 	err = skb_cow(skb, header_size);
 	if (err)
@@ -175,11 +189,7 @@
 
 	skb_copy_to_linear_data_offset(skb, -header_size,
 				       skb->nf_bridge->data, header_size);
-
-	if (skb->protocol == htons(ETH_P_8021Q))
-		__skb_push(skb, VLAN_HLEN);
-	else if (skb->protocol == htons(ETH_P_PPP_SES))
-		__skb_push(skb, PPPOE_SES_HLEN);
+	__skb_push(skb, nf_bridge_encap_header_len(skb));
 	return 0;
 }
 
@@ -200,13 +210,7 @@
 	dst_hold(skb->dst);
 
 	skb->dev = nf_bridge->physindev;
-	if (skb->protocol == htons(ETH_P_8021Q)) {
-		skb_push(skb, VLAN_HLEN);
-		skb->network_header -= VLAN_HLEN;
-	} else if (skb->protocol == htons(ETH_P_PPP_SES)) {
-		skb_push(skb, PPPOE_SES_HLEN);
-		skb->network_header -= PPPOE_SES_HLEN;
-	}
+	nf_bridge_push_encap_header(skb);
 	NF_HOOK_THRESH(PF_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL,
 		       br_handle_frame_finish, 1);
 
@@ -284,13 +288,7 @@
 	if (!skb->dev)
 		kfree_skb(skb);
 	else {
-		if (skb->protocol == htons(ETH_P_8021Q)) {
-			skb_pull(skb, VLAN_HLEN);
-			skb->network_header += VLAN_HLEN;
-		} else if (skb->protocol == htons(ETH_P_PPP_SES)) {
-			skb_pull(skb, PPPOE_SES_HLEN);
-			skb->network_header += PPPOE_SES_HLEN;
-		}
+		nf_bridge_pull_encap_header(skb);
 		skb->dst->output(skb);
 	}
 	return 0;
@@ -356,15 +354,7 @@
 				 * bridged frame */
 				nf_bridge->mask |= BRNF_BRIDGED_DNAT;
 				skb->dev = nf_bridge->physindev;
-				if (skb->protocol ==
-				    htons(ETH_P_8021Q)) {
-					skb_push(skb, VLAN_HLEN);
-					skb->network_header -= VLAN_HLEN;
-				} else if(skb->protocol ==
-				    htons(ETH_P_PPP_SES)) {
-					skb_push(skb, PPPOE_SES_HLEN);
-					skb->network_header -= PPPOE_SES_HLEN;
-				}
+				nf_bridge_push_encap_header(skb);
 				NF_HOOK_THRESH(PF_BRIDGE, NF_BR_PRE_ROUTING,
 					       skb, skb->dev, NULL,
 					       br_nf_pre_routing_finish_bridge,
@@ -380,13 +370,7 @@
 	}
 
 	skb->dev = nf_bridge->physindev;
-	if (skb->protocol == htons(ETH_P_8021Q)) {
-		skb_push(skb, VLAN_HLEN);
-		skb->network_header -= VLAN_HLEN;
-	} else if (skb->protocol == htons(ETH_P_PPP_SES)) {
-		skb_push(skb, PPPOE_SES_HLEN);
-		skb->network_header -= PPPOE_SES_HLEN;
-	}
+	nf_bridge_push_encap_header(skb);
 	NF_HOOK_THRESH(PF_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL,
 		       br_handle_frame_finish, 1);
 
@@ -536,14 +520,7 @@
 #endif
 		if ((skb = skb_share_check(*pskb, GFP_ATOMIC)) == NULL)
 			goto out;
-
-		if (skb->protocol == htons(ETH_P_8021Q)) {
-			skb_pull_rcsum(skb, VLAN_HLEN);
-			skb->network_header += VLAN_HLEN;
-		} else if (skb->protocol == htons(ETH_P_PPP_SES)) {
-			skb_pull_rcsum(skb, PPPOE_SES_HLEN);
-			skb->network_header += PPPOE_SES_HLEN;
-		}
+		nf_bridge_pull_encap_header_rcsum(skb);
 		return br_nf_pre_routing_ipv6(hook, skb, in, out, okfn);
 	}
 #ifdef CONFIG_SYSCTL
@@ -557,14 +534,7 @@
 
 	if ((skb = skb_share_check(*pskb, GFP_ATOMIC)) == NULL)
 		goto out;
-
-	if (skb->protocol == htons(ETH_P_8021Q)) {
-		skb_pull_rcsum(skb, VLAN_HLEN);
-		skb->network_header += VLAN_HLEN;
-	} else if (skb->protocol == htons(ETH_P_PPP_SES)) {
-		skb_pull_rcsum(skb, PPPOE_SES_HLEN);
-		skb->network_header += PPPOE_SES_HLEN;
-	}
+	nf_bridge_pull_encap_header_rcsum(skb);
 
 	if (!pskb_may_pull(skb, sizeof(struct iphdr)))
 		goto inhdr_error;
@@ -642,13 +612,7 @@
 	} else {
 		in = *((struct net_device **)(skb->cb));
 	}
-	if (skb->protocol == htons(ETH_P_8021Q)) {
-		skb_push(skb, VLAN_HLEN);
-		skb->network_header -= VLAN_HLEN;
-	} else if (skb->protocol == htons(ETH_P_PPP_SES)) {
-		skb_push(skb, PPPOE_SES_HLEN);
-		skb->network_header -= PPPOE_SES_HLEN;
-	}
+	nf_bridge_push_encap_header(skb);
 	NF_HOOK_THRESH(PF_BRIDGE, NF_BR_FORWARD, skb, in,
 		       skb->dev, br_forward_finish, 1);
 	return 0;
@@ -682,13 +646,7 @@
 	else
 		pf = PF_INET6;
 
-	if (skb->protocol == htons(ETH_P_8021Q)) {
-		skb_pull(*pskb, VLAN_HLEN);
-		(*pskb)->network_header += VLAN_HLEN;
-	} else if (skb->protocol == htons(ETH_P_PPP_SES)) {
-		skb_pull(*pskb, PPPOE_SES_HLEN);
-		(*pskb)->network_header += PPPOE_SES_HLEN;
-	}
+	nf_bridge_pull_encap_header(*pskb);
 
 	nf_bridge = skb->nf_bridge;
 	if (skb->pkt_type == PACKET_OTHERHOST) {
@@ -722,15 +680,12 @@
 	if (skb->protocol != htons(ETH_P_ARP)) {
 		if (!IS_VLAN_ARP(skb))
 			return NF_ACCEPT;
-		skb_pull(*pskb, VLAN_HLEN);
-		(*pskb)->network_header += VLAN_HLEN;
+		nf_bridge_pull_encap_header(*pskb);
 	}
 
 	if (arp_hdr(skb)->ar_pln != 4) {
-		if (IS_VLAN_ARP(skb)) {
-			skb_push(*pskb, VLAN_HLEN);
-			(*pskb)->network_header -= VLAN_HLEN;
-		}
+		if (IS_VLAN_ARP(skb))
+			nf_bridge_push_encap_header(*pskb);
 		return NF_ACCEPT;
 	}
 	*d = (struct net_device *)in;
@@ -777,13 +732,7 @@
 		skb->pkt_type = PACKET_OTHERHOST;
 		nf_bridge->mask ^= BRNF_PKT_TYPE;
 	}
-	if (skb->protocol == htons(ETH_P_8021Q)) {
-		skb_push(skb, VLAN_HLEN);
-		skb->network_header -= VLAN_HLEN;
-	} else if (skb->protocol == htons(ETH_P_PPP_SES)) {
-		skb_push(skb, PPPOE_SES_HLEN);
-		skb->network_header -= PPPOE_SES_HLEN;
-	}
+	nf_bridge_push_encap_header(skb);
 
 	NF_HOOK(PF_BRIDGE, NF_BR_FORWARD, skb, realindev, skb->dev,
 		br_forward_finish);
@@ -848,14 +797,7 @@
 		nf_bridge->mask |= BRNF_PKT_TYPE;
 	}
 
-	if (skb->protocol == htons(ETH_P_8021Q)) {
-		skb_pull(skb, VLAN_HLEN);
-		skb->network_header += VLAN_HLEN;
-	} else if (skb->protocol == htons(ETH_P_PPP_SES)) {
-		skb_pull(skb, PPPOE_SES_HLEN);
-		skb->network_header += PPPOE_SES_HLEN;
-	}
-
+	nf_bridge_pull_encap_header(skb);
 	nf_bridge_save_header(skb);
 
 #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
index 35facc0..0fcf6f0 100644
--- a/net/bridge/br_netlink.c
+++ b/net/bridge/br_netlink.c
@@ -109,7 +109,8 @@
 	struct net_device *dev;
 	int idx;
 
-	for (dev = dev_base, idx = 0; dev; dev = dev->next) {
+	idx = 0;
+	for_each_netdev(dev) {
 		/* not a bridge port */
 		if (dev->br_port == NULL || idx < cb->args[0])
 			goto skip;
diff --git a/net/core/dev.c b/net/core/dev.c
index eb99900..f27d4ab 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -156,13 +156,13 @@
 #endif
 
 /*
- * The @dev_base list is protected by @dev_base_lock and the rtnl
+ * The @dev_base_head list is protected by @dev_base_lock and the rtnl
  * semaphore.
  *
  * Pure readers hold dev_base_lock for reading.
  *
  * Writers must hold the rtnl semaphore while they loop through the
- * dev_base list, and hold dev_base_lock for writing when they do the
+ * dev_base_head list, and hold dev_base_lock for writing when they do the
  * actual updates.  This allows pure readers to access the list even
  * while a writer is preparing to update it.
  *
@@ -174,11 +174,10 @@
  * unregister_netdevice(), which must be called with the rtnl
  * semaphore held.
  */
-struct net_device *dev_base;
-static struct net_device **dev_tail = &dev_base;
+LIST_HEAD(dev_base_head);
 DEFINE_RWLOCK(dev_base_lock);
 
-EXPORT_SYMBOL(dev_base);
+EXPORT_SYMBOL(dev_base_head);
 EXPORT_SYMBOL(dev_base_lock);
 
 #define NETDEV_HASHBITS	8
@@ -567,26 +566,38 @@
 
 	ASSERT_RTNL();
 
-	for (dev = dev_base; dev; dev = dev->next)
+	for_each_netdev(dev)
 		if (dev->type == type &&
 		    !memcmp(dev->dev_addr, ha, dev->addr_len))
-			break;
-	return dev;
+			return dev;
+
+	return NULL;
 }
 
 EXPORT_SYMBOL(dev_getbyhwaddr);
 
+struct net_device *__dev_getfirstbyhwtype(unsigned short type)
+{
+	struct net_device *dev;
+
+	ASSERT_RTNL();
+	for_each_netdev(dev)
+		if (dev->type == type)
+			return dev;
+
+	return NULL;
+}
+
+EXPORT_SYMBOL(__dev_getfirstbyhwtype);
+
 struct net_device *dev_getfirstbyhwtype(unsigned short type)
 {
 	struct net_device *dev;
 
 	rtnl_lock();
-	for (dev = dev_base; dev; dev = dev->next) {
-		if (dev->type == type) {
-			dev_hold(dev);
-			break;
-		}
-	}
+	dev = __dev_getfirstbyhwtype(type);
+	if (dev)
+		dev_hold(dev);
 	rtnl_unlock();
 	return dev;
 }
@@ -606,17 +617,19 @@
 
 struct net_device * dev_get_by_flags(unsigned short if_flags, unsigned short mask)
 {
-	struct net_device *dev;
+	struct net_device *dev, *ret;
 
+	ret = NULL;
 	read_lock(&dev_base_lock);
-	for (dev = dev_base; dev != NULL; dev = dev->next) {
+	for_each_netdev(dev) {
 		if (((dev->flags ^ if_flags) & mask) == 0) {
 			dev_hold(dev);
+			ret = dev;
 			break;
 		}
 	}
 	read_unlock(&dev_base_lock);
-	return dev;
+	return ret;
 }
 
 /**
@@ -682,7 +695,7 @@
 		if (!inuse)
 			return -ENOMEM;
 
-		for (d = dev_base; d; d = d->next) {
+		for_each_netdev(d) {
 			if (!sscanf(d->name, name, &i))
 				continue;
 			if (i < 0 || i >= max_netdevices)
@@ -964,7 +977,7 @@
 	rtnl_lock();
 	err = raw_notifier_chain_register(&netdev_chain, nb);
 	if (!err) {
-		for (dev = dev_base; dev; dev = dev->next) {
+		for_each_netdev(dev) {
 			nb->notifier_call(nb, NETDEV_REGISTER, dev);
 
 			if (dev->flags & IFF_UP)
@@ -2038,7 +2051,7 @@
 	 */
 
 	total = 0;
-	for (dev = dev_base; dev; dev = dev->next) {
+	for_each_netdev(dev) {
 		for (i = 0; i < NPROTO; i++) {
 			if (gifconf_list[i]) {
 				int done;
@@ -2070,26 +2083,28 @@
  *	This is invoked by the /proc filesystem handler to display a device
  *	in detail.
  */
-static struct net_device *dev_get_idx(loff_t pos)
-{
-	struct net_device *dev;
-	loff_t i;
-
-	for (i = 0, dev = dev_base; dev && i < pos; ++i, dev = dev->next);
-
-	return i == pos ? dev : NULL;
-}
-
 void *dev_seq_start(struct seq_file *seq, loff_t *pos)
 {
+	loff_t off;
+	struct net_device *dev;
+
 	read_lock(&dev_base_lock);
-	return *pos ? dev_get_idx(*pos - 1) : SEQ_START_TOKEN;
+	if (!*pos)
+		return SEQ_START_TOKEN;
+
+	off = 1;
+	for_each_netdev(dev)
+		if (off++ == *pos)
+			return dev;
+
+	return NULL;
 }
 
 void *dev_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 {
 	++*pos;
-	return v == SEQ_START_TOKEN ? dev_base : ((struct net_device *)v)->next;
+	return v == SEQ_START_TOKEN ?
+		first_net_device() : next_net_device((struct net_device *)v);
 }
 
 void dev_seq_stop(struct seq_file *seq, void *v)
@@ -3071,11 +3086,9 @@
 
 	set_bit(__LINK_STATE_PRESENT, &dev->state);
 
-	dev->next = NULL;
 	dev_init_scheduler(dev);
 	write_lock_bh(&dev_base_lock);
-	*dev_tail = dev;
-	dev_tail = &dev->next;
+	list_add_tail(&dev->dev_list, &dev_base_head);
 	hlist_add_head(&dev->name_hlist, head);
 	hlist_add_head(&dev->index_hlist, dev_index_hash(dev->ifindex));
 	dev_hold(dev);
@@ -3349,8 +3362,6 @@
 
 void unregister_netdevice(struct net_device *dev)
 {
-	struct net_device *d, **dp;
-
 	BUG_ON(dev_boot_phase);
 	ASSERT_RTNL();
 
@@ -3370,19 +3381,11 @@
 		dev_close(dev);
 
 	/* And unlink it from device chain. */
-	for (dp = &dev_base; (d = *dp) != NULL; dp = &d->next) {
-		if (d == dev) {
-			write_lock_bh(&dev_base_lock);
-			hlist_del(&dev->name_hlist);
-			hlist_del(&dev->index_hlist);
-			if (dev_tail == &dev->next)
-				dev_tail = dp;
-			*dp = d->next;
-			write_unlock_bh(&dev_base_lock);
-			break;
-		}
-	}
-	BUG_ON(!d);
+	write_lock_bh(&dev_base_lock);
+	list_del(&dev->dev_list);
+	hlist_del(&dev->name_hlist);
+	hlist_del(&dev->index_hlist);
+	write_unlock_bh(&dev_base_lock);
 
 	dev->reg_state = NETREG_UNREGISTERING;
 
diff --git a/net/core/dev_mcast.c b/net/core/dev_mcast.c
index 7d57bf7..5a54053 100644
--- a/net/core/dev_mcast.c
+++ b/net/core/dev_mcast.c
@@ -223,7 +223,7 @@
 	loff_t off = 0;
 
 	read_lock(&dev_base_lock);
-	for (dev = dev_base; dev; dev = dev->next) {
+	for_each_netdev(dev) {
 		if (off++ == *pos)
 			return dev;
 	}
@@ -232,9 +232,8 @@
 
 static void *dev_mc_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 {
-	struct net_device *dev = v;
 	++*pos;
-	return dev->next;
+	return next_net_device((struct net_device *)v);
 }
 
 static void dev_mc_seq_stop(struct seq_file *seq, void *v)
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index cec1111..8c971a2 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -539,13 +539,16 @@
 	int s_idx = cb->args[0];
 	struct net_device *dev;
 
-	for (dev=dev_base, idx=0; dev; dev = dev->next, idx++) {
+	idx = 0;
+	for_each_netdev(dev) {
 		if (idx < s_idx)
-			continue;
+			goto cont;
 		if (rtnl_fill_ifinfo(skb, dev, NULL, 0, RTM_NEWLINK,
 				     NETLINK_CB(cb->skb).pid,
 				     cb->nlh->nlmsg_seq, 0, NLM_F_MULTI) <= 0)
 			break;
+cont:
+		idx++;
 	}
 	cb->args[0] = idx;
 
diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c
index a205eaa..9fbe87c 100644
--- a/net/decnet/af_decnet.c
+++ b/net/decnet/af_decnet.c
@@ -721,7 +721,7 @@
 	struct sock *sk = sock->sk;
 	struct dn_scp *scp = DN_SK(sk);
 	struct sockaddr_dn *saddr = (struct sockaddr_dn *)uaddr;
-	struct net_device *dev;
+	struct net_device *dev, *ldev;
 	int rv;
 
 	if (addr_len != sizeof(struct sockaddr_dn))
@@ -746,14 +746,17 @@
 	if (!(saddr->sdn_flags & SDF_WILD)) {
 		if (dn_ntohs(saddr->sdn_nodeaddrl)) {
 			read_lock(&dev_base_lock);
-			for(dev = dev_base; dev; dev = dev->next) {
+			ldev = NULL;
+			for_each_netdev(dev) {
 				if (!dev->dn_ptr)
 					continue;
-				if (dn_dev_islocal(dev, dn_saddr2dn(saddr)))
+				if (dn_dev_islocal(dev, dn_saddr2dn(saddr))) {
+					ldev = dev;
 					break;
+				}
 			}
 			read_unlock(&dev_base_lock);
-			if (dev == NULL)
+			if (ldev == NULL)
 				return -EADDRNOTAVAIL;
 		}
 	}
diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c
index 5c2a995..764a56a 100644
--- a/net/decnet/dn_dev.c
+++ b/net/decnet/dn_dev.c
@@ -799,9 +799,10 @@
 	skip_ndevs = cb->args[0];
 	skip_naddr = cb->args[1];
 
-	for (dev = dev_base, idx = 0; dev; dev = dev->next, idx++) {
+	idx = 0;
+	for_each_netdev(dev) {
 		if (idx < skip_ndevs)
-			continue;
+			goto cont;
 		else if (idx > skip_ndevs) {
 			/* Only skip over addresses for first dev dumped
 			 * in this iteration (idx == skip_ndevs) */
@@ -809,18 +810,20 @@
 		}
 
 		if ((dn_db = dev->dn_ptr) == NULL)
-			continue;
+			goto cont;
 
 		for (ifa = dn_db->ifa_list, dn_idx = 0; ifa;
 		     ifa = ifa->ifa_next, dn_idx++) {
 			if (dn_idx < skip_naddr)
-				continue;
+				goto cont;
 
 			if (dn_nl_fill_ifaddr(skb, ifa, NETLINK_CB(cb->skb).pid,
 					      cb->nlh->nlmsg_seq, RTM_NEWADDR,
 					      NLM_F_MULTI) < 0)
 				goto done;
 		}
+cont:
+		idx++;
 	}
 done:
 	cb->args[0] = idx;
@@ -1296,7 +1299,7 @@
 	struct net_device *dev;
 
 	rtnl_lock();
-	for(dev = dev_base; dev; dev = dev->next)
+	for_each_netdev(dev)
 		dn_dev_down(dev);
 	rtnl_unlock();
 
@@ -1307,7 +1310,7 @@
 	struct net_device *dev;
 
 	rtnl_lock();
-	for(dev = dev_base; dev; dev = dev->next) {
+	for_each_netdev(dev) {
 		if (dev->flags & IFF_UP)
 			dn_dev_up(dev);
 	}
@@ -1325,62 +1328,56 @@
 }
 
 #ifdef CONFIG_PROC_FS
-static inline struct net_device *dn_dev_get_next(struct seq_file *seq, struct net_device *dev)
+static inline int is_dn_dev(struct net_device *dev)
 {
-	do {
-		dev = dev->next;
-	} while(dev && !dev->dn_ptr);
-
-	return dev;
-}
-
-static struct net_device *dn_dev_get_idx(struct seq_file *seq, loff_t pos)
-{
-	struct net_device *dev;
-
-	dev = dev_base;
-	if (dev && !dev->dn_ptr)
-		dev = dn_dev_get_next(seq, dev);
-	if (pos) {
-		while(dev && (dev = dn_dev_get_next(seq, dev)))
-			--pos;
-	}
-	return dev;
+	return dev->dn_ptr != NULL;
 }
 
 static void *dn_dev_seq_start(struct seq_file *seq, loff_t *pos)
 {
-	if (*pos) {
-		struct net_device *dev;
-		read_lock(&dev_base_lock);
-		dev = dn_dev_get_idx(seq, *pos - 1);
-		if (dev == NULL)
-			read_unlock(&dev_base_lock);
-		return dev;
+	int i;
+	struct net_device *dev;
+
+	read_lock(&dev_base_lock);
+
+	if (*pos == 0)
+		return SEQ_START_TOKEN;
+
+	i = 1;
+	for_each_netdev(dev) {
+		if (!is_dn_dev(dev))
+			continue;
+
+		if (i++ == *pos)
+			return dev;
 	}
-	return SEQ_START_TOKEN;
+
+	return NULL;
 }
 
 static void *dn_dev_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 {
-	struct net_device *dev = v;
-	loff_t one = 1;
+	struct net_device *dev;
 
-	if (v == SEQ_START_TOKEN) {
-		dev = dn_dev_seq_start(seq, &one);
-	} else {
-		dev = dn_dev_get_next(seq, dev);
-		if (dev == NULL)
-			read_unlock(&dev_base_lock);
-	}
 	++*pos;
-	return dev;
+
+	dev = (struct net_device *)v;
+	if (v == SEQ_START_TOKEN)
+		dev = net_device_entry(&dev_base_head);
+
+	for_each_netdev_continue(dev) {
+		if (!is_dn_dev(dev))
+			continue;
+
+		return dev;
+	}
+
+	return NULL;
 }
 
 static void dn_dev_seq_stop(struct seq_file *seq, void *v)
 {
-	if (v && v != SEQ_START_TOKEN)
-		read_unlock(&dev_base_lock);
+	read_unlock(&dev_base_lock);
 }
 
 static char *dn_type2asc(char type)
diff --git a/net/decnet/dn_fib.c b/net/decnet/dn_fib.c
index 310a862..d2bc19d 100644
--- a/net/decnet/dn_fib.c
+++ b/net/decnet/dn_fib.c
@@ -602,7 +602,7 @@
 
 	/* Scan device list */
 	read_lock(&dev_base_lock);
-	for(dev = dev_base; dev; dev = dev->next) {
+	for_each_netdev(dev) {
 		dn_db = dev->dn_ptr;
 		if (dn_db == NULL)
 			continue;
diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c
index 5d7337b..a8bf106 100644
--- a/net/decnet/dn_route.c
+++ b/net/decnet/dn_route.c
@@ -886,7 +886,7 @@
 			    .iif = loopback_dev.ifindex,
 			    .oif = oldflp->oif };
 	struct dn_route *rt = NULL;
-	struct net_device *dev_out = NULL;
+	struct net_device *dev_out = NULL, *dev;
 	struct neighbour *neigh = NULL;
 	unsigned hash;
 	unsigned flags = 0;
@@ -925,15 +925,17 @@
 			goto out;
 		}
 		read_lock(&dev_base_lock);
-		for(dev_out = dev_base; dev_out; dev_out = dev_out->next) {
-			if (!dev_out->dn_ptr)
+		for_each_netdev(dev) {
+			if (!dev->dn_ptr)
 				continue;
-			if (!dn_dev_islocal(dev_out, oldflp->fld_src))
+			if (!dn_dev_islocal(dev, oldflp->fld_src))
 				continue;
-			if ((dev_out->flags & IFF_LOOPBACK) &&
+			if ((dev->flags & IFF_LOOPBACK) &&
 			    oldflp->fld_dst &&
-			    !dn_dev_islocal(dev_out, oldflp->fld_dst))
+			    !dn_dev_islocal(dev, oldflp->fld_dst))
 				continue;
+
+			dev_out = dev;
 			break;
 		}
 		read_unlock(&dev_base_lock);
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 088888d..7f95e6e 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -910,7 +910,7 @@
 	 */
 	read_lock(&dev_base_lock);
 	rcu_read_lock();
-	for (dev = dev_base; dev; dev = dev->next) {
+	for_each_netdev(dev) {
 		if ((in_dev = __in_dev_get_rcu(dev)) == NULL)
 			continue;
 
@@ -989,7 +989,7 @@
 
 	read_lock(&dev_base_lock);
 	rcu_read_lock();
-	for (dev = dev_base; dev; dev = dev->next) {
+	for_each_netdev(dev) {
 		if ((in_dev = __in_dev_get_rcu(dev))) {
 			addr = confirm_addr_indev(in_dev, dst, local, scope);
 			if (addr)
@@ -1182,23 +1182,26 @@
 	int s_ip_idx, s_idx = cb->args[0];
 
 	s_ip_idx = ip_idx = cb->args[1];
-	for (dev = dev_base, idx = 0; dev; dev = dev->next, idx++) {
+	idx = 0;
+	for_each_netdev(dev) {
 		if (idx < s_idx)
-			continue;
+			goto cont;
 		if (idx > s_idx)
 			s_ip_idx = 0;
 		if ((in_dev = __in_dev_get_rtnl(dev)) == NULL)
-			continue;
+			goto cont;
 
 		for (ifa = in_dev->ifa_list, ip_idx = 0; ifa;
 		     ifa = ifa->ifa_next, ip_idx++) {
 			if (ip_idx < s_ip_idx)
-				continue;
+				goto cont;
 			if (inet_fill_ifaddr(skb, ifa, NETLINK_CB(cb->skb).pid,
 					     cb->nlh->nlmsg_seq,
 					     RTM_NEWADDR, NLM_F_MULTI) <= 0)
 				goto done;
 		}
+cont:
+		idx++;
 	}
 
 done:
@@ -1243,7 +1246,7 @@
 	ipv4_devconf_dflt.forwarding = on;
 
 	read_lock(&dev_base_lock);
-	for (dev = dev_base; dev; dev = dev->next) {
+	for_each_netdev(dev) {
 		struct in_device *in_dev;
 		rcu_read_lock();
 		in_dev = __in_dev_get_rcu(dev);
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c
index 2506021..f4dd474 100644
--- a/net/ipv4/igmp.c
+++ b/net/ipv4/igmp.c
@@ -2288,9 +2288,8 @@
 	struct ip_mc_list *im = NULL;
 	struct igmp_mc_iter_state *state = igmp_mc_seq_private(seq);
 
-	for (state->dev = dev_base, state->in_dev = NULL;
-	     state->dev;
-	     state->dev = state->dev->next) {
+	state->in_dev = NULL;
+	for_each_netdev(state->dev) {
 		struct in_device *in_dev;
 		in_dev = in_dev_get(state->dev);
 		if (!in_dev)
@@ -2316,7 +2315,7 @@
 			read_unlock(&state->in_dev->mc_list_lock);
 			in_dev_put(state->in_dev);
 		}
-		state->dev = state->dev->next;
+		state->dev = next_net_device(state->dev);
 		if (!state->dev) {
 			state->in_dev = NULL;
 			break;
@@ -2450,9 +2449,9 @@
 	struct ip_mc_list *im = NULL;
 	struct igmp_mcf_iter_state *state = igmp_mcf_seq_private(seq);
 
-	for (state->dev = dev_base, state->idev = NULL, state->im = NULL;
-	     state->dev;
-	     state->dev = state->dev->next) {
+	state->idev = NULL;
+	state->im = NULL;
+	for_each_netdev(state->dev) {
 		struct in_device *idev;
 		idev = in_dev_get(state->dev);
 		if (unlikely(idev == NULL))
@@ -2488,7 +2487,7 @@
 				read_unlock(&state->idev->mc_list_lock);
 				in_dev_put(state->idev);
 			}
-			state->dev = state->dev->next;
+			state->dev = next_net_device(state->dev);
 			if (!state->dev) {
 				state->idev = NULL;
 				goto out;
diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c
index 597c800..342ca8d 100644
--- a/net/ipv4/ipconfig.c
+++ b/net/ipv4/ipconfig.c
@@ -192,7 +192,7 @@
 	if (dev_change_flags(&loopback_dev, loopback_dev.flags | IFF_UP) < 0)
 		printk(KERN_ERR "IP-Config: Failed to open %s\n", loopback_dev.name);
 
-	for (dev = dev_base; dev; dev = dev->next) {
+	for_each_netdev(dev) {
 		if (dev == &loopback_dev)
 			continue;
 		if (user_dev_name[0] ? !strcmp(dev->name, user_dev_name) :
diff --git a/net/ipv4/netfilter/nf_nat_proto_gre.c b/net/ipv4/netfilter/nf_nat_proto_gre.c
index e5a34c1..c3908bc 100644
--- a/net/ipv4/netfilter/nf_nat_proto_gre.c
+++ b/net/ipv4/netfilter/nf_nat_proto_gre.c
@@ -72,6 +72,11 @@
 	__be16 *keyptr;
 	unsigned int min, i, range_size;
 
+	/* If there is no master conntrack we are not PPTP,
+	   do not change tuples */
+	if (!conntrack->master)
+		return 0;
+
 	if (maniptype == IP_NAT_MANIP_SRC)
 		keyptr = &tuple->src.u.gre.key;
 	else
@@ -122,18 +127,9 @@
 	if (maniptype != IP_NAT_MANIP_DST)
 		return 1;
 	switch (greh->version) {
-	case 0:
-		if (!greh->key) {
-			DEBUGP("can't nat GRE w/o key\n");
-			break;
-		}
-		if (greh->csum) {
-			/* FIXME: Never tested this code... */
-			nf_proto_csum_replace4(gre_csum(greh), *pskb,
-					       *(gre_key(greh)),
-					       tuple->dst.u.gre.key, 0);
-		}
-		*(gre_key(greh)) = tuple->dst.u.gre.key;
+	case GRE_VERSION_1701:
+		/* We do not currently NAT any GREv0 packets.
+		 * Try to behave like "nf_nat_proto_unknown" */
 		break;
 	case GRE_VERSION_PPTP:
 		DEBUGP("call_id -> 0x%04x\n", ntohs(tuple->dst.u.gre.key));
diff --git a/net/ipv4/netfilter/nf_nat_rule.c b/net/ipv4/netfilter/nf_nat_rule.c
index 2a28339..2534f71 100644
--- a/net/ipv4/netfilter/nf_nat_rule.c
+++ b/net/ipv4/netfilter/nf_nat_rule.c
@@ -226,10 +226,6 @@
 		printk("DNAT: multiple ranges no longer supported\n");
 		return 0;
 	}
-	if (mr->range[0].flags & IP_NAT_RANGE_PROTO_RANDOM) {
-		printk("DNAT: port randomization not supported\n");
-		return 0;
-	}
 	return 1;
 }
 
diff --git a/net/ipv4/netfilter/nf_nat_sip.c b/net/ipv4/netfilter/nf_nat_sip.c
index bfd88e4..fac97cf 100644
--- a/net/ipv4/netfilter/nf_nat_sip.c
+++ b/net/ipv4/netfilter/nf_nat_sip.c
@@ -222,6 +222,29 @@
 	return mangle_content_len(pskb, ctinfo, ct, dptr);
 }
 
+static void ip_nat_sdp_expect(struct nf_conn *ct,
+			      struct nf_conntrack_expect *exp)
+{
+	struct nf_nat_range range;
+
+	/* This must be a fresh one. */
+	BUG_ON(ct->status & IPS_NAT_DONE_MASK);
+
+	/* Change src to where master sends to */
+	range.flags = IP_NAT_RANGE_MAP_IPS;
+	range.min_ip = range.max_ip
+		= ct->master->tuplehash[!exp->dir].tuple.dst.u3.ip;
+	/* hook doesn't matter, but it has to do source manip */
+	nf_nat_setup_info(ct, &range, NF_IP_POST_ROUTING);
+
+	/* For DST manip, map port here to where it's expected. */
+	range.flags = (IP_NAT_RANGE_MAP_IPS | IP_NAT_RANGE_PROTO_SPECIFIED);
+	range.min = range.max = exp->saved_proto;
+	range.min_ip = range.max_ip = exp->saved_ip;
+	/* hook doesn't matter, but it has to do destination manip */
+	nf_nat_setup_info(ct, &range, NF_IP_PRE_ROUTING);
+}
+
 /* So, this packet has hit the connection tracking matching code.
    Mangle it, and change the expectation to match the new version. */
 static unsigned int ip_nat_sdp(struct sk_buff **pskb,
@@ -239,13 +262,14 @@
 	/* Connection will come from reply */
 	newip = ct->tuplehash[!dir].tuple.dst.u3.ip;
 
+	exp->saved_ip = exp->tuple.dst.u3.ip;
 	exp->tuple.dst.u3.ip = newip;
 	exp->saved_proto.udp.port = exp->tuple.dst.u.udp.port;
 	exp->dir = !dir;
 
 	/* When you see the packet, we need to NAT it the same as the
 	   this one. */
-	exp->expectfn = nf_nat_follow_master;
+	exp->expectfn = ip_nat_sdp_expect;
 
 	/* Try to get same port: if not, try to change it. */
 	for (port = ntohs(exp->saved_proto.udp.port); port != 0; port++) {
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index d6e4886..8b124ea 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -1760,8 +1760,7 @@
 	tcp_clear_retrans(tp);
 	inet_csk_delack_init(sk);
 	tcp_init_send_head(sk);
-	tp->rx_opt.saw_tstamp = 0;
-	tcp_sack_reset(&tp->rx_opt);
+	memset(&tp->rx_opt, 0, sizeof(tp->rx_opt));
 	__sk_dst_reset(sk);
 
 	BUG_TRAP(!inet->num || icsk->icsk_bind_hash);
diff --git a/net/ipv4/tcp_highspeed.c b/net/ipv4/tcp_highspeed.c
index a291097..43d624e5 100644
--- a/net/ipv4/tcp_highspeed.c
+++ b/net/ipv4/tcp_highspeed.c
@@ -97,10 +97,6 @@
 	u32	ai;
 };
 
-static int max_ssthresh = 100;
-module_param(max_ssthresh, int, 0644);
-MODULE_PARM_DESC(max_ssthresh, "limited slow start threshold (RFC3742)");
-
 static void hstcp_init(struct sock *sk)
 {
 	struct tcp_sock *tp = tcp_sk(sk);
@@ -122,23 +118,9 @@
 	if (!tcp_is_cwnd_limited(sk, in_flight))
 		return;
 
-	if (tp->snd_cwnd <= tp->snd_ssthresh) {
-		/* RFC3742: limited slow start
-		 * the window is increased by 1/K MSS for each arriving ACK,
-		 * for K = int(cwnd/(0.5 max_ssthresh))
-		 */
-		if (max_ssthresh > 0 && tp->snd_cwnd > max_ssthresh) {
-			u32 k = max(tp->snd_cwnd / (max_ssthresh >> 1), 1U);
-			if (++tp->snd_cwnd_cnt >= k) {
-				if (tp->snd_cwnd < tp->snd_cwnd_clamp)
-					tp->snd_cwnd++;
-				tp->snd_cwnd_cnt = 0;
-			}
-		} else {
-			if (tp->snd_cwnd < tp->snd_cwnd_clamp)
-				tp->snd_cwnd++;
-		}
-	} else {
+	if (tp->snd_cwnd <= tp->snd_ssthresh)
+		tcp_slow_start(tp);
+	else {
 		/* Update AIMD parameters.
 		 *
 		 * We want to guarantee that:
diff --git a/net/ipv4/tcp_yeah.h b/net/ipv4/tcp_yeah.h
deleted file mode 100644
index ed3b719..0000000
--- a/net/ipv4/tcp_yeah.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/skbuff.h>
-#include <linux/inet_diag.h>
-#include <asm/div64.h>
-
-#include <net/tcp.h>
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 3452433..d02685c 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -449,7 +449,7 @@
 	struct inet6_dev *idev;
 
 	read_lock(&dev_base_lock);
-	for (dev=dev_base; dev; dev=dev->next) {
+	for_each_netdev(dev) {
 		rcu_read_lock();
 		idev = __in6_dev_get(dev);
 		if (idev) {
@@ -911,7 +911,7 @@
 	read_lock(&dev_base_lock);
 	rcu_read_lock();
 
-	for (dev = dev_base; dev; dev=dev->next) {
+	for_each_netdev(dev) {
 		struct inet6_dev *idev;
 		struct inet6_ifaddr *ifa;
 
@@ -2064,7 +2064,7 @@
 		return;
 	}
 
-	for (dev = dev_base; dev != NULL; dev = dev->next) {
+	for_each_netdev(dev) {
 		struct in_device * in_dev = __in_dev_get_rtnl(dev);
 		if (in_dev && (dev->flags & IFF_UP)) {
 			struct in_ifaddr * ifa;
@@ -2225,7 +2225,7 @@
 			return;
 	}
 	/* then try to inherit it from any device */
-	for (link_dev = dev_base; link_dev; link_dev = link_dev->next) {
+	for_each_netdev(link_dev) {
 		if (!ipv6_inherit_linklocal(idev, link_dev))
 			return;
 	}
@@ -3257,14 +3257,15 @@
 	s_idx = cb->args[0];
 	s_ip_idx = ip_idx = cb->args[1];
 
-	for (dev = dev_base, idx = 0; dev; dev = dev->next, idx++) {
+	idx = 0;
+	for_each_netdev(dev) {
 		if (idx < s_idx)
-			continue;
+			goto cont;
 		if (idx > s_idx)
 			s_ip_idx = 0;
 		ip_idx = 0;
 		if ((idev = in6_dev_get(dev)) == NULL)
-			continue;
+			goto cont;
 		read_lock_bh(&idev->lock);
 		switch (type) {
 		case UNICAST_ADDR:
@@ -3311,6 +3312,8 @@
 		}
 		read_unlock_bh(&idev->lock);
 		in6_dev_put(idev);
+cont:
+		idx++;
 	}
 done:
 	if (err <= 0) {
@@ -3575,16 +3578,19 @@
 	struct inet6_dev *idev;
 
 	read_lock(&dev_base_lock);
-	for (dev=dev_base, idx=0; dev; dev = dev->next, idx++) {
+	idx = 0;
+	for_each_netdev(dev) {
 		if (idx < s_idx)
-			continue;
+			goto cont;
 		if ((idev = in6_dev_get(dev)) == NULL)
-			continue;
+			goto cont;
 		err = inet6_fill_ifinfo(skb, idev, NETLINK_CB(cb->skb).pid,
 				cb->nlh->nlmsg_seq, RTM_NEWLINK, NLM_F_MULTI);
 		in6_dev_put(idev);
 		if (err <= 0)
 			break;
+cont:
+		idx++;
 	}
 	read_unlock(&dev_base_lock);
 	cb->args[0] = idx;
@@ -4247,7 +4253,7 @@
 	 *	clean dev list.
 	 */
 
-	for (dev=dev_base; dev; dev=dev->next) {
+	for_each_netdev(dev) {
 		if ((idev = __in6_dev_get(dev)) == NULL)
 			continue;
 		addrconf_ifdown(dev, 1);
diff --git a/net/ipv6/anycast.c b/net/ipv6/anycast.c
index 09117d6..9b81264 100644
--- a/net/ipv6/anycast.c
+++ b/net/ipv6/anycast.c
@@ -423,14 +423,18 @@
  */
 int ipv6_chk_acast_addr(struct net_device *dev, struct in6_addr *addr)
 {
+	int found = 0;
+
 	if (dev)
 		return ipv6_chk_acast_dev(dev, addr);
 	read_lock(&dev_base_lock);
-	for (dev=dev_base; dev; dev=dev->next)
-		if (ipv6_chk_acast_dev(dev, addr))
+	for_each_netdev(dev)
+		if (ipv6_chk_acast_dev(dev, addr)) {
+			found = 1;
 			break;
+		}
 	read_unlock(&dev_base_lock);
-	return dev != 0;
+	return found;
 }
 
 
@@ -447,9 +451,8 @@
 	struct ifacaddr6 *im = NULL;
 	struct ac6_iter_state *state = ac6_seq_private(seq);
 
-	for (state->dev = dev_base, state->idev = NULL;
-	     state->dev;
-	     state->dev = state->dev->next) {
+	state->idev = NULL;
+	for_each_netdev(state->dev) {
 		struct inet6_dev *idev;
 		idev = in6_dev_get(state->dev);
 		if (!idev)
@@ -476,7 +479,7 @@
 			read_unlock_bh(&state->idev->lock);
 			in6_dev_put(state->idev);
 		}
-		state->dev = state->dev->next;
+		state->dev = next_net_device(state->dev);
 		if (!state->dev) {
 			state->idev = NULL;
 			break;
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
index 6c27589..3e308fb 100644
--- a/net/ipv6/mcast.c
+++ b/net/ipv6/mcast.c
@@ -2331,9 +2331,8 @@
 	struct ifmcaddr6 *im = NULL;
 	struct igmp6_mc_iter_state *state = igmp6_mc_seq_private(seq);
 
-	for (state->dev = dev_base, state->idev = NULL;
-	     state->dev;
-	     state->dev = state->dev->next) {
+	state->idev = NULL;
+	for_each_netdev(state->dev) {
 		struct inet6_dev *idev;
 		idev = in6_dev_get(state->dev);
 		if (!idev)
@@ -2360,7 +2359,7 @@
 			read_unlock_bh(&state->idev->lock);
 			in6_dev_put(state->idev);
 		}
-		state->dev = state->dev->next;
+		state->dev = next_net_device(state->dev);
 		if (!state->dev) {
 			state->idev = NULL;
 			break;
@@ -2475,9 +2474,9 @@
 	struct ifmcaddr6 *im = NULL;
 	struct igmp6_mcf_iter_state *state = igmp6_mcf_seq_private(seq);
 
-	for (state->dev = dev_base, state->idev = NULL, state->im = NULL;
-	     state->dev;
-	     state->dev = state->dev->next) {
+	state->idev = NULL;
+	state->im = NULL;
+	for_each_netdev(state->dev) {
 		struct inet6_dev *idev;
 		idev = in6_dev_get(state->dev);
 		if (unlikely(idev == NULL))
@@ -2513,7 +2512,7 @@
 				read_unlock_bh(&state->idev->lock);
 				in6_dev_put(state->idev);
 			}
-			state->dev = state->dev->next;
+			state->dev = next_net_device(state->dev);
 			if (!state->dev) {
 				state->idev = NULL;
 				goto out;
diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c
index e84c924..d9e9ddb 100644
--- a/net/iucv/af_iucv.c
+++ b/net/iucv/af_iucv.c
@@ -45,7 +45,8 @@
 static void iucv_callback_rx(struct iucv_path *, struct iucv_message *);
 static void iucv_callback_txdone(struct iucv_path *, struct iucv_message *);
 static void iucv_callback_connack(struct iucv_path *, u8 ipuser[16]);
-static int iucv_callback_connreq(struct iucv_path *, u8 ipvmid[8], u8 ipuser[16]);
+static int iucv_callback_connreq(struct iucv_path *, u8 ipvmid[8],
+				 u8 ipuser[16]);
 static void iucv_callback_connrej(struct iucv_path *, u8 ipuser[16]);
 
 static struct iucv_sock_list iucv_sk_list = {
@@ -147,11 +148,12 @@
 	unsigned char user_data[16];
 	struct iucv_sock *iucv = iucv_sk(sk);
 	int err;
+	unsigned long timeo;
 
 	iucv_sock_clear_timer(sk);
 	lock_sock(sk);
 
-	switch(sk->sk_state) {
+	switch (sk->sk_state) {
 	case IUCV_LISTEN:
 		iucv_sock_cleanup_listen(sk);
 		break;
@@ -159,6 +161,21 @@
 	case IUCV_CONNECTED:
 	case IUCV_DISCONN:
 		err = 0;
+
+		sk->sk_state = IUCV_CLOSING;
+		sk->sk_state_change(sk);
+
+		if (!skb_queue_empty(&iucv->send_skb_q)) {
+			if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime)
+				timeo = sk->sk_lingertime;
+			else
+				timeo = IUCV_DISCONN_TIMEOUT;
+			err = iucv_sock_wait_state(sk, IUCV_CLOSED, 0, timeo);
+		}
+
+		sk->sk_state = IUCV_CLOSED;
+		sk->sk_state_change(sk);
+
 		if (iucv->path) {
 			low_nmcpy(user_data, iucv->src_name);
 			high_nmcpy(user_data, iucv->dst_name);
@@ -168,12 +185,11 @@
 			iucv->path = NULL;
 		}
 
-		sk->sk_state = IUCV_CLOSED;
-		sk->sk_state_change(sk);
 		sk->sk_err = ECONNRESET;
 		sk->sk_state_change(sk);
 
 		skb_queue_purge(&iucv->send_skb_q);
+		skb_queue_purge(&iucv->backlog_skb_q);
 
 		sock_set_flag(sk, SOCK_ZAPPED);
 		break;
@@ -204,6 +220,7 @@
 	sock_init_data(sock, sk);
 	INIT_LIST_HEAD(&iucv_sk(sk)->accept_q);
 	skb_queue_head_init(&iucv_sk(sk)->send_skb_q);
+	skb_queue_head_init(&iucv_sk(sk)->backlog_skb_q);
 	iucv_sk(sk)->send_tag = 0;
 
 	sk->sk_destruct = iucv_sock_destruct;
@@ -276,7 +293,7 @@
 	struct iucv_sock *isk, *n;
 	struct sock *sk;
 
-	list_for_each_entry_safe(isk, n, &iucv_sk(parent)->accept_q, accept_q){
+	list_for_each_entry_safe(isk, n, &iucv_sk(parent)->accept_q, accept_q) {
 		sk = (struct sock *) isk;
 		lock_sock(sk);
 
@@ -510,7 +527,7 @@
 	long timeo;
 	int err = 0;
 
-	lock_sock(sk);
+	lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
 
 	if (sk->sk_state != IUCV_LISTEN) {
 		err = -EBADFD;
@@ -521,7 +538,7 @@
 
 	/* Wait for an incoming connection */
 	add_wait_queue_exclusive(sk->sk_sleep, &wait);
-	while (!(nsk = iucv_accept_dequeue(sk, newsock))){
+	while (!(nsk = iucv_accept_dequeue(sk, newsock))) {
 		set_current_state(TASK_INTERRUPTIBLE);
 		if (!timeo) {
 			err = -EAGAIN;
@@ -530,7 +547,7 @@
 
 		release_sock(sk);
 		timeo = schedule_timeout(timeo);
-		lock_sock(sk);
+		lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
 
 		if (sk->sk_state != IUCV_LISTEN) {
 			err = -EBADFD;
@@ -602,13 +619,13 @@
 		goto out;
 	}
 
-	if (sk->sk_state == IUCV_CONNECTED){
-		if(!(skb = sock_alloc_send_skb(sk, len,
-				       msg->msg_flags & MSG_DONTWAIT,
-				       &err)))
-			return err;
+	if (sk->sk_state == IUCV_CONNECTED) {
+		if (!(skb = sock_alloc_send_skb(sk, len,
+						msg->msg_flags & MSG_DONTWAIT,
+						&err)))
+			goto out;
 
-		if (memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len)){
+		if (memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len)) {
 			err = -EFAULT;
 			goto fail;
 		}
@@ -647,10 +664,16 @@
 {
 	int noblock = flags & MSG_DONTWAIT;
 	struct sock *sk = sock->sk;
+	struct iucv_sock *iucv = iucv_sk(sk);
 	int target, copied = 0;
-	struct sk_buff *skb;
+	struct sk_buff *skb, *rskb, *cskb;
 	int err = 0;
 
+	if ((sk->sk_state == IUCV_DISCONN || sk->sk_state == IUCV_SEVERED) &&
+		skb_queue_empty(&iucv->backlog_skb_q) &&
+		skb_queue_empty(&sk->sk_receive_queue))
+		return 0;
+
 	if (flags & (MSG_OOB))
 		return -EOPNOTSUPP;
 
@@ -665,10 +688,12 @@
 
 	copied = min_t(unsigned int, skb->len, len);
 
-	if (memcpy_toiovec(msg->msg_iov, skb->data, copied)) {
+	cskb = skb;
+	if (memcpy_toiovec(msg->msg_iov, cskb->data, copied)) {
 		skb_queue_head(&sk->sk_receive_queue, skb);
 		if (copied == 0)
 			return -EFAULT;
+		goto done;
 	}
 
 	len -= copied;
@@ -683,6 +708,18 @@
 		}
 
 		kfree_skb(skb);
+
+		/* Queue backlog skbs */
+		rskb = skb_dequeue(&iucv_sk(sk)->backlog_skb_q);
+		while (rskb) {
+			if (sock_queue_rcv_skb(sk, rskb)) {
+				skb_queue_head(&iucv_sk(sk)->backlog_skb_q,
+						rskb);
+				break;
+			} else {
+				rskb = skb_dequeue(&iucv_sk(sk)->backlog_skb_q);
+			}
+		}
 	} else
 		skb_queue_head(&sk->sk_receive_queue, skb);
 
@@ -695,7 +732,7 @@
 	struct iucv_sock *isk, *n;
 	struct sock *sk;
 
-	list_for_each_entry_safe(isk, n, &iucv_sk(parent)->accept_q, accept_q){
+	list_for_each_entry_safe(isk, n, &iucv_sk(parent)->accept_q, accept_q) {
 		sk = (struct sock *) isk;
 
 		if (sk->sk_state == IUCV_CONNECTED)
@@ -726,12 +763,15 @@
 		mask |= POLLHUP;
 
 	if (!skb_queue_empty(&sk->sk_receive_queue) ||
-			(sk->sk_shutdown & RCV_SHUTDOWN))
+	    (sk->sk_shutdown & RCV_SHUTDOWN))
 		mask |= POLLIN | POLLRDNORM;
 
 	if (sk->sk_state == IUCV_CLOSED)
 		mask |= POLLHUP;
 
+	if (sk->sk_state == IUCV_DISCONN || sk->sk_state == IUCV_SEVERED)
+		mask |= POLLIN;
+
 	if (sock_writeable(sk))
 		mask |= POLLOUT | POLLWRNORM | POLLWRBAND;
 	else
@@ -754,7 +794,7 @@
 		return -EINVAL;
 
 	lock_sock(sk);
-	switch(sk->sk_state) {
+	switch (sk->sk_state) {
 	case IUCV_CLOSED:
 		err = -ENOTCONN;
 		goto fail;
@@ -770,7 +810,7 @@
 		err = iucv_message_send(iucv->path, &txmsg, IUCV_IPRMDATA, 0,
 					(void *) prmmsg, 8);
 		if (err) {
-			switch(err) {
+			switch (err) {
 			case 1:
 				err = -ENOTCONN;
 				break;
@@ -817,13 +857,6 @@
 		iucv_sk(sk)->path = NULL;
 	}
 
-	if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime){
-		lock_sock(sk);
-		err = iucv_sock_wait_state(sk, IUCV_CLOSED, 0,
-					   sk->sk_lingertime);
-		release_sock(sk);
-	}
-
 	sock_orphan(sk);
 	iucv_sock_kill(sk);
 	return err;
@@ -880,7 +913,7 @@
 
 	/* Create the new socket */
 	nsk = iucv_sock_alloc(NULL, SOCK_STREAM, GFP_ATOMIC);
-	if (!nsk){
+	if (!nsk) {
 		err = iucv_path_sever(path, user_data);
 		goto fail;
 	}
@@ -903,7 +936,7 @@
 
 	path->msglim = IUCV_QUEUELEN_DEFAULT;
 	err = iucv_path_accept(path, &af_iucv_handler, nuser_data, nsk);
-	if (err){
+	if (err) {
 		err = iucv_path_sever(path, user_data);
 		goto fail;
 	}
@@ -927,18 +960,53 @@
 	sk->sk_state_change(sk);
 }
 
+static int iucv_fragment_skb(struct sock *sk, struct sk_buff *skb, int len,
+			     struct sk_buff_head *fragmented_skb_q)
+{
+	int dataleft, size, copied = 0;
+	struct sk_buff *nskb;
+
+	dataleft = len;
+	while (dataleft) {
+		if (dataleft >= sk->sk_rcvbuf / 4)
+			size = sk->sk_rcvbuf / 4;
+		else
+			size = dataleft;
+
+		nskb = alloc_skb(size, GFP_ATOMIC | GFP_DMA);
+		if (!nskb)
+			return -ENOMEM;
+
+		memcpy(nskb->data, skb->data + copied, size);
+		copied += size;
+		dataleft -= size;
+
+		skb_reset_transport_header(nskb);
+		skb_reset_network_header(nskb);
+		nskb->len = size;
+
+		skb_queue_tail(fragmented_skb_q, nskb);
+	}
+
+	return 0;
+}
+
 static void iucv_callback_rx(struct iucv_path *path, struct iucv_message *msg)
 {
 	struct sock *sk = path->private;
-	struct sk_buff *skb;
+	struct iucv_sock *iucv = iucv_sk(sk);
+	struct sk_buff *skb, *fskb;
+	struct sk_buff_head fragmented_skb_q;
 	int rc;
 
+	skb_queue_head_init(&fragmented_skb_q);
+
 	if (sk->sk_shutdown & RCV_SHUTDOWN)
 		return;
 
 	skb = alloc_skb(msg->length, GFP_ATOMIC | GFP_DMA);
 	if (!skb) {
-		iucv_message_reject(path, msg);
+		iucv_path_sever(path, NULL);
 		return;
 	}
 
@@ -952,14 +1020,39 @@
 			kfree_skb(skb);
 			return;
 		}
-
-		skb_reset_transport_header(skb);
-		skb_reset_network_header(skb);
-		skb->len = msg->length;
+		if (skb->truesize >= sk->sk_rcvbuf / 4) {
+			rc = iucv_fragment_skb(sk, skb, msg->length,
+					       &fragmented_skb_q);
+			kfree_skb(skb);
+			skb = NULL;
+			if (rc) {
+				iucv_path_sever(path, NULL);
+				return;
+			}
+		} else {
+			skb_reset_transport_header(skb);
+			skb_reset_network_header(skb);
+			skb->len = msg->length;
+		}
+	}
+	/* Queue the fragmented skb */
+	fskb = skb_dequeue(&fragmented_skb_q);
+	while (fskb) {
+		if (!skb_queue_empty(&iucv->backlog_skb_q))
+			skb_queue_tail(&iucv->backlog_skb_q, fskb);
+		else if (sock_queue_rcv_skb(sk, fskb))
+			skb_queue_tail(&iucv_sk(sk)->backlog_skb_q, fskb);
+		fskb = skb_dequeue(&fragmented_skb_q);
 	}
 
-	if (sock_queue_rcv_skb(sk, skb))
-		kfree_skb(skb);
+	/* Queue the original skb if it exists (was not fragmented) */
+	if (skb) {
+		if (!skb_queue_empty(&iucv->backlog_skb_q))
+			skb_queue_tail(&iucv_sk(sk)->backlog_skb_q, skb);
+		else if (sock_queue_rcv_skb(sk, skb))
+			skb_queue_tail(&iucv_sk(sk)->backlog_skb_q, skb);
+	}
+
 }
 
 static void iucv_callback_txdone(struct iucv_path *path,
@@ -971,17 +1064,27 @@
 	struct sk_buff *list_skb = list->next;
 	unsigned long flags;
 
-	spin_lock_irqsave(&list->lock, flags);
+	if (list_skb) {
+		spin_lock_irqsave(&list->lock, flags);
 
-	do {
-		this = list_skb;
-		list_skb = list_skb->next;
-	} while (memcmp(&msg->tag, this->cb, 4));
+		do {
+			this = list_skb;
+			list_skb = list_skb->next;
+		} while (memcmp(&msg->tag, this->cb, 4) && list_skb);
 
-	spin_unlock_irqrestore(&list->lock, flags);
+		spin_unlock_irqrestore(&list->lock, flags);
 
-	skb_unlink(this, &iucv_sk(sk)->send_skb_q);
-	kfree_skb(this);
+		skb_unlink(this, &iucv_sk(sk)->send_skb_q);
+		kfree_skb(this);
+	}
+
+	if (sk->sk_state == IUCV_CLOSING) {
+		if (skb_queue_empty(&iucv_sk(sk)->send_skb_q)) {
+			sk->sk_state = IUCV_CLOSED;
+			sk->sk_state_change(sk);
+		}
+	}
+
 }
 
 static void iucv_callback_connrej(struct iucv_path *path, u8 ipuser[16])
@@ -1022,7 +1125,7 @@
 	.create	= iucv_sock_create,
 };
 
-static int afiucv_init(void)
+static int __init afiucv_init(void)
 {
 	int err;
 
diff --git a/net/iucv/iucv.c b/net/iucv/iucv.c
index 903bdb6..fb3faf7 100644
--- a/net/iucv/iucv.c
+++ b/net/iucv/iucv.c
@@ -32,7 +32,6 @@
 
 #include <linux/module.h>
 #include <linux/moduleparam.h>
-
 #include <linux/spinlock.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
@@ -69,7 +68,7 @@
 #define IUCV_IPNORPY	0x10
 #define IUCV_IPALL	0x80
 
-static int iucv_bus_match (struct device *dev, struct device_driver *drv)
+static int iucv_bus_match(struct device *dev, struct device_driver *drv)
 {
 	return 0;
 }
@@ -78,8 +77,11 @@
 	.name = "iucv",
 	.match = iucv_bus_match,
 };
+EXPORT_SYMBOL(iucv_bus);
 
 struct device *iucv_root;
+EXPORT_SYMBOL(iucv_root);
+
 static int iucv_available;
 
 /* General IUCV interrupt structure */
@@ -405,7 +407,7 @@
 	rc = iucv_call_b2f0(IUCV_DECLARE_BUFFER, parm);
 	if (rc) {
 		char *err = "Unknown";
-		switch(rc) {
+		switch (rc) {
 		case 0x03:
 			err = "Directory error";
 			break;
@@ -588,7 +590,7 @@
 	return NOTIFY_OK;
 }
 
-static struct notifier_block iucv_cpu_notifier = {
+static struct notifier_block __cpuinitdata iucv_cpu_notifier = {
 	.notifier_call = iucv_cpu_notify,
 };
 
@@ -691,6 +693,7 @@
 	mutex_unlock(&iucv_register_mutex);
 	return rc;
 }
+EXPORT_SYMBOL(iucv_register);
 
 /**
  * iucv_unregister
@@ -723,6 +726,7 @@
 		iucv_setmask_mp();
 	mutex_unlock(&iucv_register_mutex);
 }
+EXPORT_SYMBOL(iucv_unregister);
 
 /**
  * iucv_path_accept
@@ -761,6 +765,7 @@
 	local_bh_enable();
 	return rc;
 }
+EXPORT_SYMBOL(iucv_path_accept);
 
 /**
  * iucv_path_connect
@@ -824,6 +829,7 @@
 	spin_unlock_bh(&iucv_table_lock);
 	return rc;
 }
+EXPORT_SYMBOL(iucv_path_connect);
 
 /**
  * iucv_path_quiesce:
@@ -850,6 +856,7 @@
 	local_bh_enable();
 	return rc;
 }
+EXPORT_SYMBOL(iucv_path_quiesce);
 
 /**
  * iucv_path_resume:
@@ -890,7 +897,6 @@
 {
 	int rc;
 
-
 	preempt_disable();
 	if (iucv_active_cpu != smp_processor_id())
 		spin_lock_bh(&iucv_table_lock);
@@ -904,6 +910,7 @@
 	preempt_enable();
 	return rc;
 }
+EXPORT_SYMBOL(iucv_path_sever);
 
 /**
  * iucv_message_purge
@@ -936,6 +943,7 @@
 	local_bh_enable();
 	return rc;
 }
+EXPORT_SYMBOL(iucv_message_purge);
 
 /**
  * iucv_message_receive
@@ -1006,6 +1014,7 @@
 	local_bh_enable();
 	return rc;
 }
+EXPORT_SYMBOL(iucv_message_receive);
 
 /**
  * iucv_message_reject
@@ -1034,6 +1043,7 @@
 	local_bh_enable();
 	return rc;
 }
+EXPORT_SYMBOL(iucv_message_reject);
 
 /**
  * iucv_message_reply
@@ -1077,6 +1087,7 @@
 	local_bh_enable();
 	return rc;
 }
+EXPORT_SYMBOL(iucv_message_reply);
 
 /**
  * iucv_message_send
@@ -1125,6 +1136,7 @@
 	local_bh_enable();
 	return rc;
 }
+EXPORT_SYMBOL(iucv_message_send);
 
 /**
  * iucv_message_send2way
@@ -1181,6 +1193,7 @@
 	local_bh_enable();
 	return rc;
 }
+EXPORT_SYMBOL(iucv_message_send2way);
 
 /**
  * iucv_path_pending
@@ -1572,7 +1585,7 @@
  *
  * Allocates and initializes various data structures.
  */
-static int iucv_init(void)
+static int __init iucv_init(void)
 {
 	int rc;
 
@@ -1583,7 +1596,7 @@
 	rc = iucv_query_maxconn();
 	if (rc)
 		goto out;
-	rc = register_external_interrupt (0x4000, iucv_external_interrupt);
+	rc = register_external_interrupt(0x4000, iucv_external_interrupt);
 	if (rc)
 		goto out;
 	rc = bus_register(&iucv_bus);
@@ -1594,7 +1607,7 @@
 		rc = PTR_ERR(iucv_root);
 		goto out_bus;
 	}
-	/* Note: GFP_DMA used used to get memory below 2G */
+	/* Note: GFP_DMA used to get memory below 2G */
 	iucv_irq_data = percpu_alloc(sizeof(struct iucv_irq_data),
 				     GFP_KERNEL|GFP_DMA);
 	if (!iucv_irq_data) {
@@ -1632,7 +1645,7 @@
  *
  * Frees everything allocated from iucv_init.
  */
-static void iucv_exit(void)
+static void __exit iucv_exit(void)
 {
 	struct iucv_irq_list *p, *n;
 
@@ -1653,24 +1666,6 @@
 subsys_initcall(iucv_init);
 module_exit(iucv_exit);
 
-/**
- * Export all public stuff
- */
-EXPORT_SYMBOL (iucv_bus);
-EXPORT_SYMBOL (iucv_root);
-EXPORT_SYMBOL (iucv_register);
-EXPORT_SYMBOL (iucv_unregister);
-EXPORT_SYMBOL (iucv_path_accept);
-EXPORT_SYMBOL (iucv_path_connect);
-EXPORT_SYMBOL (iucv_path_quiesce);
-EXPORT_SYMBOL (iucv_path_sever);
-EXPORT_SYMBOL (iucv_message_purge);
-EXPORT_SYMBOL (iucv_message_receive);
-EXPORT_SYMBOL (iucv_message_reject);
-EXPORT_SYMBOL (iucv_message_reply);
-EXPORT_SYMBOL (iucv_message_send);
-EXPORT_SYMBOL (iucv_message_send2way);
-
 MODULE_AUTHOR("(C) 2001 IBM Corp. by Fritz Elfert (felfert@millenux.com)");
 MODULE_DESCRIPTION("Linux for S/390 IUCV lowlevel driver");
 MODULE_LICENSE("GPL");
diff --git a/net/llc/llc_core.c b/net/llc/llc_core.c
index d12413c..d4b13a0 100644
--- a/net/llc/llc_core.c
+++ b/net/llc/llc_core.c
@@ -160,8 +160,14 @@
 
 static int __init llc_init(void)
 {
-	if (dev_base->next)
-		memcpy(llc_station_mac_sa, dev_base->next->dev_addr, ETH_ALEN);
+	struct net_device *dev;
+
+	dev = first_net_device();
+	if (dev != NULL)
+		dev = next_net_device(dev);
+
+	if (dev != NULL)
+		memcpy(llc_station_mac_sa, dev->dev_addr, ETH_ALEN);
 	else
 		memset(llc_station_mac_sa, 0, ETH_ALEN);
 	dev_add_pack(&llc_packet_type);
diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig
new file mode 100644
index 0000000..6fffb38
--- /dev/null
+++ b/net/mac80211/Kconfig
@@ -0,0 +1,78 @@
+config MAC80211
+	tristate "Generic IEEE 802.11 Networking Stack (mac80211)"
+	depends on EXPERIMENTAL
+	select CRYPTO
+	select CRYPTO_ECB
+	select CRYPTO_ARC4
+	select CRYPTO_AES
+	select CRC32
+	select WIRELESS_EXT
+	select CFG80211
+	select NET_SCH_FIFO
+	---help---
+	This option enables the hardware independent IEEE 802.11
+	networking stack.
+
+config MAC80211_LEDS
+	bool "Enable LED triggers"
+	depends on MAC80211 && LEDS_TRIGGERS
+	---help---
+	This option enables a few LED triggers for different
+	packet receive/transmit events.
+
+config MAC80211_DEBUGFS
+	bool "Export mac80211 internals in DebugFS"
+	depends on MAC80211 && DEBUG_FS
+	---help---
+	  Select this to see extensive information about
+	  the internal state of mac80211 in debugfs.
+
+	  Say N unless you know you need this.
+
+config MAC80211_DEBUG
+	bool "Enable debugging output"
+	depends on MAC80211
+	---help---
+	  This option will enable debug tracing output for the
+	  ieee80211 network stack.
+
+	  If you are not trying to debug or develop the ieee80211
+	  subsystem, you most likely want to say N here.
+
+config MAC80211_VERBOSE_DEBUG
+	bool "Verbose debugging output"
+	depends on MAC80211_DEBUG
+
+config MAC80211_LOWTX_FRAME_DUMP
+	bool "Debug frame dumping"
+	depends on MAC80211_DEBUG
+	---help---
+	  Selecting this option will cause the stack to
+	  print a message for each frame that is handed
+	  to the lowlevel driver for transmission. This
+	  message includes all MAC addresses and the
+	  frame control field.
+
+	  If unsure, say N and insert the debugging code
+	  you require into the driver you are debugging.
+
+config TKIP_DEBUG
+	bool "TKIP debugging"
+	depends on MAC80211_DEBUG
+
+config MAC80211_DEBUG_COUNTERS
+	bool "Extra statistics for TX/RX debugging"
+	depends on MAC80211_DEBUG
+
+config MAC80211_IBSS_DEBUG
+	bool "Support for IBSS testing"
+	depends on MAC80211_DEBUG
+	---help---
+	  Say Y here if you intend to debug the IBSS code.
+
+config MAC80211_VERBOSE_PS_DEBUG
+	bool "Verbose powersave mode debugging"
+	depends on MAC80211_DEBUG
+	---help---
+	  Say Y here to print out verbose powersave
+	  mode debug messages.
diff --git a/net/mac80211/Makefile b/net/mac80211/Makefile
new file mode 100644
index 0000000..e9738da
--- /dev/null
+++ b/net/mac80211/Makefile
@@ -0,0 +1,20 @@
+obj-$(CONFIG_MAC80211) += mac80211.o rc80211_simple.o
+
+mac80211-objs-$(CONFIG_MAC80211_LEDS) += ieee80211_led.o
+mac80211-objs-$(CONFIG_MAC80211_DEBUGFS) += debugfs.o debugfs_sta.o debugfs_netdev.o debugfs_key.o
+
+mac80211-objs := \
+	ieee80211.o \
+	ieee80211_ioctl.o \
+	sta_info.o \
+	wep.o \
+	wpa.o \
+	ieee80211_sta.o \
+	ieee80211_iface.o \
+	ieee80211_rate.o \
+	michael.o \
+	tkip.o \
+	aes_ccm.o \
+	wme.o \
+	ieee80211_cfg.o \
+	$(mac80211-objs-y)
diff --git a/net/mac80211/aes_ccm.c b/net/mac80211/aes_ccm.c
new file mode 100644
index 0000000..e55569b
--- /dev/null
+++ b/net/mac80211/aes_ccm.c
@@ -0,0 +1,155 @@
+/*
+ * Copyright 2003-2004, Instant802 Networks, Inc.
+ * Copyright 2005-2006, Devicescape Software, Inc.
+ *
+ * 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/types.h>
+#include <linux/crypto.h>
+#include <linux/err.h>
+#include <asm/scatterlist.h>
+
+#include <net/mac80211.h>
+#include "ieee80211_key.h"
+#include "aes_ccm.h"
+
+
+static void ieee80211_aes_encrypt(struct crypto_cipher *tfm,
+				  const u8 pt[16], u8 ct[16])
+{
+	crypto_cipher_encrypt_one(tfm, ct, pt);
+}
+
+
+static inline void aes_ccm_prepare(struct crypto_cipher *tfm, u8 *b_0, u8 *aad,
+				   u8 *b, u8 *s_0, u8 *a)
+{
+	int i;
+
+	ieee80211_aes_encrypt(tfm, b_0, b);
+
+	/* Extra Authenticate-only data (always two AES blocks) */
+	for (i = 0; i < AES_BLOCK_LEN; i++)
+		aad[i] ^= b[i];
+	ieee80211_aes_encrypt(tfm, aad, b);
+
+	aad += AES_BLOCK_LEN;
+
+	for (i = 0; i < AES_BLOCK_LEN; i++)
+		aad[i] ^= b[i];
+	ieee80211_aes_encrypt(tfm, aad, a);
+
+	/* Mask out bits from auth-only-b_0 */
+	b_0[0] &= 0x07;
+
+	/* S_0 is used to encrypt T (= MIC) */
+	b_0[14] = 0;
+	b_0[15] = 0;
+	ieee80211_aes_encrypt(tfm, b_0, s_0);
+}
+
+
+void ieee80211_aes_ccm_encrypt(struct crypto_cipher *tfm, u8 *scratch,
+			       u8 *b_0, u8 *aad, u8 *data, size_t data_len,
+			       u8 *cdata, u8 *mic)
+{
+	int i, j, last_len, num_blocks;
+	u8 *pos, *cpos, *b, *s_0, *e;
+
+	b = scratch;
+	s_0 = scratch + AES_BLOCK_LEN;
+	e = scratch + 2 * AES_BLOCK_LEN;
+
+	num_blocks = (data_len + AES_BLOCK_LEN - 1) / AES_BLOCK_LEN;
+	last_len = data_len % AES_BLOCK_LEN;
+	aes_ccm_prepare(tfm, b_0, aad, b, s_0, b);
+
+	/* Process payload blocks */
+	pos = data;
+	cpos = cdata;
+	for (j = 1; j <= num_blocks; j++) {
+		int blen = (j == num_blocks && last_len) ?
+			last_len : AES_BLOCK_LEN;
+
+		/* Authentication followed by encryption */
+		for (i = 0; i < blen; i++)
+			b[i] ^= pos[i];
+		ieee80211_aes_encrypt(tfm, b, b);
+
+		b_0[14] = (j >> 8) & 0xff;
+		b_0[15] = j & 0xff;
+		ieee80211_aes_encrypt(tfm, b_0, e);
+		for (i = 0; i < blen; i++)
+			*cpos++ = *pos++ ^ e[i];
+	}
+
+	for (i = 0; i < CCMP_MIC_LEN; i++)
+		mic[i] = b[i] ^ s_0[i];
+}
+
+
+int ieee80211_aes_ccm_decrypt(struct crypto_cipher *tfm, u8 *scratch,
+			      u8 *b_0, u8 *aad, u8 *cdata, size_t data_len,
+			      u8 *mic, u8 *data)
+{
+	int i, j, last_len, num_blocks;
+	u8 *pos, *cpos, *b, *s_0, *a;
+
+	b = scratch;
+	s_0 = scratch + AES_BLOCK_LEN;
+	a = scratch + 2 * AES_BLOCK_LEN;
+
+	num_blocks = (data_len + AES_BLOCK_LEN - 1) / AES_BLOCK_LEN;
+	last_len = data_len % AES_BLOCK_LEN;
+	aes_ccm_prepare(tfm, b_0, aad, b, s_0, a);
+
+	/* Process payload blocks */
+	cpos = cdata;
+	pos = data;
+	for (j = 1; j <= num_blocks; j++) {
+		int blen = (j == num_blocks && last_len) ?
+			last_len : AES_BLOCK_LEN;
+
+		/* Decryption followed by authentication */
+		b_0[14] = (j >> 8) & 0xff;
+		b_0[15] = j & 0xff;
+		ieee80211_aes_encrypt(tfm, b_0, b);
+		for (i = 0; i < blen; i++) {
+			*pos = *cpos++ ^ b[i];
+			a[i] ^= *pos++;
+		}
+
+		ieee80211_aes_encrypt(tfm, a, a);
+	}
+
+	for (i = 0; i < CCMP_MIC_LEN; i++) {
+		if ((mic[i] ^ s_0[i]) != a[i])
+			return -1;
+	}
+
+	return 0;
+}
+
+
+struct crypto_cipher * ieee80211_aes_key_setup_encrypt(const u8 key[])
+{
+	struct crypto_cipher *tfm;
+
+	tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC);
+	if (IS_ERR(tfm))
+		return NULL;
+
+	crypto_cipher_setkey(tfm, key, ALG_CCMP_KEY_LEN);
+
+	return tfm;
+}
+
+
+void ieee80211_aes_key_free(struct crypto_cipher *tfm)
+{
+	if (tfm)
+		crypto_free_cipher(tfm);
+}
diff --git a/net/mac80211/aes_ccm.h b/net/mac80211/aes_ccm.h
new file mode 100644
index 0000000..885f190
--- /dev/null
+++ b/net/mac80211/aes_ccm.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2003-2004, Instant802 Networks, Inc.
+ * Copyright 2006, Devicescape Software, Inc.
+ *
+ * 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 AES_CCM_H
+#define AES_CCM_H
+
+#include <linux/crypto.h>
+
+#define AES_BLOCK_LEN 16
+
+struct crypto_cipher * ieee80211_aes_key_setup_encrypt(const u8 key[]);
+void ieee80211_aes_ccm_encrypt(struct crypto_cipher *tfm, u8 *scratch,
+			       u8 *b_0, u8 *aad, u8 *data, size_t data_len,
+			       u8 *cdata, u8 *mic);
+int ieee80211_aes_ccm_decrypt(struct crypto_cipher *tfm, u8 *scratch,
+			      u8 *b_0, u8 *aad, u8 *cdata, size_t data_len,
+			      u8 *mic, u8 *data);
+void ieee80211_aes_key_free(struct crypto_cipher *tfm);
+
+#endif /* AES_CCM_H */
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c
new file mode 100644
index 0000000..bb6c0fe
--- /dev/null
+++ b/net/mac80211/debugfs.c
@@ -0,0 +1,433 @@
+/*
+ * mac80211 debugfs for wireless PHYs
+ *
+ * Copyright 2007	Johannes Berg <johannes@sipsolutions.net>
+ *
+ * GPLv2
+ *
+ */
+
+#include <linux/debugfs.h>
+#include <linux/rtnetlink.h>
+#include "ieee80211_i.h"
+#include "ieee80211_rate.h"
+#include "debugfs.h"
+
+int mac80211_open_file_generic(struct inode *inode, struct file *file)
+{
+	file->private_data = inode->i_private;
+	return 0;
+}
+
+static const char *ieee80211_mode_str(int mode)
+{
+	switch (mode) {
+	case MODE_IEEE80211A:
+		return "IEEE 802.11a";
+	case MODE_IEEE80211B:
+		return "IEEE 802.11b";
+	case MODE_IEEE80211G:
+		return "IEEE 802.11g";
+	case MODE_ATHEROS_TURBO:
+		return "Atheros Turbo (5 GHz)";
+	default:
+		return "UNKNOWN";
+	}
+}
+
+static ssize_t modes_read(struct file *file, char __user *userbuf,
+			  size_t count, loff_t *ppos)
+{
+	struct ieee80211_local *local = file->private_data;
+	struct ieee80211_hw_mode *mode;
+	char buf[150], *p = buf;
+
+	/* FIXME: locking! */
+	list_for_each_entry(mode, &local->modes_list, list) {
+		p += scnprintf(p, sizeof(buf)+buf-p,
+			       "%s\n", ieee80211_mode_str(mode->mode));
+	}
+
+	return simple_read_from_buffer(userbuf, count, ppos, buf, p-buf);
+}
+
+static const struct file_operations modes_ops = {
+	.read = modes_read,
+	.open = mac80211_open_file_generic,
+};
+
+#define DEBUGFS_READONLY_FILE(name, buflen, fmt, value...)		\
+static ssize_t name## _read(struct file *file, char __user *userbuf,	\
+			    size_t count, loff_t *ppos)			\
+{									\
+	struct ieee80211_local *local = file->private_data;		\
+	char buf[buflen];						\
+	int res;							\
+									\
+	res = scnprintf(buf, buflen, fmt "\n", ##value);		\
+	return simple_read_from_buffer(userbuf, count, ppos, buf, res);	\
+}									\
+									\
+static const struct file_operations name## _ops = {			\
+	.read = name## _read,						\
+	.open = mac80211_open_file_generic,				\
+};
+
+#define DEBUGFS_ADD(name)						\
+	local->debugfs.name = debugfs_create_file(#name, 0444, phyd,	\
+						  local, &name## _ops);
+
+#define DEBUGFS_DEL(name)						\
+	debugfs_remove(local->debugfs.name);				\
+	local->debugfs.name = NULL;
+
+
+DEBUGFS_READONLY_FILE(channel, 20, "%d",
+		      local->hw.conf.channel);
+DEBUGFS_READONLY_FILE(frequency, 20, "%d",
+		      local->hw.conf.freq);
+DEBUGFS_READONLY_FILE(radar_detect, 20, "%d",
+		      local->hw.conf.radar_detect);
+DEBUGFS_READONLY_FILE(antenna_sel_tx, 20, "%d",
+		      local->hw.conf.antenna_sel_tx);
+DEBUGFS_READONLY_FILE(antenna_sel_rx, 20, "%d",
+		      local->hw.conf.antenna_sel_rx);
+DEBUGFS_READONLY_FILE(bridge_packets, 20, "%d",
+		      local->bridge_packets);
+DEBUGFS_READONLY_FILE(key_tx_rx_threshold, 20, "%d",
+		      local->key_tx_rx_threshold);
+DEBUGFS_READONLY_FILE(rts_threshold, 20, "%d",
+		      local->rts_threshold);
+DEBUGFS_READONLY_FILE(fragmentation_threshold, 20, "%d",
+		      local->fragmentation_threshold);
+DEBUGFS_READONLY_FILE(short_retry_limit, 20, "%d",
+		      local->short_retry_limit);
+DEBUGFS_READONLY_FILE(long_retry_limit, 20, "%d",
+		      local->long_retry_limit);
+DEBUGFS_READONLY_FILE(total_ps_buffered, 20, "%d",
+		      local->total_ps_buffered);
+DEBUGFS_READONLY_FILE(mode, 20, "%s",
+		      ieee80211_mode_str(local->hw.conf.phymode));
+DEBUGFS_READONLY_FILE(wep_iv, 20, "%#06x",
+		      local->wep_iv & 0xffffff);
+DEBUGFS_READONLY_FILE(tx_power_reduction, 20, "%d.%d dBm",
+		      local->hw.conf.tx_power_reduction / 10,
+		      local->hw.conf.tx_power_reduction & 10);
+DEBUGFS_READONLY_FILE(rate_ctrl_alg, 100, "%s",
+		      local->rate_ctrl ? local->rate_ctrl->ops->name : "<unset>");
+
+/* statistics stuff */
+
+static inline int rtnl_lock_local(struct ieee80211_local *local)
+{
+	rtnl_lock();
+	if (unlikely(local->reg_state != IEEE80211_DEV_REGISTERED)) {
+		rtnl_unlock();
+		return -ENODEV;
+	}
+	return 0;
+}
+
+#define DEBUGFS_STATS_FILE(name, buflen, fmt, value...)			\
+	DEBUGFS_READONLY_FILE(stats_ ##name, buflen, fmt, ##value)
+
+static ssize_t format_devstat_counter(struct ieee80211_local *local,
+	char __user *userbuf,
+	size_t count, loff_t *ppos,
+	int (*printvalue)(struct ieee80211_low_level_stats *stats, char *buf,
+			  int buflen))
+{
+	struct ieee80211_low_level_stats stats;
+	char buf[20];
+	int res;
+
+	if (!local->ops->get_stats)
+		return -EOPNOTSUPP;
+
+	res = rtnl_lock_local(local);
+	if (res)
+		return res;
+
+	res = local->ops->get_stats(local_to_hw(local), &stats);
+	rtnl_unlock();
+	if (!res)
+		res = printvalue(&stats, buf, sizeof(buf));
+	return simple_read_from_buffer(userbuf, count, ppos, buf, res);
+}
+
+#define DEBUGFS_DEVSTATS_FILE(name)					\
+static int print_devstats_##name(struct ieee80211_low_level_stats *stats,\
+				 char *buf, int buflen)			\
+{									\
+	return scnprintf(buf, buflen, "%u\n", stats->name);		\
+}									\
+static ssize_t stats_ ##name## _read(struct file *file,			\
+				     char __user *userbuf,		\
+				     size_t count, loff_t *ppos)	\
+{									\
+	return format_devstat_counter(file->private_data,		\
+				      userbuf,				\
+				      count,				\
+				      ppos,				\
+				      print_devstats_##name);		\
+}									\
+									\
+static const struct file_operations stats_ ##name## _ops = {		\
+	.read = stats_ ##name## _read,					\
+	.open = mac80211_open_file_generic,				\
+};
+
+#define DEBUGFS_STATS_ADD(name)						\
+	local->debugfs.stats.name = debugfs_create_file(#name, 0444, statsd,\
+		local, &stats_ ##name## _ops);
+
+#define DEBUGFS_STATS_DEL(name)						\
+	debugfs_remove(local->debugfs.stats.name);			\
+	local->debugfs.stats.name = NULL;
+
+DEBUGFS_STATS_FILE(transmitted_fragment_count, 20, "%u",
+		   local->dot11TransmittedFragmentCount);
+DEBUGFS_STATS_FILE(multicast_transmitted_frame_count, 20, "%u",
+		   local->dot11MulticastTransmittedFrameCount);
+DEBUGFS_STATS_FILE(failed_count, 20, "%u",
+		   local->dot11FailedCount);
+DEBUGFS_STATS_FILE(retry_count, 20, "%u",
+		   local->dot11RetryCount);
+DEBUGFS_STATS_FILE(multiple_retry_count, 20, "%u",
+		   local->dot11MultipleRetryCount);
+DEBUGFS_STATS_FILE(frame_duplicate_count, 20, "%u",
+		   local->dot11FrameDuplicateCount);
+DEBUGFS_STATS_FILE(received_fragment_count, 20, "%u",
+		   local->dot11ReceivedFragmentCount);
+DEBUGFS_STATS_FILE(multicast_received_frame_count, 20, "%u",
+		   local->dot11MulticastReceivedFrameCount);
+DEBUGFS_STATS_FILE(transmitted_frame_count, 20, "%u",
+		   local->dot11TransmittedFrameCount);
+DEBUGFS_STATS_FILE(wep_undecryptable_count, 20, "%u",
+		   local->dot11WEPUndecryptableCount);
+#ifdef CONFIG_MAC80211_DEBUG_COUNTERS
+DEBUGFS_STATS_FILE(tx_handlers_drop, 20, "%u",
+		   local->tx_handlers_drop);
+DEBUGFS_STATS_FILE(tx_handlers_queued, 20, "%u",
+		   local->tx_handlers_queued);
+DEBUGFS_STATS_FILE(tx_handlers_drop_unencrypted, 20, "%u",
+		   local->tx_handlers_drop_unencrypted);
+DEBUGFS_STATS_FILE(tx_handlers_drop_fragment, 20, "%u",
+		   local->tx_handlers_drop_fragment);
+DEBUGFS_STATS_FILE(tx_handlers_drop_wep, 20, "%u",
+		   local->tx_handlers_drop_wep);
+DEBUGFS_STATS_FILE(tx_handlers_drop_not_assoc, 20, "%u",
+		   local->tx_handlers_drop_not_assoc);
+DEBUGFS_STATS_FILE(tx_handlers_drop_unauth_port, 20, "%u",
+		   local->tx_handlers_drop_unauth_port);
+DEBUGFS_STATS_FILE(rx_handlers_drop, 20, "%u",
+		   local->rx_handlers_drop);
+DEBUGFS_STATS_FILE(rx_handlers_queued, 20, "%u",
+		   local->rx_handlers_queued);
+DEBUGFS_STATS_FILE(rx_handlers_drop_nullfunc, 20, "%u",
+		   local->rx_handlers_drop_nullfunc);
+DEBUGFS_STATS_FILE(rx_handlers_drop_defrag, 20, "%u",
+		   local->rx_handlers_drop_defrag);
+DEBUGFS_STATS_FILE(rx_handlers_drop_short, 20, "%u",
+		   local->rx_handlers_drop_short);
+DEBUGFS_STATS_FILE(rx_handlers_drop_passive_scan, 20, "%u",
+		   local->rx_handlers_drop_passive_scan);
+DEBUGFS_STATS_FILE(tx_expand_skb_head, 20, "%u",
+		   local->tx_expand_skb_head);
+DEBUGFS_STATS_FILE(tx_expand_skb_head_cloned, 20, "%u",
+		   local->tx_expand_skb_head_cloned);
+DEBUGFS_STATS_FILE(rx_expand_skb_head, 20, "%u",
+		   local->rx_expand_skb_head);
+DEBUGFS_STATS_FILE(rx_expand_skb_head2, 20, "%u",
+		   local->rx_expand_skb_head2);
+DEBUGFS_STATS_FILE(rx_handlers_fragments, 20, "%u",
+		   local->rx_handlers_fragments);
+DEBUGFS_STATS_FILE(tx_status_drop, 20, "%u",
+		   local->tx_status_drop);
+
+static ssize_t stats_wme_rx_queue_read(struct file *file,
+				       char __user *userbuf,
+				       size_t count, loff_t *ppos)
+{
+	struct ieee80211_local *local = file->private_data;
+	char buf[NUM_RX_DATA_QUEUES*15], *p = buf;
+	int i;
+
+	for (i = 0; i < NUM_RX_DATA_QUEUES; i++)
+		p += scnprintf(p, sizeof(buf)+buf-p,
+			       "%u\n", local->wme_rx_queue[i]);
+
+	return simple_read_from_buffer(userbuf, count, ppos, buf, p-buf);
+}
+
+static const struct file_operations stats_wme_rx_queue_ops = {
+	.read = stats_wme_rx_queue_read,
+	.open = mac80211_open_file_generic,
+};
+
+static ssize_t stats_wme_tx_queue_read(struct file *file,
+				       char __user *userbuf,
+				       size_t count, loff_t *ppos)
+{
+	struct ieee80211_local *local = file->private_data;
+	char buf[NUM_TX_DATA_QUEUES*15], *p = buf;
+	int i;
+
+	for (i = 0; i < NUM_TX_DATA_QUEUES; i++)
+		p += scnprintf(p, sizeof(buf)+buf-p,
+			       "%u\n", local->wme_tx_queue[i]);
+
+	return simple_read_from_buffer(userbuf, count, ppos, buf, p-buf);
+}
+
+static const struct file_operations stats_wme_tx_queue_ops = {
+	.read = stats_wme_tx_queue_read,
+	.open = mac80211_open_file_generic,
+};
+#endif
+
+DEBUGFS_DEVSTATS_FILE(dot11ACKFailureCount);
+DEBUGFS_DEVSTATS_FILE(dot11RTSFailureCount);
+DEBUGFS_DEVSTATS_FILE(dot11FCSErrorCount);
+DEBUGFS_DEVSTATS_FILE(dot11RTSSuccessCount);
+
+
+void debugfs_hw_add(struct ieee80211_local *local)
+{
+	struct dentry *phyd = local->hw.wiphy->debugfsdir;
+	struct dentry *statsd;
+
+	if (!phyd)
+		return;
+
+	local->debugfs.stations = debugfs_create_dir("stations", phyd);
+	local->debugfs.keys = debugfs_create_dir("keys", phyd);
+
+	DEBUGFS_ADD(channel);
+	DEBUGFS_ADD(frequency);
+	DEBUGFS_ADD(radar_detect);
+	DEBUGFS_ADD(antenna_sel_tx);
+	DEBUGFS_ADD(antenna_sel_rx);
+	DEBUGFS_ADD(bridge_packets);
+	DEBUGFS_ADD(key_tx_rx_threshold);
+	DEBUGFS_ADD(rts_threshold);
+	DEBUGFS_ADD(fragmentation_threshold);
+	DEBUGFS_ADD(short_retry_limit);
+	DEBUGFS_ADD(long_retry_limit);
+	DEBUGFS_ADD(total_ps_buffered);
+	DEBUGFS_ADD(mode);
+	DEBUGFS_ADD(wep_iv);
+	DEBUGFS_ADD(tx_power_reduction);
+	DEBUGFS_ADD(modes);
+
+	statsd = debugfs_create_dir("statistics", phyd);
+	local->debugfs.statistics = statsd;
+
+	/* if the dir failed, don't put all the other things into the root! */
+	if (!statsd)
+		return;
+
+	DEBUGFS_STATS_ADD(transmitted_fragment_count);
+	DEBUGFS_STATS_ADD(multicast_transmitted_frame_count);
+	DEBUGFS_STATS_ADD(failed_count);
+	DEBUGFS_STATS_ADD(retry_count);
+	DEBUGFS_STATS_ADD(multiple_retry_count);
+	DEBUGFS_STATS_ADD(frame_duplicate_count);
+	DEBUGFS_STATS_ADD(received_fragment_count);
+	DEBUGFS_STATS_ADD(multicast_received_frame_count);
+	DEBUGFS_STATS_ADD(transmitted_frame_count);
+	DEBUGFS_STATS_ADD(wep_undecryptable_count);
+#ifdef CONFIG_MAC80211_DEBUG_COUNTERS
+	DEBUGFS_STATS_ADD(tx_handlers_drop);
+	DEBUGFS_STATS_ADD(tx_handlers_queued);
+	DEBUGFS_STATS_ADD(tx_handlers_drop_unencrypted);
+	DEBUGFS_STATS_ADD(tx_handlers_drop_fragment);
+	DEBUGFS_STATS_ADD(tx_handlers_drop_wep);
+	DEBUGFS_STATS_ADD(tx_handlers_drop_not_assoc);
+	DEBUGFS_STATS_ADD(tx_handlers_drop_unauth_port);
+	DEBUGFS_STATS_ADD(rx_handlers_drop);
+	DEBUGFS_STATS_ADD(rx_handlers_queued);
+	DEBUGFS_STATS_ADD(rx_handlers_drop_nullfunc);
+	DEBUGFS_STATS_ADD(rx_handlers_drop_defrag);
+	DEBUGFS_STATS_ADD(rx_handlers_drop_short);
+	DEBUGFS_STATS_ADD(rx_handlers_drop_passive_scan);
+	DEBUGFS_STATS_ADD(tx_expand_skb_head);
+	DEBUGFS_STATS_ADD(tx_expand_skb_head_cloned);
+	DEBUGFS_STATS_ADD(rx_expand_skb_head);
+	DEBUGFS_STATS_ADD(rx_expand_skb_head2);
+	DEBUGFS_STATS_ADD(rx_handlers_fragments);
+	DEBUGFS_STATS_ADD(tx_status_drop);
+	DEBUGFS_STATS_ADD(wme_tx_queue);
+	DEBUGFS_STATS_ADD(wme_rx_queue);
+#endif
+	DEBUGFS_STATS_ADD(dot11ACKFailureCount);
+	DEBUGFS_STATS_ADD(dot11RTSFailureCount);
+	DEBUGFS_STATS_ADD(dot11FCSErrorCount);
+	DEBUGFS_STATS_ADD(dot11RTSSuccessCount);
+}
+
+void debugfs_hw_del(struct ieee80211_local *local)
+{
+	DEBUGFS_DEL(channel);
+	DEBUGFS_DEL(frequency);
+	DEBUGFS_DEL(radar_detect);
+	DEBUGFS_DEL(antenna_sel_tx);
+	DEBUGFS_DEL(antenna_sel_rx);
+	DEBUGFS_DEL(bridge_packets);
+	DEBUGFS_DEL(key_tx_rx_threshold);
+	DEBUGFS_DEL(rts_threshold);
+	DEBUGFS_DEL(fragmentation_threshold);
+	DEBUGFS_DEL(short_retry_limit);
+	DEBUGFS_DEL(long_retry_limit);
+	DEBUGFS_DEL(total_ps_buffered);
+	DEBUGFS_DEL(mode);
+	DEBUGFS_DEL(wep_iv);
+	DEBUGFS_DEL(tx_power_reduction);
+	DEBUGFS_DEL(modes);
+
+	DEBUGFS_STATS_DEL(transmitted_fragment_count);
+	DEBUGFS_STATS_DEL(multicast_transmitted_frame_count);
+	DEBUGFS_STATS_DEL(failed_count);
+	DEBUGFS_STATS_DEL(retry_count);
+	DEBUGFS_STATS_DEL(multiple_retry_count);
+	DEBUGFS_STATS_DEL(frame_duplicate_count);
+	DEBUGFS_STATS_DEL(received_fragment_count);
+	DEBUGFS_STATS_DEL(multicast_received_frame_count);
+	DEBUGFS_STATS_DEL(transmitted_frame_count);
+	DEBUGFS_STATS_DEL(wep_undecryptable_count);
+	DEBUGFS_STATS_DEL(num_scans);
+#ifdef CONFIG_MAC80211_DEBUG_COUNTERS
+	DEBUGFS_STATS_DEL(tx_handlers_drop);
+	DEBUGFS_STATS_DEL(tx_handlers_queued);
+	DEBUGFS_STATS_DEL(tx_handlers_drop_unencrypted);
+	DEBUGFS_STATS_DEL(tx_handlers_drop_fragment);
+	DEBUGFS_STATS_DEL(tx_handlers_drop_wep);
+	DEBUGFS_STATS_DEL(tx_handlers_drop_not_assoc);
+	DEBUGFS_STATS_DEL(tx_handlers_drop_unauth_port);
+	DEBUGFS_STATS_DEL(rx_handlers_drop);
+	DEBUGFS_STATS_DEL(rx_handlers_queued);
+	DEBUGFS_STATS_DEL(rx_handlers_drop_nullfunc);
+	DEBUGFS_STATS_DEL(rx_handlers_drop_defrag);
+	DEBUGFS_STATS_DEL(rx_handlers_drop_short);
+	DEBUGFS_STATS_DEL(rx_handlers_drop_passive_scan);
+	DEBUGFS_STATS_DEL(tx_expand_skb_head);
+	DEBUGFS_STATS_DEL(tx_expand_skb_head_cloned);
+	DEBUGFS_STATS_DEL(rx_expand_skb_head);
+	DEBUGFS_STATS_DEL(rx_expand_skb_head2);
+	DEBUGFS_STATS_DEL(rx_handlers_fragments);
+	DEBUGFS_STATS_DEL(tx_status_drop);
+	DEBUGFS_STATS_DEL(wme_tx_queue);
+	DEBUGFS_STATS_DEL(wme_rx_queue);
+#endif
+	DEBUGFS_STATS_DEL(dot11ACKFailureCount);
+	DEBUGFS_STATS_DEL(dot11RTSFailureCount);
+	DEBUGFS_STATS_DEL(dot11FCSErrorCount);
+	DEBUGFS_STATS_DEL(dot11RTSSuccessCount);
+
+	debugfs_remove(local->debugfs.statistics);
+	local->debugfs.statistics = NULL;
+	debugfs_remove(local->debugfs.stations);
+	local->debugfs.stations = NULL;
+	debugfs_remove(local->debugfs.keys);
+	local->debugfs.keys = NULL;
+}
diff --git a/net/mac80211/debugfs.h b/net/mac80211/debugfs.h
new file mode 100644
index 0000000..dd25419
--- /dev/null
+++ b/net/mac80211/debugfs.h
@@ -0,0 +1,16 @@
+#ifndef __MAC80211_DEBUGFS_H
+#define __MAC80211_DEBUGFS_H
+
+#ifdef CONFIG_MAC80211_DEBUGFS
+extern void debugfs_hw_add(struct ieee80211_local *local);
+extern void debugfs_hw_del(struct ieee80211_local *local);
+extern int mac80211_open_file_generic(struct inode *inode, struct file *file);
+#else
+static inline void debugfs_hw_add(struct ieee80211_local *local)
+{
+	return;
+}
+static inline void debugfs_hw_del(struct ieee80211_local *local) {}
+#endif
+
+#endif /* __MAC80211_DEBUGFS_H */
diff --git a/net/mac80211/debugfs_key.c b/net/mac80211/debugfs_key.c
new file mode 100644
index 0000000..7d56dc9
--- /dev/null
+++ b/net/mac80211/debugfs_key.c
@@ -0,0 +1,252 @@
+/*
+ * Copyright 2003-2005	Devicescape Software, Inc.
+ * Copyright (c) 2006	Jiri Benc <jbenc@suse.cz>
+ * Copyright 2007	Johannes Berg <johannes@sipsolutions.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kobject.h>
+#include "ieee80211_i.h"
+#include "ieee80211_key.h"
+#include "debugfs.h"
+#include "debugfs_key.h"
+
+#define KEY_READ(name, buflen, format_string)				\
+static ssize_t key_##name##_read(struct file *file,			\
+				 char __user *userbuf,			\
+				 size_t count, loff_t *ppos)		\
+{									\
+	char buf[buflen];						\
+	struct ieee80211_key *key = file->private_data;			\
+	int res = scnprintf(buf, buflen, format_string, key->name);	\
+	return simple_read_from_buffer(userbuf, count, ppos, buf, res);	\
+}
+#define KEY_READ_D(name) KEY_READ(name, 20, "%d\n")
+
+#define KEY_OPS(name)							\
+static const struct file_operations key_ ##name## _ops = {		\
+	.read = key_##name##_read,					\
+	.open = mac80211_open_file_generic,				\
+}
+
+#define KEY_FILE(name, format)						\
+		 KEY_READ_##format(name)				\
+		 KEY_OPS(name)
+
+KEY_FILE(keylen, D);
+KEY_FILE(force_sw_encrypt, D);
+KEY_FILE(keyidx, D);
+KEY_FILE(hw_key_idx, D);
+KEY_FILE(tx_rx_count, D);
+
+static ssize_t key_algorithm_read(struct file *file,
+				  char __user *userbuf,
+				  size_t count, loff_t *ppos)
+{
+	char *alg;
+	struct ieee80211_key *key = file->private_data;
+
+	switch (key->alg) {
+	case ALG_WEP:
+		alg = "WEP\n";
+		break;
+	case ALG_TKIP:
+		alg = "TKIP\n";
+		break;
+	case ALG_CCMP:
+		alg = "CCMP\n";
+		break;
+	default:
+		return 0;
+	}
+	return simple_read_from_buffer(userbuf, count, ppos, alg, strlen(alg));
+}
+KEY_OPS(algorithm);
+
+static ssize_t key_tx_spec_read(struct file *file, char __user *userbuf,
+				size_t count, loff_t *ppos)
+{
+	const u8 *tpn;
+	char buf[20];
+	int len;
+	struct ieee80211_key *key = file->private_data;
+
+	switch (key->alg) {
+	case ALG_WEP:
+		len = scnprintf(buf, sizeof(buf), "\n");
+	case ALG_TKIP:
+		len = scnprintf(buf, sizeof(buf), "%08x %04x\n",
+				key->u.tkip.iv32,
+				key->u.tkip.iv16);
+	case ALG_CCMP:
+		tpn = key->u.ccmp.tx_pn;
+		len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n",
+				tpn[0], tpn[1], tpn[2], tpn[3], tpn[4], tpn[5]);
+	default:
+		return 0;
+	}
+	return simple_read_from_buffer(userbuf, count, ppos, buf, len);
+}
+KEY_OPS(tx_spec);
+
+static ssize_t key_rx_spec_read(struct file *file, char __user *userbuf,
+				size_t count, loff_t *ppos)
+{
+	struct ieee80211_key *key = file->private_data;
+	char buf[14*NUM_RX_DATA_QUEUES+1], *p = buf;
+	int i, len;
+	const u8 *rpn;
+
+	switch (key->alg) {
+	case ALG_WEP:
+		len = scnprintf(buf, sizeof(buf), "\n");
+	case ALG_TKIP:
+		for (i = 0; i < NUM_RX_DATA_QUEUES; i++)
+			p += scnprintf(p, sizeof(buf)+buf-p,
+				       "%08x %04x\n",
+				       key->u.tkip.iv32_rx[i],
+				       key->u.tkip.iv16_rx[i]);
+		len = p - buf;
+	case ALG_CCMP:
+		for (i = 0; i < NUM_RX_DATA_QUEUES; i++) {
+			rpn = key->u.ccmp.rx_pn[i];
+			p += scnprintf(p, sizeof(buf)+buf-p,
+				       "%02x%02x%02x%02x%02x%02x\n",
+				       rpn[0], rpn[1], rpn[2],
+				       rpn[3], rpn[4], rpn[5]);
+		}
+		len = p - buf;
+	default:
+		return 0;
+	}
+	return simple_read_from_buffer(userbuf, count, ppos, buf, len);
+}
+KEY_OPS(rx_spec);
+
+static ssize_t key_replays_read(struct file *file, char __user *userbuf,
+				size_t count, loff_t *ppos)
+{
+	struct ieee80211_key *key = file->private_data;
+	char buf[20];
+	int len;
+
+	if (key->alg != ALG_CCMP)
+		return 0;
+	len = scnprintf(buf, sizeof(buf), "%u\n", key->u.ccmp.replays);
+	return simple_read_from_buffer(userbuf, count, ppos, buf, len);
+}
+KEY_OPS(replays);
+
+static ssize_t key_key_read(struct file *file, char __user *userbuf,
+			    size_t count, loff_t *ppos)
+{
+	struct ieee80211_key *key = file->private_data;
+	int i, res, bufsize = 2*key->keylen+2;
+	char *buf = kmalloc(bufsize, GFP_KERNEL);
+	char *p = buf;
+
+	for (i = 0; i < key->keylen; i++)
+		p += scnprintf(p, bufsize+buf-p, "%02x", key->key[i]);
+	p += scnprintf(p, bufsize+buf-p, "\n");
+	res = simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
+	kfree(buf);
+	return res;
+}
+KEY_OPS(key);
+
+#define DEBUGFS_ADD(name) \
+	key->debugfs.name = debugfs_create_file(#name, 0400,\
+				key->debugfs.dir, key, &key_##name##_ops);
+
+void ieee80211_debugfs_key_add(struct ieee80211_local *local,
+			       struct ieee80211_key *key)
+{
+	char buf[20];
+
+	if (!local->debugfs.keys)
+		return;
+
+	sprintf(buf, "%d", key->keyidx);
+	key->debugfs.dir = debugfs_create_dir(buf,
+					local->debugfs.keys);
+
+	if (!key->debugfs.dir)
+		return;
+
+	DEBUGFS_ADD(keylen);
+	DEBUGFS_ADD(force_sw_encrypt);
+	DEBUGFS_ADD(keyidx);
+	DEBUGFS_ADD(hw_key_idx);
+	DEBUGFS_ADD(tx_rx_count);
+	DEBUGFS_ADD(algorithm);
+	DEBUGFS_ADD(tx_spec);
+	DEBUGFS_ADD(rx_spec);
+	DEBUGFS_ADD(replays);
+	DEBUGFS_ADD(key);
+};
+
+#define DEBUGFS_DEL(name) \
+	debugfs_remove(key->debugfs.name); key->debugfs.name = NULL;
+
+void ieee80211_debugfs_key_remove(struct ieee80211_key *key)
+{
+	if (!key)
+		return;
+
+	DEBUGFS_DEL(keylen);
+	DEBUGFS_DEL(force_sw_encrypt);
+	DEBUGFS_DEL(keyidx);
+	DEBUGFS_DEL(hw_key_idx);
+	DEBUGFS_DEL(tx_rx_count);
+	DEBUGFS_DEL(algorithm);
+	DEBUGFS_DEL(tx_spec);
+	DEBUGFS_DEL(rx_spec);
+	DEBUGFS_DEL(replays);
+	DEBUGFS_DEL(key);
+
+	debugfs_remove(key->debugfs.stalink);
+	key->debugfs.stalink = NULL;
+	debugfs_remove(key->debugfs.dir);
+	key->debugfs.dir = NULL;
+}
+void ieee80211_debugfs_key_add_default(struct ieee80211_sub_if_data *sdata)
+{
+	char buf[50];
+
+	if (!sdata->debugfsdir)
+		return;
+
+	sprintf(buf, "../keys/%d", sdata->default_key->keyidx);
+	sdata->debugfs.default_key =
+		debugfs_create_symlink("default_key", sdata->debugfsdir, buf);
+}
+void ieee80211_debugfs_key_remove_default(struct ieee80211_sub_if_data *sdata)
+{
+	if (!sdata)
+		return;
+
+	debugfs_remove(sdata->debugfs.default_key);
+	sdata->debugfs.default_key = NULL;
+}
+void ieee80211_debugfs_key_sta_link(struct ieee80211_key *key,
+				    struct sta_info *sta)
+{
+	char buf[50];
+
+	if (!key->debugfs.dir)
+		return;
+
+	sprintf(buf, "../sta/" MAC_FMT, MAC_ARG(sta->addr));
+	key->debugfs.stalink =
+		debugfs_create_symlink("station", key->debugfs.dir, buf);
+}
+
+void ieee80211_debugfs_key_sta_del(struct ieee80211_key *key,
+				   struct sta_info *sta)
+{
+	debugfs_remove(key->debugfs.stalink);
+	key->debugfs.stalink = NULL;
+}
diff --git a/net/mac80211/debugfs_key.h b/net/mac80211/debugfs_key.h
new file mode 100644
index 0000000..aecfce3
--- /dev/null
+++ b/net/mac80211/debugfs_key.h
@@ -0,0 +1,34 @@
+#ifndef __MAC80211_DEBUGFS_KEY_H
+#define __MAC80211_DEBUGFS_KEY_H
+
+#ifdef CONFIG_MAC80211_DEBUGFS
+void ieee80211_debugfs_key_add(struct ieee80211_local *local,
+			       struct ieee80211_key *key);
+void ieee80211_debugfs_key_remove(struct ieee80211_key *key);
+void ieee80211_debugfs_key_add_default(struct ieee80211_sub_if_data *sdata);
+void ieee80211_debugfs_key_remove_default(struct ieee80211_sub_if_data *sdata);
+void ieee80211_debugfs_key_sta_link(struct ieee80211_key *key,
+				    struct sta_info *sta);
+void ieee80211_debugfs_key_sta_del(struct ieee80211_key *key,
+				   struct sta_info *sta);
+#else
+static inline void ieee80211_debugfs_key_add(struct ieee80211_local *local,
+					     struct ieee80211_key *key)
+{}
+static inline void ieee80211_debugfs_key_remove(struct ieee80211_key *key)
+{}
+static inline void ieee80211_debugfs_key_add_default(
+	struct ieee80211_sub_if_data *sdata)
+{}
+static inline void ieee80211_debugfs_key_remove_default(
+	struct ieee80211_sub_if_data *sdata)
+{}
+static inline void ieee80211_debugfs_key_sta_link(
+	struct ieee80211_key *key, struct sta_info *sta)
+{}
+static inline void ieee80211_debugfs_key_sta_del(struct ieee80211_key *key,
+						 struct sta_info *sta)
+{}
+#endif
+
+#endif /* __MAC80211_DEBUGFS_KEY_H */
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c
new file mode 100644
index 0000000..9e39646
--- /dev/null
+++ b/net/mac80211/debugfs_netdev.c
@@ -0,0 +1,440 @@
+/*
+ * Copyright (c) 2006	Jiri Benc <jbenc@suse.cz>
+ * Copyright 2007	Johannes Berg <johannes@sipsolutions.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/if.h>
+#include <linux/interrupt.h>
+#include <linux/netdevice.h>
+#include <linux/rtnetlink.h>
+#include <linux/notifier.h>
+#include <net/mac80211.h>
+#include <net/cfg80211.h>
+#include "ieee80211_i.h"
+#include "ieee80211_rate.h"
+#include "debugfs.h"
+#include "debugfs_netdev.h"
+
+static ssize_t ieee80211_if_read(
+	struct ieee80211_sub_if_data *sdata,
+	char __user *userbuf,
+	size_t count, loff_t *ppos,
+	ssize_t (*format)(const struct ieee80211_sub_if_data *, char *, int))
+{
+	char buf[70];
+	ssize_t ret = -EINVAL;
+
+	read_lock(&dev_base_lock);
+	if (sdata->dev->reg_state == NETREG_REGISTERED) {
+		ret = (*format)(sdata, buf, sizeof(buf));
+		ret = simple_read_from_buffer(userbuf, count, ppos, buf, ret);
+	}
+	read_unlock(&dev_base_lock);
+	return ret;
+}
+
+#define IEEE80211_IF_FMT(name, field, format_string)			\
+static ssize_t ieee80211_if_fmt_##name(					\
+	const struct ieee80211_sub_if_data *sdata, char *buf,		\
+	int buflen)							\
+{									\
+	return scnprintf(buf, buflen, format_string, sdata->field);	\
+}
+#define IEEE80211_IF_FMT_DEC(name, field)				\
+		IEEE80211_IF_FMT(name, field, "%d\n")
+#define IEEE80211_IF_FMT_HEX(name, field)				\
+		IEEE80211_IF_FMT(name, field, "%#x\n")
+#define IEEE80211_IF_FMT_SIZE(name, field)				\
+		IEEE80211_IF_FMT(name, field, "%zd\n")
+
+#define IEEE80211_IF_FMT_ATOMIC(name, field)				\
+static ssize_t ieee80211_if_fmt_##name(					\
+	const struct ieee80211_sub_if_data *sdata,			\
+	char *buf, int buflen)						\
+{									\
+	return scnprintf(buf, buflen, "%d\n", atomic_read(&sdata->field));\
+}
+
+#define IEEE80211_IF_FMT_MAC(name, field)				\
+static ssize_t ieee80211_if_fmt_##name(					\
+	const struct ieee80211_sub_if_data *sdata, char *buf,		\
+	int buflen)							\
+{									\
+	return scnprintf(buf, buflen, MAC_FMT "\n", MAC_ARG(sdata->field));\
+}
+
+#define __IEEE80211_IF_FILE(name)					\
+static ssize_t ieee80211_if_read_##name(struct file *file,		\
+					char __user *userbuf,		\
+					size_t count, loff_t *ppos)	\
+{									\
+	return ieee80211_if_read(file->private_data,			\
+				 userbuf, count, ppos,			\
+				 ieee80211_if_fmt_##name);		\
+}									\
+static const struct file_operations name##_ops = {			\
+	.read = ieee80211_if_read_##name,				\
+	.open = mac80211_open_file_generic,				\
+}
+
+#define IEEE80211_IF_FILE(name, field, format)				\
+		IEEE80211_IF_FMT_##format(name, field)			\
+		__IEEE80211_IF_FILE(name)
+
+/* common attributes */
+IEEE80211_IF_FILE(channel_use, channel_use, DEC);
+IEEE80211_IF_FILE(drop_unencrypted, drop_unencrypted, DEC);
+IEEE80211_IF_FILE(eapol, eapol, DEC);
+IEEE80211_IF_FILE(ieee8021_x, ieee802_1x, DEC);
+
+/* STA/IBSS attributes */
+IEEE80211_IF_FILE(state, u.sta.state, DEC);
+IEEE80211_IF_FILE(bssid, u.sta.bssid, MAC);
+IEEE80211_IF_FILE(prev_bssid, u.sta.prev_bssid, MAC);
+IEEE80211_IF_FILE(ssid_len, u.sta.ssid_len, SIZE);
+IEEE80211_IF_FILE(aid, u.sta.aid, DEC);
+IEEE80211_IF_FILE(ap_capab, u.sta.ap_capab, HEX);
+IEEE80211_IF_FILE(capab, u.sta.capab, HEX);
+IEEE80211_IF_FILE(extra_ie_len, u.sta.extra_ie_len, SIZE);
+IEEE80211_IF_FILE(auth_tries, u.sta.auth_tries, DEC);
+IEEE80211_IF_FILE(assoc_tries, u.sta.assoc_tries, DEC);
+IEEE80211_IF_FILE(auth_algs, u.sta.auth_algs, HEX);
+IEEE80211_IF_FILE(auth_alg, u.sta.auth_alg, DEC);
+IEEE80211_IF_FILE(auth_transaction, u.sta.auth_transaction, DEC);
+
+static ssize_t ieee80211_if_fmt_flags(
+	const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
+{
+	return scnprintf(buf, buflen, "%s%s%s%s%s%s%s\n",
+			 sdata->u.sta.ssid_set ? "SSID\n" : "",
+			 sdata->u.sta.bssid_set ? "BSSID\n" : "",
+			 sdata->u.sta.prev_bssid_set ? "prev BSSID\n" : "",
+			 sdata->u.sta.authenticated ? "AUTH\n" : "",
+			 sdata->u.sta.associated ? "ASSOC\n" : "",
+			 sdata->u.sta.probereq_poll ? "PROBEREQ POLL\n" : "",
+			 sdata->u.sta.use_protection ? "CTS prot\n" : "");
+}
+__IEEE80211_IF_FILE(flags);
+
+/* AP attributes */
+IEEE80211_IF_FILE(num_sta_ps, u.ap.num_sta_ps, ATOMIC);
+IEEE80211_IF_FILE(dtim_period, u.ap.dtim_period, DEC);
+IEEE80211_IF_FILE(dtim_count, u.ap.dtim_count, DEC);
+IEEE80211_IF_FILE(num_beacons, u.ap.num_beacons, DEC);
+IEEE80211_IF_FILE(force_unicast_rateidx, u.ap.force_unicast_rateidx, DEC);
+IEEE80211_IF_FILE(max_ratectrl_rateidx, u.ap.max_ratectrl_rateidx, DEC);
+
+static ssize_t ieee80211_if_fmt_num_buffered_multicast(
+	const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
+{
+	return scnprintf(buf, buflen, "%u\n",
+			 skb_queue_len(&sdata->u.ap.ps_bc_buf));
+}
+__IEEE80211_IF_FILE(num_buffered_multicast);
+
+static ssize_t ieee80211_if_fmt_beacon_head_len(
+	const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
+{
+	if (sdata->u.ap.beacon_head)
+		return scnprintf(buf, buflen, "%d\n",
+				 sdata->u.ap.beacon_head_len);
+	return scnprintf(buf, buflen, "\n");
+}
+__IEEE80211_IF_FILE(beacon_head_len);
+
+static ssize_t ieee80211_if_fmt_beacon_tail_len(
+	const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
+{
+	if (sdata->u.ap.beacon_tail)
+		return scnprintf(buf, buflen, "%d\n",
+				 sdata->u.ap.beacon_tail_len);
+	return scnprintf(buf, buflen, "\n");
+}
+__IEEE80211_IF_FILE(beacon_tail_len);
+
+/* WDS attributes */
+IEEE80211_IF_FILE(peer, u.wds.remote_addr, MAC);
+
+/* VLAN attributes */
+IEEE80211_IF_FILE(vlan_id, u.vlan.id, DEC);
+
+/* MONITOR attributes */
+static ssize_t ieee80211_if_fmt_mode(
+	const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
+{
+	struct ieee80211_local *local = sdata->local;
+
+	return scnprintf(buf, buflen, "%s\n",
+			 ((local->hw.flags & IEEE80211_HW_MONITOR_DURING_OPER) ||
+			  local->open_count == local->monitors) ?
+			 "hard" : "soft");
+}
+__IEEE80211_IF_FILE(mode);
+
+
+#define DEBUGFS_ADD(name, type)\
+	sdata->debugfs.type.name = debugfs_create_file(#name, 0444,\
+		sdata->debugfsdir, sdata, &name##_ops);
+
+static void add_sta_files(struct ieee80211_sub_if_data *sdata)
+{
+	DEBUGFS_ADD(channel_use, sta);
+	DEBUGFS_ADD(drop_unencrypted, sta);
+	DEBUGFS_ADD(eapol, sta);
+	DEBUGFS_ADD(ieee8021_x, sta);
+	DEBUGFS_ADD(state, sta);
+	DEBUGFS_ADD(bssid, sta);
+	DEBUGFS_ADD(prev_bssid, sta);
+	DEBUGFS_ADD(ssid_len, sta);
+	DEBUGFS_ADD(aid, sta);
+	DEBUGFS_ADD(ap_capab, sta);
+	DEBUGFS_ADD(capab, sta);
+	DEBUGFS_ADD(extra_ie_len, sta);
+	DEBUGFS_ADD(auth_tries, sta);
+	DEBUGFS_ADD(assoc_tries, sta);
+	DEBUGFS_ADD(auth_algs, sta);
+	DEBUGFS_ADD(auth_alg, sta);
+	DEBUGFS_ADD(auth_transaction, sta);
+	DEBUGFS_ADD(flags, sta);
+}
+
+static void add_ap_files(struct ieee80211_sub_if_data *sdata)
+{
+	DEBUGFS_ADD(channel_use, ap);
+	DEBUGFS_ADD(drop_unencrypted, ap);
+	DEBUGFS_ADD(eapol, ap);
+	DEBUGFS_ADD(ieee8021_x, ap);
+	DEBUGFS_ADD(num_sta_ps, ap);
+	DEBUGFS_ADD(dtim_period, ap);
+	DEBUGFS_ADD(dtim_count, ap);
+	DEBUGFS_ADD(num_beacons, ap);
+	DEBUGFS_ADD(force_unicast_rateidx, ap);
+	DEBUGFS_ADD(max_ratectrl_rateidx, ap);
+	DEBUGFS_ADD(num_buffered_multicast, ap);
+	DEBUGFS_ADD(beacon_head_len, ap);
+	DEBUGFS_ADD(beacon_tail_len, ap);
+}
+
+static void add_wds_files(struct ieee80211_sub_if_data *sdata)
+{
+	DEBUGFS_ADD(channel_use, wds);
+	DEBUGFS_ADD(drop_unencrypted, wds);
+	DEBUGFS_ADD(eapol, wds);
+	DEBUGFS_ADD(ieee8021_x, wds);
+	DEBUGFS_ADD(peer, wds);
+}
+
+static void add_vlan_files(struct ieee80211_sub_if_data *sdata)
+{
+	DEBUGFS_ADD(channel_use, vlan);
+	DEBUGFS_ADD(drop_unencrypted, vlan);
+	DEBUGFS_ADD(eapol, vlan);
+	DEBUGFS_ADD(ieee8021_x, vlan);
+	DEBUGFS_ADD(vlan_id, vlan);
+}
+
+static void add_monitor_files(struct ieee80211_sub_if_data *sdata)
+{
+	DEBUGFS_ADD(mode, monitor);
+}
+
+static void add_files(struct ieee80211_sub_if_data *sdata)
+{
+	if (!sdata->debugfsdir)
+		return;
+
+	switch (sdata->type) {
+	case IEEE80211_IF_TYPE_STA:
+	case IEEE80211_IF_TYPE_IBSS:
+		add_sta_files(sdata);
+		break;
+	case IEEE80211_IF_TYPE_AP:
+		add_ap_files(sdata);
+		break;
+	case IEEE80211_IF_TYPE_WDS:
+		add_wds_files(sdata);
+		break;
+	case IEEE80211_IF_TYPE_MNTR:
+		add_monitor_files(sdata);
+		break;
+	case IEEE80211_IF_TYPE_VLAN:
+		add_vlan_files(sdata);
+		break;
+	default:
+		break;
+	}
+}
+
+#define DEBUGFS_DEL(name, type)\
+	debugfs_remove(sdata->debugfs.type.name);\
+	sdata->debugfs.type.name = NULL;
+
+static void del_sta_files(struct ieee80211_sub_if_data *sdata)
+{
+	DEBUGFS_DEL(channel_use, sta);
+	DEBUGFS_DEL(drop_unencrypted, sta);
+	DEBUGFS_DEL(eapol, sta);
+	DEBUGFS_DEL(ieee8021_x, sta);
+	DEBUGFS_DEL(state, sta);
+	DEBUGFS_DEL(bssid, sta);
+	DEBUGFS_DEL(prev_bssid, sta);
+	DEBUGFS_DEL(ssid_len, sta);
+	DEBUGFS_DEL(aid, sta);
+	DEBUGFS_DEL(ap_capab, sta);
+	DEBUGFS_DEL(capab, sta);
+	DEBUGFS_DEL(extra_ie_len, sta);
+	DEBUGFS_DEL(auth_tries, sta);
+	DEBUGFS_DEL(assoc_tries, sta);
+	DEBUGFS_DEL(auth_algs, sta);
+	DEBUGFS_DEL(auth_alg, sta);
+	DEBUGFS_DEL(auth_transaction, sta);
+	DEBUGFS_DEL(flags, sta);
+}
+
+static void del_ap_files(struct ieee80211_sub_if_data *sdata)
+{
+	DEBUGFS_DEL(channel_use, ap);
+	DEBUGFS_DEL(drop_unencrypted, ap);
+	DEBUGFS_DEL(eapol, ap);
+	DEBUGFS_DEL(ieee8021_x, ap);
+	DEBUGFS_DEL(num_sta_ps, ap);
+	DEBUGFS_DEL(dtim_period, ap);
+	DEBUGFS_DEL(dtim_count, ap);
+	DEBUGFS_DEL(num_beacons, ap);
+	DEBUGFS_DEL(force_unicast_rateidx, ap);
+	DEBUGFS_DEL(max_ratectrl_rateidx, ap);
+	DEBUGFS_DEL(num_buffered_multicast, ap);
+	DEBUGFS_DEL(beacon_head_len, ap);
+	DEBUGFS_DEL(beacon_tail_len, ap);
+}
+
+static void del_wds_files(struct ieee80211_sub_if_data *sdata)
+{
+	DEBUGFS_DEL(channel_use, wds);
+	DEBUGFS_DEL(drop_unencrypted, wds);
+	DEBUGFS_DEL(eapol, wds);
+	DEBUGFS_DEL(ieee8021_x, wds);
+	DEBUGFS_DEL(peer, wds);
+}
+
+static void del_vlan_files(struct ieee80211_sub_if_data *sdata)
+{
+	DEBUGFS_DEL(channel_use, vlan);
+	DEBUGFS_DEL(drop_unencrypted, vlan);
+	DEBUGFS_DEL(eapol, vlan);
+	DEBUGFS_DEL(ieee8021_x, vlan);
+	DEBUGFS_DEL(vlan_id, vlan);
+}
+
+static void del_monitor_files(struct ieee80211_sub_if_data *sdata)
+{
+	DEBUGFS_DEL(mode, monitor);
+}
+
+static void del_files(struct ieee80211_sub_if_data *sdata, int type)
+{
+	if (!sdata->debugfsdir)
+		return;
+
+	switch (type) {
+	case IEEE80211_IF_TYPE_STA:
+	case IEEE80211_IF_TYPE_IBSS:
+		del_sta_files(sdata);
+		break;
+	case IEEE80211_IF_TYPE_AP:
+		del_ap_files(sdata);
+		break;
+	case IEEE80211_IF_TYPE_WDS:
+		del_wds_files(sdata);
+		break;
+	case IEEE80211_IF_TYPE_MNTR:
+		del_monitor_files(sdata);
+		break;
+	case IEEE80211_IF_TYPE_VLAN:
+		del_vlan_files(sdata);
+		break;
+	default:
+		break;
+	}
+}
+
+static int notif_registered;
+
+void ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data *sdata)
+{
+	char buf[10+IFNAMSIZ];
+
+	if (!notif_registered)
+		return;
+
+	sprintf(buf, "netdev:%s", sdata->dev->name);
+	sdata->debugfsdir = debugfs_create_dir(buf,
+		sdata->local->hw.wiphy->debugfsdir);
+}
+
+void ieee80211_debugfs_remove_netdev(struct ieee80211_sub_if_data *sdata)
+{
+	del_files(sdata, sdata->type);
+	debugfs_remove(sdata->debugfsdir);
+	sdata->debugfsdir = NULL;
+}
+
+void ieee80211_debugfs_change_if_type(struct ieee80211_sub_if_data *sdata,
+				      int oldtype)
+{
+	del_files(sdata, oldtype);
+	add_files(sdata);
+}
+
+static int netdev_notify(struct notifier_block * nb,
+			 unsigned long state,
+			 void *ndev)
+{
+	struct net_device *dev = ndev;
+	char buf[10+IFNAMSIZ];
+
+	if (state != NETDEV_CHANGENAME)
+		return 0;
+
+	if (!dev->ieee80211_ptr || !dev->ieee80211_ptr->wiphy)
+		return 0;
+
+	if (dev->ieee80211_ptr->wiphy->privid != mac80211_wiphy_privid)
+		return 0;
+
+	/* TODO
+	sprintf(buf, "netdev:%s", dev->name);
+	debugfs_rename(IEEE80211_DEV_TO_SUB_IF(dev)->debugfsdir, buf);
+	*/
+
+	return 0;
+}
+
+static struct notifier_block mac80211_debugfs_netdev_notifier = {
+	.notifier_call = netdev_notify,
+};
+
+void ieee80211_debugfs_netdev_init(void)
+{
+	int err;
+
+	err = register_netdevice_notifier(&mac80211_debugfs_netdev_notifier);
+	if (err) {
+		printk(KERN_ERR
+		       "mac80211: failed to install netdev notifier,"
+		       " disabling per-netdev debugfs!\n");
+	} else
+		notif_registered = 1;
+}
+
+void ieee80211_debugfs_netdev_exit(void)
+{
+	unregister_netdevice_notifier(&mac80211_debugfs_netdev_notifier);
+	notif_registered = 0;
+}
diff --git a/net/mac80211/debugfs_netdev.h b/net/mac80211/debugfs_netdev.h
new file mode 100644
index 0000000..a690071
--- /dev/null
+++ b/net/mac80211/debugfs_netdev.h
@@ -0,0 +1,30 @@
+/* routines exported for debugfs handling */
+
+#ifndef __IEEE80211_DEBUGFS_NETDEV_H
+#define __IEEE80211_DEBUGFS_NETDEV_H
+
+#ifdef CONFIG_MAC80211_DEBUGFS
+void ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data *sdata);
+void ieee80211_debugfs_remove_netdev(struct ieee80211_sub_if_data *sdata);
+void ieee80211_debugfs_change_if_type(struct ieee80211_sub_if_data *sdata,
+				     int oldtype);
+void ieee80211_debugfs_netdev_init(void);
+void ieee80211_debugfs_netdev_exit(void);
+#else
+static inline void ieee80211_debugfs_add_netdev(
+	struct ieee80211_sub_if_data *sdata)
+{}
+static inline void ieee80211_debugfs_remove_netdev(
+	struct ieee80211_sub_if_data *sdata)
+{}
+static inline void ieee80211_debugfs_change_if_type(
+	struct ieee80211_sub_if_data *sdata, int oldtype)
+{}
+static inline void ieee80211_debugfs_netdev_init(void)
+{}
+
+static inline void ieee80211_debugfs_netdev_exit(void)
+{}
+#endif
+
+#endif /* __IEEE80211_DEBUGFS_NETDEV_H */
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c
new file mode 100644
index 0000000..d41e696
--- /dev/null
+++ b/net/mac80211/debugfs_sta.c
@@ -0,0 +1,246 @@
+/*
+ * Copyright 2003-2005	Devicescape Software, Inc.
+ * Copyright (c) 2006	Jiri Benc <jbenc@suse.cz>
+ * Copyright 2007	Johannes Berg <johannes@sipsolutions.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/debugfs.h>
+#include <linux/ieee80211.h>
+#include "ieee80211_i.h"
+#include "debugfs.h"
+#include "debugfs_sta.h"
+#include "sta_info.h"
+
+/* sta attributtes */
+
+#define STA_READ(name, buflen, field, format_string)			\
+static ssize_t sta_ ##name## _read(struct file *file,			\
+				   char __user *userbuf,		\
+				   size_t count, loff_t *ppos)		\
+{									\
+	int res;							\
+	struct sta_info *sta = file->private_data;			\
+	char buf[buflen];						\
+	res = scnprintf(buf, buflen, format_string, sta->field);	\
+	return simple_read_from_buffer(userbuf, count, ppos, buf, res);	\
+}
+#define STA_READ_D(name, field) STA_READ(name, 20, field, "%d\n")
+#define STA_READ_U(name, field) STA_READ(name, 20, field, "%u\n")
+#define STA_READ_LU(name, field) STA_READ(name, 20, field, "%lu\n")
+#define STA_READ_S(name, field) STA_READ(name, 20, field, "%s\n")
+
+#define STA_READ_RATE(name, field)					\
+static ssize_t sta_##name##_read(struct file *file,			\
+				 char __user *userbuf,			\
+				 size_t count, loff_t *ppos)		\
+{									\
+	struct sta_info *sta = file->private_data;			\
+	struct ieee80211_local *local = wdev_priv(sta->dev->ieee80211_ptr);\
+	struct ieee80211_hw_mode *mode = local->oper_hw_mode;		\
+	char buf[20];							\
+	int res = scnprintf(buf, sizeof(buf), "%d\n",			\
+			    (sta->field >= 0 &&				\
+			    sta->field < mode->num_rates) ?		\
+			    mode->rates[sta->field].rate : -1);		\
+	return simple_read_from_buffer(userbuf, count, ppos, buf, res);	\
+}
+
+#define STA_OPS(name)							\
+static const struct file_operations sta_ ##name## _ops = {		\
+	.read = sta_##name##_read,					\
+	.open = mac80211_open_file_generic,				\
+}
+
+#define STA_FILE(name, field, format)					\
+		STA_READ_##format(name, field)				\
+		STA_OPS(name)
+
+STA_FILE(aid, aid, D);
+STA_FILE(key_idx_compression, key_idx_compression, D);
+STA_FILE(dev, dev->name, S);
+STA_FILE(vlan_id, vlan_id, D);
+STA_FILE(rx_packets, rx_packets, LU);
+STA_FILE(tx_packets, tx_packets, LU);
+STA_FILE(rx_bytes, rx_bytes, LU);
+STA_FILE(tx_bytes, tx_bytes, LU);
+STA_FILE(rx_duplicates, num_duplicates, LU);
+STA_FILE(rx_fragments, rx_fragments, LU);
+STA_FILE(rx_dropped, rx_dropped, LU);
+STA_FILE(tx_fragments, tx_fragments, LU);
+STA_FILE(tx_filtered, tx_filtered_count, LU);
+STA_FILE(txrate, txrate, RATE);
+STA_FILE(last_txrate, last_txrate, RATE);
+STA_FILE(tx_retry_failed, tx_retry_failed, LU);
+STA_FILE(tx_retry_count, tx_retry_count, LU);
+STA_FILE(last_rssi, last_rssi, D);
+STA_FILE(last_signal, last_signal, D);
+STA_FILE(last_noise, last_noise, D);
+STA_FILE(channel_use, channel_use, D);
+STA_FILE(wep_weak_iv_count, wep_weak_iv_count, D);
+
+static ssize_t sta_flags_read(struct file *file, char __user *userbuf,
+			      size_t count, loff_t *ppos)
+{
+	char buf[100];
+	struct sta_info *sta = file->private_data;
+	int res = scnprintf(buf, sizeof(buf), "%s%s%s%s%s%s%s%s%s",
+		sta->flags & WLAN_STA_AUTH ? "AUTH\n" : "",
+		sta->flags & WLAN_STA_ASSOC ? "ASSOC\n" : "",
+		sta->flags & WLAN_STA_PS ? "PS\n" : "",
+		sta->flags & WLAN_STA_TIM ? "TIM\n" : "",
+		sta->flags & WLAN_STA_PERM ? "PERM\n" : "",
+		sta->flags & WLAN_STA_AUTHORIZED ? "AUTHORIZED\n" : "",
+		sta->flags & WLAN_STA_SHORT_PREAMBLE ? "SHORT PREAMBLE\n" : "",
+		sta->flags & WLAN_STA_WME ? "WME\n" : "",
+		sta->flags & WLAN_STA_WDS ? "WDS\n" : "");
+	return simple_read_from_buffer(userbuf, count, ppos, buf, res);
+}
+STA_OPS(flags);
+
+static ssize_t sta_num_ps_buf_frames_read(struct file *file,
+					  char __user *userbuf,
+					  size_t count, loff_t *ppos)
+{
+	char buf[20];
+	struct sta_info *sta = file->private_data;
+	int res = scnprintf(buf, sizeof(buf), "%u\n",
+			    skb_queue_len(&sta->ps_tx_buf));
+	return simple_read_from_buffer(userbuf, count, ppos, buf, res);
+}
+STA_OPS(num_ps_buf_frames);
+
+static ssize_t sta_last_ack_rssi_read(struct file *file, char __user *userbuf,
+				      size_t count, loff_t *ppos)
+{
+	char buf[100];
+	struct sta_info *sta = file->private_data;
+	int res = scnprintf(buf, sizeof(buf), "%d %d %d\n",
+			    sta->last_ack_rssi[0],
+			    sta->last_ack_rssi[1],
+			    sta->last_ack_rssi[2]);
+	return simple_read_from_buffer(userbuf, count, ppos, buf, res);
+}
+STA_OPS(last_ack_rssi);
+
+static ssize_t sta_last_ack_ms_read(struct file *file, char __user *userbuf,
+				    size_t count, loff_t *ppos)
+{
+	char buf[20];
+	struct sta_info *sta = file->private_data;
+	int res = scnprintf(buf, sizeof(buf), "%d\n",
+			    sta->last_ack ?
+			    jiffies_to_msecs(jiffies - sta->last_ack) : -1);
+	return simple_read_from_buffer(userbuf, count, ppos, buf, res);
+}
+STA_OPS(last_ack_ms);
+
+static ssize_t sta_inactive_ms_read(struct file *file, char __user *userbuf,
+				    size_t count, loff_t *ppos)
+{
+	char buf[20];
+	struct sta_info *sta = file->private_data;
+	int res = scnprintf(buf, sizeof(buf), "%d\n",
+			    jiffies_to_msecs(jiffies - sta->last_rx));
+	return simple_read_from_buffer(userbuf, count, ppos, buf, res);
+}
+STA_OPS(inactive_ms);
+
+static ssize_t sta_last_seq_ctrl_read(struct file *file, char __user *userbuf,
+				      size_t count, loff_t *ppos)
+{
+	char buf[15*NUM_RX_DATA_QUEUES], *p = buf;
+	int i;
+	struct sta_info *sta = file->private_data;
+	for (i = 0; i < NUM_RX_DATA_QUEUES; i++)
+		p += scnprintf(p, sizeof(buf)+buf-p, "%x ",
+			       sta->last_seq_ctrl[i]);
+	p += scnprintf(p, sizeof(buf)+buf-p, "\n");
+	return simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
+}
+STA_OPS(last_seq_ctrl);
+
+#ifdef CONFIG_MAC80211_DEBUG_COUNTERS
+static ssize_t sta_wme_rx_queue_read(struct file *file, char __user *userbuf,
+				     size_t count, loff_t *ppos)
+{
+	char buf[15*NUM_RX_DATA_QUEUES], *p = buf;
+	int i;
+	struct sta_info *sta = file->private_data;
+	for (i = 0; i < NUM_RX_DATA_QUEUES; i++)
+		p += scnprintf(p, sizeof(buf)+buf-p, "%u ",
+			       sta->wme_rx_queue[i]);
+	p += scnprintf(p, sizeof(buf)+buf-p, "\n");
+	return simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
+}
+STA_OPS(wme_rx_queue);
+
+static ssize_t sta_wme_tx_queue_read(struct file *file, char __user *userbuf,
+				     size_t count, loff_t *ppos)
+{
+	char buf[15*NUM_TX_DATA_QUEUES], *p = buf;
+	int i;
+	struct sta_info *sta = file->private_data;
+	for (i = 0; i < NUM_TX_DATA_QUEUES; i++)
+		p += scnprintf(p, sizeof(buf)+buf-p, "%u ",
+			       sta->wme_tx_queue[i]);
+	p += scnprintf(p, sizeof(buf)+buf-p, "\n");
+	return simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
+}
+STA_OPS(wme_tx_queue);
+#endif
+
+#define DEBUGFS_ADD(name) \
+	sta->debugfs.name = debugfs_create_file(#name, 0444, \
+		sta->debugfs.dir, sta, &sta_ ##name## _ops);
+
+#define DEBUGFS_DEL(name) \
+	debugfs_remove(sta->debugfs.name);\
+	sta->debugfs.name = NULL;
+
+
+void ieee80211_sta_debugfs_add(struct sta_info *sta)
+{
+	char buf[3*6];
+	struct dentry *stations_dir = sta->local->debugfs.stations;
+
+	if (!stations_dir)
+		return;
+
+	sprintf(buf, MAC_FMT, MAC_ARG(sta->addr));
+
+	sta->debugfs.dir = debugfs_create_dir(buf, stations_dir);
+	if (!sta->debugfs.dir)
+		return;
+
+	DEBUGFS_ADD(flags);
+	DEBUGFS_ADD(num_ps_buf_frames);
+	DEBUGFS_ADD(last_ack_rssi);
+	DEBUGFS_ADD(last_ack_ms);
+	DEBUGFS_ADD(inactive_ms);
+	DEBUGFS_ADD(last_seq_ctrl);
+#ifdef CONFIG_MAC80211_DEBUG_COUNTERS
+	DEBUGFS_ADD(wme_rx_queue);
+	DEBUGFS_ADD(wme_tx_queue);
+#endif
+}
+
+void ieee80211_sta_debugfs_remove(struct sta_info *sta)
+{
+	DEBUGFS_DEL(flags);
+	DEBUGFS_DEL(num_ps_buf_frames);
+	DEBUGFS_DEL(last_ack_rssi);
+	DEBUGFS_DEL(last_ack_ms);
+	DEBUGFS_DEL(inactive_ms);
+	DEBUGFS_DEL(last_seq_ctrl);
+#ifdef CONFIG_MAC80211_DEBUG_COUNTERS
+	DEBUGFS_DEL(wme_rx_queue);
+	DEBUGFS_DEL(wme_tx_queue);
+#endif
+
+	debugfs_remove(sta->debugfs.dir);
+	sta->debugfs.dir = NULL;
+}
diff --git a/net/mac80211/debugfs_sta.h b/net/mac80211/debugfs_sta.h
new file mode 100644
index 0000000..574a1cd
--- /dev/null
+++ b/net/mac80211/debugfs_sta.h
@@ -0,0 +1,12 @@
+#ifndef __MAC80211_DEBUGFS_STA_H
+#define __MAC80211_DEBUGFS_STA_H
+
+#ifdef CONFIG_MAC80211_DEBUGFS
+void ieee80211_sta_debugfs_add(struct sta_info *sta);
+void ieee80211_sta_debugfs_remove(struct sta_info *sta);
+#else
+static inline void ieee80211_sta_debugfs_add(struct sta_info *sta) {}
+static inline void ieee80211_sta_debugfs_remove(struct sta_info *sta) {}
+#endif
+
+#endif /* __MAC80211_DEBUGFS_STA_H */
diff --git a/net/mac80211/hostapd_ioctl.h b/net/mac80211/hostapd_ioctl.h
new file mode 100644
index 0000000..34fa128
--- /dev/null
+++ b/net/mac80211/hostapd_ioctl.h
@@ -0,0 +1,108 @@
+/*
+ * Host AP (software wireless LAN access point) user space daemon for
+ * Host AP kernel driver
+ * Copyright 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
+ * Copyright 2002-2004, Instant802 Networks, Inc.
+ * Copyright 2005, Devicescape Software, Inc.
+ *
+ * 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 HOSTAPD_IOCTL_H
+#define HOSTAPD_IOCTL_H
+
+#ifdef __KERNEL__
+#include <linux/types.h>
+#endif /* __KERNEL__ */
+
+#define PRISM2_IOCTL_PRISM2_PARAM (SIOCIWFIRSTPRIV + 0)
+#define PRISM2_IOCTL_GET_PRISM2_PARAM (SIOCIWFIRSTPRIV + 1)
+#define PRISM2_IOCTL_HOSTAPD (SIOCIWFIRSTPRIV + 3)
+
+/* PRISM2_IOCTL_PRISM2_PARAM ioctl() subtypes:
+ * This table is no longer added to, the whole sub-ioctl
+ * mess shall be deleted completely. */
+enum {
+	PRISM2_PARAM_IEEE_802_1X = 23,
+	PRISM2_PARAM_ANTSEL_TX = 24,
+	PRISM2_PARAM_ANTSEL_RX = 25,
+
+	/* Instant802 additions */
+	PRISM2_PARAM_CTS_PROTECT_ERP_FRAMES = 1001,
+	PRISM2_PARAM_DROP_UNENCRYPTED = 1002,
+	PRISM2_PARAM_PREAMBLE = 1003,
+	PRISM2_PARAM_SHORT_SLOT_TIME = 1006,
+	PRISM2_PARAM_NEXT_MODE = 1008,
+	PRISM2_PARAM_CLEAR_KEYS = 1009,
+	PRISM2_PARAM_RADIO_ENABLED = 1010,
+	PRISM2_PARAM_ANTENNA_MODE = 1013,
+	PRISM2_PARAM_STAT_TIME = 1016,
+	PRISM2_PARAM_STA_ANTENNA_SEL = 1017,
+	PRISM2_PARAM_FORCE_UNICAST_RATE = 1018,
+	PRISM2_PARAM_RATE_CTRL_NUM_UP = 1019,
+	PRISM2_PARAM_RATE_CTRL_NUM_DOWN = 1020,
+	PRISM2_PARAM_MAX_RATECTRL_RATE = 1021,
+	PRISM2_PARAM_TX_POWER_REDUCTION = 1022,
+	PRISM2_PARAM_KEY_TX_RX_THRESHOLD = 1024,
+	PRISM2_PARAM_DEFAULT_WEP_ONLY = 1026,
+	PRISM2_PARAM_WIFI_WME_NOACK_TEST = 1033,
+	PRISM2_PARAM_SCAN_FLAGS = 1035,
+	PRISM2_PARAM_HW_MODES = 1036,
+	PRISM2_PARAM_CREATE_IBSS = 1037,
+	PRISM2_PARAM_WMM_ENABLED = 1038,
+	PRISM2_PARAM_MIXED_CELL = 1039,
+	PRISM2_PARAM_RADAR_DETECT = 1043,
+	PRISM2_PARAM_SPECTRUM_MGMT = 1044,
+};
+
+enum {
+	IEEE80211_KEY_MGMT_NONE = 0,
+	IEEE80211_KEY_MGMT_IEEE8021X = 1,
+	IEEE80211_KEY_MGMT_WPA_PSK = 2,
+	IEEE80211_KEY_MGMT_WPA_EAP = 3,
+};
+
+
+/* Data structures used for get_hw_features ioctl */
+struct hostapd_ioctl_hw_modes_hdr {
+	int mode;
+	int num_channels;
+	int num_rates;
+};
+
+struct ieee80211_channel_data {
+	short chan; /* channel number (IEEE 802.11) */
+	short freq; /* frequency in MHz */
+	int flag; /* flag for hostapd use (IEEE80211_CHAN_*) */
+};
+
+struct ieee80211_rate_data {
+	int rate; /* rate in 100 kbps */
+	int flags; /* IEEE80211_RATE_ flags */
+};
+
+
+/* ADD_IF, REMOVE_IF, and UPDATE_IF 'type' argument */
+enum {
+	HOSTAP_IF_WDS = 1, HOSTAP_IF_VLAN = 2, HOSTAP_IF_BSS = 3,
+	HOSTAP_IF_STA = 4
+};
+
+struct hostapd_if_wds {
+	u8 remote_addr[ETH_ALEN];
+};
+
+struct hostapd_if_vlan {
+	u8 id;
+};
+
+struct hostapd_if_bss {
+	u8 bssid[ETH_ALEN];
+};
+
+struct hostapd_if_sta {
+};
+
+#endif /* HOSTAPD_IOCTL_H */
diff --git a/net/mac80211/ieee80211.c b/net/mac80211/ieee80211.c
new file mode 100644
index 0000000..6e36df6
--- /dev/null
+++ b/net/mac80211/ieee80211.c
@@ -0,0 +1,4984 @@
+/*
+ * Copyright 2002-2005, Instant802 Networks, Inc.
+ * Copyright 2005-2006, Devicescape Software, Inc.
+ * Copyright 2006-2007	Jiri Benc <jbenc@suse.cz>
+ *
+ * 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 <net/mac80211.h>
+#include <net/ieee80211_radiotap.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/skbuff.h>
+#include <linux/etherdevice.h>
+#include <linux/if_arp.h>
+#include <linux/wireless.h>
+#include <linux/rtnetlink.h>
+#include <net/iw_handler.h>
+#include <linux/compiler.h>
+#include <linux/bitmap.h>
+#include <net/cfg80211.h>
+
+#include "ieee80211_common.h"
+#include "ieee80211_i.h"
+#include "ieee80211_rate.h"
+#include "wep.h"
+#include "wpa.h"
+#include "tkip.h"
+#include "wme.h"
+#include "aes_ccm.h"
+#include "ieee80211_led.h"
+#include "ieee80211_cfg.h"
+#include "debugfs.h"
+#include "debugfs_netdev.h"
+#include "debugfs_key.h"
+
+/* privid for wiphys to determine whether they belong to us or not */
+void *mac80211_wiphy_privid = &mac80211_wiphy_privid;
+
+/* See IEEE 802.1H for LLC/SNAP encapsulation/decapsulation */
+/* Ethernet-II snap header (RFC1042 for most EtherTypes) */
+static const unsigned char rfc1042_header[] =
+	{ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
+
+/* Bridge-Tunnel header (for EtherTypes ETH_P_AARP and ETH_P_IPX) */
+static const unsigned char bridge_tunnel_header[] =
+	{ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 };
+
+/* No encapsulation header if EtherType < 0x600 (=length) */
+static const unsigned char eapol_header[] =
+	{ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, 0x88, 0x8e };
+
+
+static inline void ieee80211_include_sequence(struct ieee80211_sub_if_data *sdata,
+					      struct ieee80211_hdr *hdr)
+{
+	/* Set the sequence number for this frame. */
+	hdr->seq_ctrl = cpu_to_le16(sdata->sequence);
+
+	/* Increase the sequence number. */
+	sdata->sequence = (sdata->sequence + 0x10) & IEEE80211_SCTL_SEQ;
+}
+
+struct ieee80211_key_conf *
+ieee80211_key_data2conf(struct ieee80211_local *local,
+			const struct ieee80211_key *data)
+{
+	struct ieee80211_key_conf *conf;
+
+	conf = kmalloc(sizeof(*conf) + data->keylen, GFP_ATOMIC);
+	if (!conf)
+		return NULL;
+
+	conf->hw_key_idx = data->hw_key_idx;
+	conf->alg = data->alg;
+	conf->keylen = data->keylen;
+	conf->flags = 0;
+	if (data->force_sw_encrypt)
+		conf->flags |= IEEE80211_KEY_FORCE_SW_ENCRYPT;
+	conf->keyidx = data->keyidx;
+	if (data->default_tx_key)
+		conf->flags |= IEEE80211_KEY_DEFAULT_TX_KEY;
+	if (local->default_wep_only)
+		conf->flags |= IEEE80211_KEY_DEFAULT_WEP_ONLY;
+	memcpy(conf->key, data->key, data->keylen);
+
+	return conf;
+}
+
+struct ieee80211_key *ieee80211_key_alloc(struct ieee80211_sub_if_data *sdata,
+					  int idx, size_t key_len, gfp_t flags)
+{
+	struct ieee80211_key *key;
+
+	key = kzalloc(sizeof(struct ieee80211_key) + key_len, flags);
+	if (!key)
+		return NULL;
+	kref_init(&key->kref);
+	return key;
+}
+
+static void ieee80211_key_release(struct kref *kref)
+{
+	struct ieee80211_key *key;
+
+	key = container_of(kref, struct ieee80211_key, kref);
+	if (key->alg == ALG_CCMP)
+		ieee80211_aes_key_free(key->u.ccmp.tfm);
+	ieee80211_debugfs_key_remove(key);
+	kfree(key);
+}
+
+void ieee80211_key_free(struct ieee80211_key *key)
+{
+	if (key)
+		kref_put(&key->kref, ieee80211_key_release);
+}
+
+static int rate_list_match(const int *rate_list, int rate)
+{
+	int i;
+
+	if (!rate_list)
+		return 0;
+
+	for (i = 0; rate_list[i] >= 0; i++)
+		if (rate_list[i] == rate)
+			return 1;
+
+	return 0;
+}
+
+
+void ieee80211_prepare_rates(struct ieee80211_local *local,
+			     struct ieee80211_hw_mode *mode)
+{
+	int i;
+
+	for (i = 0; i < mode->num_rates; i++) {
+		struct ieee80211_rate *rate = &mode->rates[i];
+
+		rate->flags &= ~(IEEE80211_RATE_SUPPORTED |
+				 IEEE80211_RATE_BASIC);
+
+		if (local->supp_rates[mode->mode]) {
+			if (!rate_list_match(local->supp_rates[mode->mode],
+					     rate->rate))
+				continue;
+		}
+
+		rate->flags |= IEEE80211_RATE_SUPPORTED;
+
+		/* Use configured basic rate set if it is available. If not,
+		 * use defaults that are sane for most cases. */
+		if (local->basic_rates[mode->mode]) {
+			if (rate_list_match(local->basic_rates[mode->mode],
+					    rate->rate))
+				rate->flags |= IEEE80211_RATE_BASIC;
+		} else switch (mode->mode) {
+		case MODE_IEEE80211A:
+			if (rate->rate == 60 || rate->rate == 120 ||
+			    rate->rate == 240)
+				rate->flags |= IEEE80211_RATE_BASIC;
+			break;
+		case MODE_IEEE80211B:
+			if (rate->rate == 10 || rate->rate == 20)
+				rate->flags |= IEEE80211_RATE_BASIC;
+			break;
+		case MODE_ATHEROS_TURBO:
+			if (rate->rate == 120 || rate->rate == 240 ||
+			    rate->rate == 480)
+				rate->flags |= IEEE80211_RATE_BASIC;
+			break;
+		case MODE_IEEE80211G:
+			if (rate->rate == 10 || rate->rate == 20 ||
+			    rate->rate == 55 || rate->rate == 110)
+				rate->flags |= IEEE80211_RATE_BASIC;
+			break;
+		}
+
+		/* Set ERP and MANDATORY flags based on phymode */
+		switch (mode->mode) {
+		case MODE_IEEE80211A:
+			if (rate->rate == 60 || rate->rate == 120 ||
+			    rate->rate == 240)
+				rate->flags |= IEEE80211_RATE_MANDATORY;
+			break;
+		case MODE_IEEE80211B:
+			if (rate->rate == 10)
+				rate->flags |= IEEE80211_RATE_MANDATORY;
+			break;
+		case MODE_ATHEROS_TURBO:
+			break;
+		case MODE_IEEE80211G:
+			if (rate->rate == 10 || rate->rate == 20 ||
+			    rate->rate == 55 || rate->rate == 110 ||
+			    rate->rate == 60 || rate->rate == 120 ||
+			    rate->rate == 240)
+				rate->flags |= IEEE80211_RATE_MANDATORY;
+			break;
+		}
+		if (ieee80211_is_erp_rate(mode->mode, rate->rate))
+			rate->flags |= IEEE80211_RATE_ERP;
+	}
+}
+
+
+static void ieee80211_key_threshold_notify(struct net_device *dev,
+					   struct ieee80211_key *key,
+					   struct sta_info *sta)
+{
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+	struct sk_buff *skb;
+	struct ieee80211_msg_key_notification *msg;
+
+	/* if no one will get it anyway, don't even allocate it.
+	 * unlikely because this is only relevant for APs
+	 * where the device must be open... */
+	if (unlikely(!local->apdev))
+		return;
+
+	skb = dev_alloc_skb(sizeof(struct ieee80211_frame_info) +
+			    sizeof(struct ieee80211_msg_key_notification));
+	if (!skb)
+		return;
+
+	skb_reserve(skb, sizeof(struct ieee80211_frame_info));
+	msg = (struct ieee80211_msg_key_notification *)
+		skb_put(skb, sizeof(struct ieee80211_msg_key_notification));
+	msg->tx_rx_count = key->tx_rx_count;
+	memcpy(msg->ifname, dev->name, IFNAMSIZ);
+	if (sta)
+		memcpy(msg->addr, sta->addr, ETH_ALEN);
+	else
+		memset(msg->addr, 0xff, ETH_ALEN);
+
+	key->tx_rx_count = 0;
+
+	ieee80211_rx_mgmt(local, skb, NULL,
+			  ieee80211_msg_key_threshold_notification);
+}
+
+
+static u8 * ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len)
+{
+	u16 fc;
+
+	if (len < 24)
+		return NULL;
+
+	fc = le16_to_cpu(hdr->frame_control);
+
+	switch (fc & IEEE80211_FCTL_FTYPE) {
+	case IEEE80211_FTYPE_DATA:
+		switch (fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) {
+		case IEEE80211_FCTL_TODS:
+			return hdr->addr1;
+		case (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS):
+			return NULL;
+		case IEEE80211_FCTL_FROMDS:
+			return hdr->addr2;
+		case 0:
+			return hdr->addr3;
+		}
+		break;
+	case IEEE80211_FTYPE_MGMT:
+		return hdr->addr3;
+	case IEEE80211_FTYPE_CTL:
+		if ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PSPOLL)
+			return hdr->addr1;
+		else
+			return NULL;
+	}
+
+	return NULL;
+}
+
+int ieee80211_get_hdrlen(u16 fc)
+{
+	int hdrlen = 24;
+
+	switch (fc & IEEE80211_FCTL_FTYPE) {
+	case IEEE80211_FTYPE_DATA:
+		if ((fc & IEEE80211_FCTL_FROMDS) && (fc & IEEE80211_FCTL_TODS))
+			hdrlen = 30; /* Addr4 */
+		/*
+		 * The QoS Control field is two bytes and its presence is
+		 * indicated by the IEEE80211_STYPE_QOS_DATA bit. Add 2 to
+		 * hdrlen if that bit is set.
+		 * This works by masking out the bit and shifting it to
+		 * bit position 1 so the result has the value 0 or 2.
+		 */
+		hdrlen += (fc & IEEE80211_STYPE_QOS_DATA)
+				>> (ilog2(IEEE80211_STYPE_QOS_DATA)-1);
+		break;
+	case IEEE80211_FTYPE_CTL:
+		/*
+		 * ACK and CTS are 10 bytes, all others 16. To see how
+		 * to get this condition consider
+		 *   subtype mask:   0b0000000011110000 (0x00F0)
+		 *   ACK subtype:    0b0000000011010000 (0x00D0)
+		 *   CTS subtype:    0b0000000011000000 (0x00C0)
+		 *   bits that matter:         ^^^      (0x00E0)
+		 *   value of those: 0b0000000011000000 (0x00C0)
+		 */
+		if ((fc & 0xE0) == 0xC0)
+			hdrlen = 10;
+		else
+			hdrlen = 16;
+		break;
+	}
+
+	return hdrlen;
+}
+EXPORT_SYMBOL(ieee80211_get_hdrlen);
+
+int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb)
+{
+	const struct ieee80211_hdr *hdr = (const struct ieee80211_hdr *) skb->data;
+	int hdrlen;
+
+	if (unlikely(skb->len < 10))
+		return 0;
+	hdrlen = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_control));
+	if (unlikely(hdrlen > skb->len))
+		return 0;
+	return hdrlen;
+}
+EXPORT_SYMBOL(ieee80211_get_hdrlen_from_skb);
+
+static int ieee80211_get_radiotap_len(struct sk_buff *skb)
+{
+	struct ieee80211_radiotap_header *hdr =
+		(struct ieee80211_radiotap_header *) skb->data;
+
+	return le16_to_cpu(hdr->it_len);
+}
+
+#ifdef CONFIG_MAC80211_LOWTX_FRAME_DUMP
+static void ieee80211_dump_frame(const char *ifname, const char *title,
+				 const struct sk_buff *skb)
+{
+	const struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+	u16 fc;
+	int hdrlen;
+
+	printk(KERN_DEBUG "%s: %s (len=%d)", ifname, title, skb->len);
+	if (skb->len < 4) {
+		printk("\n");
+		return;
+	}
+
+	fc = le16_to_cpu(hdr->frame_control);
+	hdrlen = ieee80211_get_hdrlen(fc);
+	if (hdrlen > skb->len)
+		hdrlen = skb->len;
+	if (hdrlen >= 4)
+		printk(" FC=0x%04x DUR=0x%04x",
+		       fc, le16_to_cpu(hdr->duration_id));
+	if (hdrlen >= 10)
+		printk(" A1=" MAC_FMT, MAC_ARG(hdr->addr1));
+	if (hdrlen >= 16)
+		printk(" A2=" MAC_FMT, MAC_ARG(hdr->addr2));
+	if (hdrlen >= 24)
+		printk(" A3=" MAC_FMT, MAC_ARG(hdr->addr3));
+	if (hdrlen >= 30)
+		printk(" A4=" MAC_FMT, MAC_ARG(hdr->addr4));
+	printk("\n");
+}
+#else /* CONFIG_MAC80211_LOWTX_FRAME_DUMP */
+static inline void ieee80211_dump_frame(const char *ifname, const char *title,
+					struct sk_buff *skb)
+{
+}
+#endif /* CONFIG_MAC80211_LOWTX_FRAME_DUMP */
+
+
+static int ieee80211_is_eapol(const struct sk_buff *skb)
+{
+	const struct ieee80211_hdr *hdr;
+	u16 fc;
+	int hdrlen;
+
+	if (unlikely(skb->len < 10))
+		return 0;
+
+	hdr = (const struct ieee80211_hdr *) skb->data;
+	fc = le16_to_cpu(hdr->frame_control);
+
+	if (unlikely(!WLAN_FC_DATA_PRESENT(fc)))
+		return 0;
+
+	hdrlen = ieee80211_get_hdrlen(fc);
+
+	if (unlikely(skb->len >= hdrlen + sizeof(eapol_header) &&
+		     memcmp(skb->data + hdrlen, eapol_header,
+			    sizeof(eapol_header)) == 0))
+		return 1;
+
+	return 0;
+}
+
+
+static ieee80211_txrx_result
+ieee80211_tx_h_rate_ctrl(struct ieee80211_txrx_data *tx)
+{
+	struct rate_control_extra extra;
+
+	memset(&extra, 0, sizeof(extra));
+	extra.mode = tx->u.tx.mode;
+	extra.mgmt_data = tx->sdata &&
+		tx->sdata->type == IEEE80211_IF_TYPE_MGMT;
+	extra.ethertype = tx->ethertype;
+
+	tx->u.tx.rate = rate_control_get_rate(tx->local, tx->dev, tx->skb,
+					      &extra);
+	if (unlikely(extra.probe != NULL)) {
+		tx->u.tx.control->flags |= IEEE80211_TXCTL_RATE_CTRL_PROBE;
+		tx->u.tx.probe_last_frag = 1;
+		tx->u.tx.control->alt_retry_rate = tx->u.tx.rate->val;
+		tx->u.tx.rate = extra.probe;
+	} else {
+		tx->u.tx.control->alt_retry_rate = -1;
+	}
+	if (!tx->u.tx.rate)
+		return TXRX_DROP;
+	if (tx->u.tx.mode->mode == MODE_IEEE80211G &&
+	    tx->local->cts_protect_erp_frames && tx->fragmented &&
+	    extra.nonerp) {
+		tx->u.tx.last_frag_rate = tx->u.tx.rate;
+		tx->u.tx.probe_last_frag = extra.probe ? 1 : 0;
+
+		tx->u.tx.rate = extra.nonerp;
+		tx->u.tx.control->rate = extra.nonerp;
+		tx->u.tx.control->flags &= ~IEEE80211_TXCTL_RATE_CTRL_PROBE;
+	} else {
+		tx->u.tx.last_frag_rate = tx->u.tx.rate;
+		tx->u.tx.control->rate = tx->u.tx.rate;
+	}
+	tx->u.tx.control->tx_rate = tx->u.tx.rate->val;
+	if ((tx->u.tx.rate->flags & IEEE80211_RATE_PREAMBLE2) &&
+	    tx->local->short_preamble &&
+	    (!tx->sta || (tx->sta->flags & WLAN_STA_SHORT_PREAMBLE))) {
+		tx->u.tx.short_preamble = 1;
+		tx->u.tx.control->tx_rate = tx->u.tx.rate->val2;
+	}
+
+	return TXRX_CONTINUE;
+}
+
+
+static ieee80211_txrx_result
+ieee80211_tx_h_select_key(struct ieee80211_txrx_data *tx)
+{
+	if (tx->sta)
+		tx->u.tx.control->key_idx = tx->sta->key_idx_compression;
+	else
+		tx->u.tx.control->key_idx = HW_KEY_IDX_INVALID;
+
+	if (unlikely(tx->u.tx.control->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT))
+		tx->key = NULL;
+	else if (tx->sta && tx->sta->key)
+		tx->key = tx->sta->key;
+	else if (tx->sdata->default_key)
+		tx->key = tx->sdata->default_key;
+	else if (tx->sdata->drop_unencrypted &&
+		 !(tx->sdata->eapol && ieee80211_is_eapol(tx->skb))) {
+		I802_DEBUG_INC(tx->local->tx_handlers_drop_unencrypted);
+		return TXRX_DROP;
+	} else
+		tx->key = NULL;
+
+	if (tx->key) {
+		tx->key->tx_rx_count++;
+		if (unlikely(tx->local->key_tx_rx_threshold &&
+			     tx->key->tx_rx_count >
+			     tx->local->key_tx_rx_threshold)) {
+			ieee80211_key_threshold_notify(tx->dev, tx->key,
+						       tx->sta);
+		}
+	}
+
+	return TXRX_CONTINUE;
+}
+
+
+static ieee80211_txrx_result
+ieee80211_tx_h_fragment(struct ieee80211_txrx_data *tx)
+{
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx->skb->data;
+	size_t hdrlen, per_fragm, num_fragm, payload_len, left;
+	struct sk_buff **frags, *first, *frag;
+	int i;
+	u16 seq;
+	u8 *pos;
+	int frag_threshold = tx->local->fragmentation_threshold;
+
+	if (!tx->fragmented)
+		return TXRX_CONTINUE;
+
+	first = tx->skb;
+
+	hdrlen = ieee80211_get_hdrlen(tx->fc);
+	payload_len = first->len - hdrlen;
+	per_fragm = frag_threshold - hdrlen - FCS_LEN;
+	num_fragm = (payload_len + per_fragm - 1) / per_fragm;
+
+	frags = kzalloc(num_fragm * sizeof(struct sk_buff *), GFP_ATOMIC);
+	if (!frags)
+		goto fail;
+
+	hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREFRAGS);
+	seq = le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ;
+	pos = first->data + hdrlen + per_fragm;
+	left = payload_len - per_fragm;
+	for (i = 0; i < num_fragm - 1; i++) {
+		struct ieee80211_hdr *fhdr;
+		size_t copylen;
+
+		if (left <= 0)
+			goto fail;
+
+		/* reserve enough extra head and tail room for possible
+		 * encryption */
+		frag = frags[i] =
+			dev_alloc_skb(tx->local->hw.extra_tx_headroom +
+				      frag_threshold +
+				      IEEE80211_ENCRYPT_HEADROOM +
+				      IEEE80211_ENCRYPT_TAILROOM);
+		if (!frag)
+			goto fail;
+		/* Make sure that all fragments use the same priority so
+		 * that they end up using the same TX queue */
+		frag->priority = first->priority;
+		skb_reserve(frag, tx->local->hw.extra_tx_headroom +
+			IEEE80211_ENCRYPT_HEADROOM);
+		fhdr = (struct ieee80211_hdr *) skb_put(frag, hdrlen);
+		memcpy(fhdr, first->data, hdrlen);
+		if (i == num_fragm - 2)
+			fhdr->frame_control &= cpu_to_le16(~IEEE80211_FCTL_MOREFRAGS);
+		fhdr->seq_ctrl = cpu_to_le16(seq | ((i + 1) & IEEE80211_SCTL_FRAG));
+		copylen = left > per_fragm ? per_fragm : left;
+		memcpy(skb_put(frag, copylen), pos, copylen);
+
+		pos += copylen;
+		left -= copylen;
+	}
+	skb_trim(first, hdrlen + per_fragm);
+
+	tx->u.tx.num_extra_frag = num_fragm - 1;
+	tx->u.tx.extra_frag = frags;
+
+	return TXRX_CONTINUE;
+
+ fail:
+	printk(KERN_DEBUG "%s: failed to fragment frame\n", tx->dev->name);
+	if (frags) {
+		for (i = 0; i < num_fragm - 1; i++)
+			if (frags[i])
+				dev_kfree_skb(frags[i]);
+		kfree(frags);
+	}
+	I802_DEBUG_INC(tx->local->tx_handlers_drop_fragment);
+	return TXRX_DROP;
+}
+
+
+static int wep_encrypt_skb(struct ieee80211_txrx_data *tx, struct sk_buff *skb)
+{
+	if (tx->key->force_sw_encrypt) {
+		if (ieee80211_wep_encrypt(tx->local, skb, tx->key))
+			return -1;
+	} else {
+		tx->u.tx.control->key_idx = tx->key->hw_key_idx;
+		if (tx->local->hw.flags & IEEE80211_HW_WEP_INCLUDE_IV) {
+			if (ieee80211_wep_add_iv(tx->local, skb, tx->key) ==
+			    NULL)
+				return -1;
+		}
+	}
+	return 0;
+}
+
+
+void ieee80211_tx_set_iswep(struct ieee80211_txrx_data *tx)
+{
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx->skb->data;
+
+	hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
+	if (tx->u.tx.extra_frag) {
+		struct ieee80211_hdr *fhdr;
+		int i;
+		for (i = 0; i < tx->u.tx.num_extra_frag; i++) {
+			fhdr = (struct ieee80211_hdr *)
+				tx->u.tx.extra_frag[i]->data;
+			fhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
+		}
+	}
+}
+
+
+static ieee80211_txrx_result
+ieee80211_tx_h_wep_encrypt(struct ieee80211_txrx_data *tx)
+{
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx->skb->data;
+	u16 fc;
+
+	fc = le16_to_cpu(hdr->frame_control);
+
+	if (!tx->key || tx->key->alg != ALG_WEP ||
+	    ((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA &&
+	     ((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_MGMT ||
+	      (fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_AUTH)))
+		return TXRX_CONTINUE;
+
+	tx->u.tx.control->iv_len = WEP_IV_LEN;
+	tx->u.tx.control->icv_len = WEP_ICV_LEN;
+	ieee80211_tx_set_iswep(tx);
+
+	if (wep_encrypt_skb(tx, tx->skb) < 0) {
+		I802_DEBUG_INC(tx->local->tx_handlers_drop_wep);
+		return TXRX_DROP;
+	}
+
+	if (tx->u.tx.extra_frag) {
+		int i;
+		for (i = 0; i < tx->u.tx.num_extra_frag; i++) {
+			if (wep_encrypt_skb(tx, tx->u.tx.extra_frag[i]) < 0) {
+				I802_DEBUG_INC(tx->local->
+					       tx_handlers_drop_wep);
+				return TXRX_DROP;
+			}
+		}
+	}
+
+	return TXRX_CONTINUE;
+}
+
+
+static int ieee80211_frame_duration(struct ieee80211_local *local, size_t len,
+				    int rate, int erp, int short_preamble)
+{
+	int dur;
+
+	/* calculate duration (in microseconds, rounded up to next higher
+	 * integer if it includes a fractional microsecond) to send frame of
+	 * len bytes (does not include FCS) at the given rate. Duration will
+	 * also include SIFS.
+	 *
+	 * rate is in 100 kbps, so divident is multiplied by 10 in the
+	 * DIV_ROUND_UP() operations.
+	 */
+
+	if (local->hw.conf.phymode == MODE_IEEE80211A || erp ||
+	    local->hw.conf.phymode == MODE_ATHEROS_TURBO) {
+		/*
+		 * OFDM:
+		 *
+		 * N_DBPS = DATARATE x 4
+		 * N_SYM = Ceiling((16+8xLENGTH+6) / N_DBPS)
+		 *	(16 = SIGNAL time, 6 = tail bits)
+		 * TXTIME = T_PREAMBLE + T_SIGNAL + T_SYM x N_SYM + Signal Ext
+		 *
+		 * T_SYM = 4 usec
+		 * 802.11a - 17.5.2: aSIFSTime = 16 usec
+		 * 802.11g - 19.8.4: aSIFSTime = 10 usec +
+		 *	signal ext = 6 usec
+		 */
+		/* FIX: Atheros Turbo may have different (shorter) duration? */
+		dur = 16; /* SIFS + signal ext */
+		dur += 16; /* 17.3.2.3: T_PREAMBLE = 16 usec */
+		dur += 4; /* 17.3.2.3: T_SIGNAL = 4 usec */
+		dur += 4 * DIV_ROUND_UP((16 + 8 * (len + 4) + 6) * 10,
+					4 * rate); /* T_SYM x N_SYM */
+	} else {
+		/*
+		 * 802.11b or 802.11g with 802.11b compatibility:
+		 * 18.3.4: TXTIME = PreambleLength + PLCPHeaderTime +
+		 * Ceiling(((LENGTH+PBCC)x8)/DATARATE). PBCC=0.
+		 *
+		 * 802.11 (DS): 15.3.3, 802.11b: 18.3.4
+		 * aSIFSTime = 10 usec
+		 * aPreambleLength = 144 usec or 72 usec with short preamble
+		 * aPLCPHeaderLength = 48 usec or 24 usec with short preamble
+		 */
+		dur = 10; /* aSIFSTime = 10 usec */
+		dur += short_preamble ? (72 + 24) : (144 + 48);
+
+		dur += DIV_ROUND_UP(8 * (len + 4) * 10, rate);
+	}
+
+	return dur;
+}
+
+
+/* Exported duration function for driver use */
+__le16 ieee80211_generic_frame_duration(struct ieee80211_hw *hw,
+					size_t frame_len, int rate)
+{
+	struct ieee80211_local *local = hw_to_local(hw);
+	u16 dur;
+	int erp;
+
+	erp = ieee80211_is_erp_rate(hw->conf.phymode, rate);
+	dur = ieee80211_frame_duration(local, frame_len, rate,
+				       erp, local->short_preamble);
+
+	return cpu_to_le16(dur);
+}
+EXPORT_SYMBOL(ieee80211_generic_frame_duration);
+
+
+static u16 ieee80211_duration(struct ieee80211_txrx_data *tx, int group_addr,
+			      int next_frag_len)
+{
+	int rate, mrate, erp, dur, i;
+	struct ieee80211_rate *txrate = tx->u.tx.rate;
+	struct ieee80211_local *local = tx->local;
+	struct ieee80211_hw_mode *mode = tx->u.tx.mode;
+
+	erp = txrate->flags & IEEE80211_RATE_ERP;
+
+	/*
+	 * data and mgmt (except PS Poll):
+	 * - during CFP: 32768
+	 * - during contention period:
+	 *   if addr1 is group address: 0
+	 *   if more fragments = 0 and addr1 is individual address: time to
+	 *      transmit one ACK plus SIFS
+	 *   if more fragments = 1 and addr1 is individual address: time to
+	 *      transmit next fragment plus 2 x ACK plus 3 x SIFS
+	 *
+	 * IEEE 802.11, 9.6:
+	 * - control response frame (CTS or ACK) shall be transmitted using the
+	 *   same rate as the immediately previous frame in the frame exchange
+	 *   sequence, if this rate belongs to the PHY mandatory rates, or else
+	 *   at the highest possible rate belonging to the PHY rates in the
+	 *   BSSBasicRateSet
+	 */
+
+	if ((tx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL) {
+		/* TODO: These control frames are not currently sent by
+		 * 80211.o, but should they be implemented, this function
+		 * needs to be updated to support duration field calculation.
+		 *
+		 * RTS: time needed to transmit pending data/mgmt frame plus
+		 *    one CTS frame plus one ACK frame plus 3 x SIFS
+		 * CTS: duration of immediately previous RTS minus time
+		 *    required to transmit CTS and its SIFS
+		 * ACK: 0 if immediately previous directed data/mgmt had
+		 *    more=0, with more=1 duration in ACK frame is duration
+		 *    from previous frame minus time needed to transmit ACK
+		 *    and its SIFS
+		 * PS Poll: BIT(15) | BIT(14) | aid
+		 */
+		return 0;
+	}
+
+	/* data/mgmt */
+	if (0 /* FIX: data/mgmt during CFP */)
+		return 32768;
+
+	if (group_addr) /* Group address as the destination - no ACK */
+		return 0;
+
+	/* Individual destination address:
+	 * IEEE 802.11, Ch. 9.6 (after IEEE 802.11g changes)
+	 * CTS and ACK frames shall be transmitted using the highest rate in
+	 * basic rate set that is less than or equal to the rate of the
+	 * immediately previous frame and that is using the same modulation
+	 * (CCK or OFDM). If no basic rate set matches with these requirements,
+	 * the highest mandatory rate of the PHY that is less than or equal to
+	 * the rate of the previous frame is used.
+	 * Mandatory rates for IEEE 802.11g PHY: 1, 2, 5.5, 11, 6, 12, 24 Mbps
+	 */
+	rate = -1;
+	mrate = 10; /* use 1 Mbps if everything fails */
+	for (i = 0; i < mode->num_rates; i++) {
+		struct ieee80211_rate *r = &mode->rates[i];
+		if (r->rate > txrate->rate)
+			break;
+
+		if (IEEE80211_RATE_MODULATION(txrate->flags) !=
+		    IEEE80211_RATE_MODULATION(r->flags))
+			continue;
+
+		if (r->flags & IEEE80211_RATE_BASIC)
+			rate = r->rate;
+		else if (r->flags & IEEE80211_RATE_MANDATORY)
+			mrate = r->rate;
+	}
+	if (rate == -1) {
+		/* No matching basic rate found; use highest suitable mandatory
+		 * PHY rate */
+		rate = mrate;
+	}
+
+	/* Time needed to transmit ACK
+	 * (10 bytes + 4-byte FCS = 112 bits) plus SIFS; rounded up
+	 * to closest integer */
+
+	dur = ieee80211_frame_duration(local, 10, rate, erp,
+				       local->short_preamble);
+
+	if (next_frag_len) {
+		/* Frame is fragmented: duration increases with time needed to
+		 * transmit next fragment plus ACK and 2 x SIFS. */
+		dur *= 2; /* ACK + SIFS */
+		/* next fragment */
+		dur += ieee80211_frame_duration(local, next_frag_len,
+						txrate->rate, erp,
+						local->short_preamble);
+	}
+
+	return dur;
+}
+
+
+static ieee80211_txrx_result
+ieee80211_tx_h_misc(struct ieee80211_txrx_data *tx)
+{
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx->skb->data;
+	u16 dur;
+	struct ieee80211_tx_control *control = tx->u.tx.control;
+	struct ieee80211_hw_mode *mode = tx->u.tx.mode;
+
+	if (!is_multicast_ether_addr(hdr->addr1)) {
+		if (tx->skb->len + FCS_LEN > tx->local->rts_threshold &&
+		    tx->local->rts_threshold < IEEE80211_MAX_RTS_THRESHOLD) {
+			control->flags |= IEEE80211_TXCTL_USE_RTS_CTS;
+			control->retry_limit =
+				tx->local->long_retry_limit;
+		} else {
+			control->retry_limit =
+				tx->local->short_retry_limit;
+		}
+	} else {
+		control->retry_limit = 1;
+	}
+
+	if (tx->fragmented) {
+		/* Do not use multiple retry rates when sending fragmented
+		 * frames.
+		 * TODO: The last fragment could still use multiple retry
+		 * rates. */
+		control->alt_retry_rate = -1;
+	}
+
+	/* Use CTS protection for unicast frames sent using extended rates if
+	 * there are associated non-ERP stations and RTS/CTS is not configured
+	 * for the frame. */
+	if (mode->mode == MODE_IEEE80211G &&
+	    (tx->u.tx.rate->flags & IEEE80211_RATE_ERP) &&
+	    tx->u.tx.unicast &&
+	    tx->local->cts_protect_erp_frames &&
+	    !(control->flags & IEEE80211_TXCTL_USE_RTS_CTS))
+		control->flags |= IEEE80211_TXCTL_USE_CTS_PROTECT;
+
+	/* Setup duration field for the first fragment of the frame. Duration
+	 * for remaining fragments will be updated when they are being sent
+	 * to low-level driver in ieee80211_tx(). */
+	dur = ieee80211_duration(tx, is_multicast_ether_addr(hdr->addr1),
+				 tx->fragmented ? tx->u.tx.extra_frag[0]->len :
+				 0);
+	hdr->duration_id = cpu_to_le16(dur);
+
+	if ((control->flags & IEEE80211_TXCTL_USE_RTS_CTS) ||
+	    (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT)) {
+		struct ieee80211_rate *rate;
+
+		/* Do not use multiple retry rates when using RTS/CTS */
+		control->alt_retry_rate = -1;
+
+		/* Use min(data rate, max base rate) as CTS/RTS rate */
+		rate = tx->u.tx.rate;
+		while (rate > mode->rates &&
+		       !(rate->flags & IEEE80211_RATE_BASIC))
+			rate--;
+
+		control->rts_cts_rate = rate->val;
+		control->rts_rate = rate;
+	}
+
+	if (tx->sta) {
+		tx->sta->tx_packets++;
+		tx->sta->tx_fragments++;
+		tx->sta->tx_bytes += tx->skb->len;
+		if (tx->u.tx.extra_frag) {
+			int i;
+			tx->sta->tx_fragments += tx->u.tx.num_extra_frag;
+			for (i = 0; i < tx->u.tx.num_extra_frag; i++) {
+				tx->sta->tx_bytes +=
+					tx->u.tx.extra_frag[i]->len;
+			}
+		}
+	}
+
+	return TXRX_CONTINUE;
+}
+
+
+static ieee80211_txrx_result
+ieee80211_tx_h_check_assoc(struct ieee80211_txrx_data *tx)
+{
+#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
+	struct sk_buff *skb = tx->skb;
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
+	u32 sta_flags;
+
+	if (unlikely(tx->local->sta_scanning != 0) &&
+	    ((tx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_MGMT ||
+	     (tx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_PROBE_REQ))
+		return TXRX_DROP;
+
+	if (tx->u.tx.ps_buffered)
+		return TXRX_CONTINUE;
+
+	sta_flags = tx->sta ? tx->sta->flags : 0;
+
+	if (likely(tx->u.tx.unicast)) {
+		if (unlikely(!(sta_flags & WLAN_STA_ASSOC) &&
+			     tx->sdata->type != IEEE80211_IF_TYPE_IBSS &&
+			     (tx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA)) {
+#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
+			printk(KERN_DEBUG "%s: dropped data frame to not "
+			       "associated station " MAC_FMT "\n",
+			       tx->dev->name, MAC_ARG(hdr->addr1));
+#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
+			I802_DEBUG_INC(tx->local->tx_handlers_drop_not_assoc);
+			return TXRX_DROP;
+		}
+	} else {
+		if (unlikely((tx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA &&
+			     tx->local->num_sta == 0 &&
+			     !tx->local->allow_broadcast_always &&
+			     tx->sdata->type != IEEE80211_IF_TYPE_IBSS)) {
+			/*
+			 * No associated STAs - no need to send multicast
+			 * frames.
+			 */
+			return TXRX_DROP;
+		}
+		return TXRX_CONTINUE;
+	}
+
+	if (unlikely(!tx->u.tx.mgmt_interface && tx->sdata->ieee802_1x &&
+		     !(sta_flags & WLAN_STA_AUTHORIZED))) {
+#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
+		printk(KERN_DEBUG "%s: dropped frame to " MAC_FMT
+		       " (unauthorized port)\n", tx->dev->name,
+		       MAC_ARG(hdr->addr1));
+#endif
+		I802_DEBUG_INC(tx->local->tx_handlers_drop_unauth_port);
+		return TXRX_DROP;
+	}
+
+	return TXRX_CONTINUE;
+}
+
+static ieee80211_txrx_result
+ieee80211_tx_h_sequence(struct ieee80211_txrx_data *tx)
+{
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
+
+	if (ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_control)) >= 24)
+		ieee80211_include_sequence(tx->sdata, hdr);
+
+	return TXRX_CONTINUE;
+}
+
+/* This function is called whenever the AP is about to exceed the maximum limit
+ * of buffered frames for power saving STAs. This situation should not really
+ * happen often during normal operation, so dropping the oldest buffered packet
+ * from each queue should be OK to make some room for new frames. */
+static void purge_old_ps_buffers(struct ieee80211_local *local)
+{
+	int total = 0, purged = 0;
+	struct sk_buff *skb;
+	struct ieee80211_sub_if_data *sdata;
+	struct sta_info *sta;
+
+	read_lock(&local->sub_if_lock);
+	list_for_each_entry(sdata, &local->sub_if_list, list) {
+		struct ieee80211_if_ap *ap;
+		if (sdata->dev == local->mdev ||
+		    sdata->type != IEEE80211_IF_TYPE_AP)
+			continue;
+		ap = &sdata->u.ap;
+		skb = skb_dequeue(&ap->ps_bc_buf);
+		if (skb) {
+			purged++;
+			dev_kfree_skb(skb);
+		}
+		total += skb_queue_len(&ap->ps_bc_buf);
+	}
+	read_unlock(&local->sub_if_lock);
+
+	spin_lock_bh(&local->sta_lock);
+	list_for_each_entry(sta, &local->sta_list, list) {
+		skb = skb_dequeue(&sta->ps_tx_buf);
+		if (skb) {
+			purged++;
+			dev_kfree_skb(skb);
+		}
+		total += skb_queue_len(&sta->ps_tx_buf);
+	}
+	spin_unlock_bh(&local->sta_lock);
+
+	local->total_ps_buffered = total;
+	printk(KERN_DEBUG "%s: PS buffers full - purged %d frames\n",
+	       local->mdev->name, purged);
+}
+
+
+static inline ieee80211_txrx_result
+ieee80211_tx_h_multicast_ps_buf(struct ieee80211_txrx_data *tx)
+{
+	/* broadcast/multicast frame */
+	/* If any of the associated stations is in power save mode,
+	 * the frame is buffered to be sent after DTIM beacon frame */
+	if ((tx->local->hw.flags & IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING) &&
+	    tx->sdata->type != IEEE80211_IF_TYPE_WDS &&
+	    tx->sdata->bss && atomic_read(&tx->sdata->bss->num_sta_ps) &&
+	    !(tx->fc & IEEE80211_FCTL_ORDER)) {
+		if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER)
+			purge_old_ps_buffers(tx->local);
+		if (skb_queue_len(&tx->sdata->bss->ps_bc_buf) >=
+		    AP_MAX_BC_BUFFER) {
+			if (net_ratelimit()) {
+				printk(KERN_DEBUG "%s: BC TX buffer full - "
+				       "dropping the oldest frame\n",
+				       tx->dev->name);
+			}
+			dev_kfree_skb(skb_dequeue(&tx->sdata->bss->ps_bc_buf));
+		} else
+			tx->local->total_ps_buffered++;
+		skb_queue_tail(&tx->sdata->bss->ps_bc_buf, tx->skb);
+		return TXRX_QUEUED;
+	}
+
+	return TXRX_CONTINUE;
+}
+
+
+static inline ieee80211_txrx_result
+ieee80211_tx_h_unicast_ps_buf(struct ieee80211_txrx_data *tx)
+{
+	struct sta_info *sta = tx->sta;
+
+	if (unlikely(!sta ||
+		     ((tx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT &&
+		      (tx->fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PROBE_RESP)))
+		return TXRX_CONTINUE;
+
+	if (unlikely((sta->flags & WLAN_STA_PS) && !sta->pspoll)) {
+		struct ieee80211_tx_packet_data *pkt_data;
+#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
+		printk(KERN_DEBUG "STA " MAC_FMT " aid %d: PS buffer (entries "
+		       "before %d)\n",
+		       MAC_ARG(sta->addr), sta->aid,
+		       skb_queue_len(&sta->ps_tx_buf));
+#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
+		sta->flags |= WLAN_STA_TIM;
+		if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER)
+			purge_old_ps_buffers(tx->local);
+		if (skb_queue_len(&sta->ps_tx_buf) >= STA_MAX_TX_BUFFER) {
+			struct sk_buff *old = skb_dequeue(&sta->ps_tx_buf);
+			if (net_ratelimit()) {
+				printk(KERN_DEBUG "%s: STA " MAC_FMT " TX "
+				       "buffer full - dropping oldest frame\n",
+				       tx->dev->name, MAC_ARG(sta->addr));
+			}
+			dev_kfree_skb(old);
+		} else
+			tx->local->total_ps_buffered++;
+		/* Queue frame to be sent after STA sends an PS Poll frame */
+		if (skb_queue_empty(&sta->ps_tx_buf)) {
+			if (tx->local->ops->set_tim)
+				tx->local->ops->set_tim(local_to_hw(tx->local),
+						       sta->aid, 1);
+			if (tx->sdata->bss)
+				bss_tim_set(tx->local, tx->sdata->bss, sta->aid);
+		}
+		pkt_data = (struct ieee80211_tx_packet_data *)tx->skb->cb;
+		pkt_data->jiffies = jiffies;
+		skb_queue_tail(&sta->ps_tx_buf, tx->skb);
+		return TXRX_QUEUED;
+	}
+#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
+	else if (unlikely(sta->flags & WLAN_STA_PS)) {
+		printk(KERN_DEBUG "%s: STA " MAC_FMT " in PS mode, but pspoll "
+		       "set -> send frame\n", tx->dev->name,
+		       MAC_ARG(sta->addr));
+	}
+#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
+	sta->pspoll = 0;
+
+	return TXRX_CONTINUE;
+}
+
+
+static ieee80211_txrx_result
+ieee80211_tx_h_ps_buf(struct ieee80211_txrx_data *tx)
+{
+	if (unlikely(tx->u.tx.ps_buffered))
+		return TXRX_CONTINUE;
+
+	if (tx->u.tx.unicast)
+		return ieee80211_tx_h_unicast_ps_buf(tx);
+	else
+		return ieee80211_tx_h_multicast_ps_buf(tx);
+}
+
+
+static void inline
+__ieee80211_tx_prepare(struct ieee80211_txrx_data *tx,
+		       struct sk_buff *skb,
+		       struct net_device *dev,
+		       struct ieee80211_tx_control *control)
+{
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+	int hdrlen;
+
+	memset(tx, 0, sizeof(*tx));
+	tx->skb = skb;
+	tx->dev = dev; /* use original interface */
+	tx->local = local;
+	tx->sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	tx->sta = sta_info_get(local, hdr->addr1);
+	tx->fc = le16_to_cpu(hdr->frame_control);
+	control->power_level = local->hw.conf.power_level;
+	tx->u.tx.control = control;
+	tx->u.tx.unicast = !is_multicast_ether_addr(hdr->addr1);
+	if (is_multicast_ether_addr(hdr->addr1))
+		control->flags |= IEEE80211_TXCTL_NO_ACK;
+	else
+		control->flags &= ~IEEE80211_TXCTL_NO_ACK;
+	tx->fragmented = local->fragmentation_threshold <
+		IEEE80211_MAX_FRAG_THRESHOLD && tx->u.tx.unicast &&
+		skb->len + FCS_LEN > local->fragmentation_threshold &&
+		(!local->ops->set_frag_threshold);
+	if (!tx->sta)
+		control->flags |= IEEE80211_TXCTL_CLEAR_DST_MASK;
+	else if (tx->sta->clear_dst_mask) {
+		control->flags |= IEEE80211_TXCTL_CLEAR_DST_MASK;
+		tx->sta->clear_dst_mask = 0;
+	}
+	control->antenna_sel_tx = local->hw.conf.antenna_sel_tx;
+	if (local->sta_antenna_sel != STA_ANTENNA_SEL_AUTO && tx->sta)
+		control->antenna_sel_tx = tx->sta->antenna_sel_tx;
+	hdrlen = ieee80211_get_hdrlen(tx->fc);
+	if (skb->len > hdrlen + sizeof(rfc1042_header) + 2) {
+		u8 *pos = &skb->data[hdrlen + sizeof(rfc1042_header)];
+		tx->ethertype = (pos[0] << 8) | pos[1];
+	}
+	control->flags |= IEEE80211_TXCTL_FIRST_FRAGMENT;
+
+}
+
+static int inline is_ieee80211_device(struct net_device *dev,
+				      struct net_device *master)
+{
+	return (wdev_priv(dev->ieee80211_ptr) ==
+		wdev_priv(master->ieee80211_ptr));
+}
+
+/* Device in tx->dev has a reference added; use dev_put(tx->dev) when
+ * finished with it. */
+static int inline ieee80211_tx_prepare(struct ieee80211_txrx_data *tx,
+				       struct sk_buff *skb,
+				       struct net_device *mdev,
+				       struct ieee80211_tx_control *control)
+{
+	struct ieee80211_tx_packet_data *pkt_data;
+	struct net_device *dev;
+
+	pkt_data = (struct ieee80211_tx_packet_data *)skb->cb;
+	dev = dev_get_by_index(pkt_data->ifindex);
+	if (unlikely(dev && !is_ieee80211_device(dev, mdev))) {
+		dev_put(dev);
+		dev = NULL;
+	}
+	if (unlikely(!dev))
+		return -ENODEV;
+	__ieee80211_tx_prepare(tx, skb, dev, control);
+	return 0;
+}
+
+static inline int __ieee80211_queue_stopped(const struct ieee80211_local *local,
+					    int queue)
+{
+	return test_bit(IEEE80211_LINK_STATE_XOFF, &local->state[queue]);
+}
+
+static inline int __ieee80211_queue_pending(const struct ieee80211_local *local,
+					    int queue)
+{
+	return test_bit(IEEE80211_LINK_STATE_PENDING, &local->state[queue]);
+}
+
+#define IEEE80211_TX_OK		0
+#define IEEE80211_TX_AGAIN	1
+#define IEEE80211_TX_FRAG_AGAIN	2
+
+static int __ieee80211_tx(struct ieee80211_local *local, struct sk_buff *skb,
+			  struct ieee80211_txrx_data *tx)
+{
+	struct ieee80211_tx_control *control = tx->u.tx.control;
+	int ret, i;
+
+	if (!ieee80211_qdisc_installed(local->mdev) &&
+	    __ieee80211_queue_stopped(local, 0)) {
+		netif_stop_queue(local->mdev);
+		return IEEE80211_TX_AGAIN;
+	}
+	if (skb) {
+		ieee80211_dump_frame(local->mdev->name, "TX to low-level driver", skb);
+		ret = local->ops->tx(local_to_hw(local), skb, control);
+		if (ret)
+			return IEEE80211_TX_AGAIN;
+		local->mdev->trans_start = jiffies;
+		ieee80211_led_tx(local, 1);
+	}
+	if (tx->u.tx.extra_frag) {
+		control->flags &= ~(IEEE80211_TXCTL_USE_RTS_CTS |
+				    IEEE80211_TXCTL_USE_CTS_PROTECT |
+				    IEEE80211_TXCTL_CLEAR_DST_MASK |
+				    IEEE80211_TXCTL_FIRST_FRAGMENT);
+		for (i = 0; i < tx->u.tx.num_extra_frag; i++) {
+			if (!tx->u.tx.extra_frag[i])
+				continue;
+			if (__ieee80211_queue_stopped(local, control->queue))
+				return IEEE80211_TX_FRAG_AGAIN;
+			if (i == tx->u.tx.num_extra_frag) {
+				control->tx_rate = tx->u.tx.last_frag_hwrate;
+				control->rate = tx->u.tx.last_frag_rate;
+				if (tx->u.tx.probe_last_frag)
+					control->flags |=
+						IEEE80211_TXCTL_RATE_CTRL_PROBE;
+				else
+					control->flags &=
+						~IEEE80211_TXCTL_RATE_CTRL_PROBE;
+			}
+
+			ieee80211_dump_frame(local->mdev->name,
+					     "TX to low-level driver",
+					     tx->u.tx.extra_frag[i]);
+			ret = local->ops->tx(local_to_hw(local),
+					    tx->u.tx.extra_frag[i],
+					    control);
+			if (ret)
+				return IEEE80211_TX_FRAG_AGAIN;
+			local->mdev->trans_start = jiffies;
+			ieee80211_led_tx(local, 1);
+			tx->u.tx.extra_frag[i] = NULL;
+		}
+		kfree(tx->u.tx.extra_frag);
+		tx->u.tx.extra_frag = NULL;
+	}
+	return IEEE80211_TX_OK;
+}
+
+static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb,
+			struct ieee80211_tx_control *control, int mgmt)
+{
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+	struct sta_info *sta;
+	ieee80211_tx_handler *handler;
+	struct ieee80211_txrx_data tx;
+	ieee80211_txrx_result res = TXRX_DROP;
+	int ret, i;
+
+	WARN_ON(__ieee80211_queue_pending(local, control->queue));
+
+	if (unlikely(skb->len < 10)) {
+		dev_kfree_skb(skb);
+		return 0;
+	}
+
+	__ieee80211_tx_prepare(&tx, skb, dev, control);
+	sta = tx.sta;
+	tx.u.tx.mgmt_interface = mgmt;
+	tx.u.tx.mode = local->hw.conf.mode;
+
+	for (handler = local->tx_handlers; *handler != NULL; handler++) {
+		res = (*handler)(&tx);
+		if (res != TXRX_CONTINUE)
+			break;
+	}
+
+	skb = tx.skb; /* handlers are allowed to change skb */
+
+	if (sta)
+		sta_info_put(sta);
+
+	if (unlikely(res == TXRX_DROP)) {
+		I802_DEBUG_INC(local->tx_handlers_drop);
+		goto drop;
+	}
+
+	if (unlikely(res == TXRX_QUEUED)) {
+		I802_DEBUG_INC(local->tx_handlers_queued);
+		return 0;
+	}
+
+	if (tx.u.tx.extra_frag) {
+		for (i = 0; i < tx.u.tx.num_extra_frag; i++) {
+			int next_len, dur;
+			struct ieee80211_hdr *hdr =
+				(struct ieee80211_hdr *)
+				tx.u.tx.extra_frag[i]->data;
+
+			if (i + 1 < tx.u.tx.num_extra_frag) {
+				next_len = tx.u.tx.extra_frag[i + 1]->len;
+			} else {
+				next_len = 0;
+				tx.u.tx.rate = tx.u.tx.last_frag_rate;
+				tx.u.tx.last_frag_hwrate = tx.u.tx.rate->val;
+			}
+			dur = ieee80211_duration(&tx, 0, next_len);
+			hdr->duration_id = cpu_to_le16(dur);
+		}
+	}
+
+retry:
+	ret = __ieee80211_tx(local, skb, &tx);
+	if (ret) {
+		struct ieee80211_tx_stored_packet *store =
+			&local->pending_packet[control->queue];
+
+		if (ret == IEEE80211_TX_FRAG_AGAIN)
+			skb = NULL;
+		set_bit(IEEE80211_LINK_STATE_PENDING,
+			&local->state[control->queue]);
+		smp_mb();
+		/* When the driver gets out of buffers during sending of
+		 * fragments and calls ieee80211_stop_queue, there is
+		 * a small window between IEEE80211_LINK_STATE_XOFF and
+		 * IEEE80211_LINK_STATE_PENDING flags are set. If a buffer
+		 * gets available in that window (i.e. driver calls
+		 * ieee80211_wake_queue), we would end up with ieee80211_tx
+		 * called with IEEE80211_LINK_STATE_PENDING. Prevent this by
+		 * continuing transmitting here when that situation is
+		 * possible to have happened. */
+		if (!__ieee80211_queue_stopped(local, control->queue)) {
+			clear_bit(IEEE80211_LINK_STATE_PENDING,
+				  &local->state[control->queue]);
+			goto retry;
+		}
+		memcpy(&store->control, control,
+		       sizeof(struct ieee80211_tx_control));
+		store->skb = skb;
+		store->extra_frag = tx.u.tx.extra_frag;
+		store->num_extra_frag = tx.u.tx.num_extra_frag;
+		store->last_frag_hwrate = tx.u.tx.last_frag_hwrate;
+		store->last_frag_rate = tx.u.tx.last_frag_rate;
+		store->last_frag_rate_ctrl_probe = tx.u.tx.probe_last_frag;
+	}
+	return 0;
+
+ drop:
+	if (skb)
+		dev_kfree_skb(skb);
+	for (i = 0; i < tx.u.tx.num_extra_frag; i++)
+		if (tx.u.tx.extra_frag[i])
+			dev_kfree_skb(tx.u.tx.extra_frag[i]);
+	kfree(tx.u.tx.extra_frag);
+	return 0;
+}
+
+static void ieee80211_tx_pending(unsigned long data)
+{
+	struct ieee80211_local *local = (struct ieee80211_local *)data;
+	struct net_device *dev = local->mdev;
+	struct ieee80211_tx_stored_packet *store;
+	struct ieee80211_txrx_data tx;
+	int i, ret, reschedule = 0;
+
+	netif_tx_lock_bh(dev);
+	for (i = 0; i < local->hw.queues; i++) {
+		if (__ieee80211_queue_stopped(local, i))
+			continue;
+		if (!__ieee80211_queue_pending(local, i)) {
+			reschedule = 1;
+			continue;
+		}
+		store = &local->pending_packet[i];
+		tx.u.tx.control = &store->control;
+		tx.u.tx.extra_frag = store->extra_frag;
+		tx.u.tx.num_extra_frag = store->num_extra_frag;
+		tx.u.tx.last_frag_hwrate = store->last_frag_hwrate;
+		tx.u.tx.last_frag_rate = store->last_frag_rate;
+		tx.u.tx.probe_last_frag = store->last_frag_rate_ctrl_probe;
+		ret = __ieee80211_tx(local, store->skb, &tx);
+		if (ret) {
+			if (ret == IEEE80211_TX_FRAG_AGAIN)
+				store->skb = NULL;
+		} else {
+			clear_bit(IEEE80211_LINK_STATE_PENDING,
+				  &local->state[i]);
+			reschedule = 1;
+		}
+	}
+	netif_tx_unlock_bh(dev);
+	if (reschedule) {
+		if (!ieee80211_qdisc_installed(dev)) {
+			if (!__ieee80211_queue_stopped(local, 0))
+				netif_wake_queue(dev);
+		} else
+			netif_schedule(dev);
+	}
+}
+
+static void ieee80211_clear_tx_pending(struct ieee80211_local *local)
+{
+	int i, j;
+	struct ieee80211_tx_stored_packet *store;
+
+	for (i = 0; i < local->hw.queues; i++) {
+		if (!__ieee80211_queue_pending(local, i))
+			continue;
+		store = &local->pending_packet[i];
+		kfree_skb(store->skb);
+		for (j = 0; j < store->num_extra_frag; j++)
+			kfree_skb(store->extra_frag[j]);
+		kfree(store->extra_frag);
+		clear_bit(IEEE80211_LINK_STATE_PENDING, &local->state[i]);
+	}
+}
+
+static int ieee80211_master_start_xmit(struct sk_buff *skb,
+				       struct net_device *dev)
+{
+	struct ieee80211_tx_control control;
+	struct ieee80211_tx_packet_data *pkt_data;
+	struct net_device *odev = NULL;
+	struct ieee80211_sub_if_data *osdata;
+	int headroom;
+	int ret;
+
+	/*
+	 * copy control out of the skb so other people can use skb->cb
+	 */
+	pkt_data = (struct ieee80211_tx_packet_data *)skb->cb;
+	memset(&control, 0, sizeof(struct ieee80211_tx_control));
+
+	if (pkt_data->ifindex)
+		odev = dev_get_by_index(pkt_data->ifindex);
+	if (unlikely(odev && !is_ieee80211_device(odev, dev))) {
+		dev_put(odev);
+		odev = NULL;
+	}
+	if (unlikely(!odev)) {
+#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
+		printk(KERN_DEBUG "%s: Discarded packet with nonexistent "
+		       "originating device\n", dev->name);
+#endif
+		dev_kfree_skb(skb);
+		return 0;
+	}
+	osdata = IEEE80211_DEV_TO_SUB_IF(odev);
+
+	headroom = osdata->local->hw.extra_tx_headroom +
+		IEEE80211_ENCRYPT_HEADROOM;
+	if (skb_headroom(skb) < headroom) {
+		if (pskb_expand_head(skb, headroom, 0, GFP_ATOMIC)) {
+			dev_kfree_skb(skb);
+			return 0;
+		}
+	}
+
+	control.ifindex = odev->ifindex;
+	control.type = osdata->type;
+	if (pkt_data->req_tx_status)
+		control.flags |= IEEE80211_TXCTL_REQ_TX_STATUS;
+	if (pkt_data->do_not_encrypt)
+		control.flags |= IEEE80211_TXCTL_DO_NOT_ENCRYPT;
+	if (pkt_data->requeue)
+		control.flags |= IEEE80211_TXCTL_REQUEUE;
+	control.queue = pkt_data->queue;
+
+	ret = ieee80211_tx(odev, skb, &control,
+			   control.type == IEEE80211_IF_TYPE_MGMT);
+	dev_put(odev);
+
+	return ret;
+}
+
+
+/**
+ * ieee80211_subif_start_xmit - netif start_xmit function for Ethernet-type
+ * subinterfaces (wlan#, WDS, and VLAN interfaces)
+ * @skb: packet to be sent
+ * @dev: incoming interface
+ *
+ * Returns: 0 on success (and frees skb in this case) or 1 on failure (skb will
+ * not be freed, and caller is responsible for either retrying later or freeing
+ * skb).
+ *
+ * This function takes in an Ethernet header and encapsulates it with suitable
+ * IEEE 802.11 header based on which interface the packet is coming in. The
+ * encapsulated packet will then be passed to master interface, wlan#.11, for
+ * transmission (through low-level driver).
+ */
+static int ieee80211_subif_start_xmit(struct sk_buff *skb,
+				      struct net_device *dev)
+{
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+	struct ieee80211_tx_packet_data *pkt_data;
+	struct ieee80211_sub_if_data *sdata;
+	int ret = 1, head_need;
+	u16 ethertype, hdrlen, fc;
+	struct ieee80211_hdr hdr;
+	const u8 *encaps_data;
+	int encaps_len, skip_header_bytes;
+	int nh_pos, h_pos, no_encrypt = 0;
+	struct sta_info *sta;
+
+	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	if (unlikely(skb->len < ETH_HLEN)) {
+		printk(KERN_DEBUG "%s: short skb (len=%d)\n",
+		       dev->name, skb->len);
+		ret = 0;
+		goto fail;
+	}
+
+	nh_pos = skb_network_header(skb) - skb->data;
+	h_pos = skb_transport_header(skb) - skb->data;
+
+	/* convert Ethernet header to proper 802.11 header (based on
+	 * operation mode) */
+	ethertype = (skb->data[12] << 8) | skb->data[13];
+	/* TODO: handling for 802.1x authorized/unauthorized port */
+	fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA;
+
+	if (likely(sdata->type == IEEE80211_IF_TYPE_AP ||
+		   sdata->type == IEEE80211_IF_TYPE_VLAN)) {
+		fc |= IEEE80211_FCTL_FROMDS;
+		/* DA BSSID SA */
+		memcpy(hdr.addr1, skb->data, ETH_ALEN);
+		memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN);
+		memcpy(hdr.addr3, skb->data + ETH_ALEN, ETH_ALEN);
+		hdrlen = 24;
+	} else if (sdata->type == IEEE80211_IF_TYPE_WDS) {
+		fc |= IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS;
+		/* RA TA DA SA */
+		memcpy(hdr.addr1, sdata->u.wds.remote_addr, ETH_ALEN);
+		memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN);
+		memcpy(hdr.addr3, skb->data, ETH_ALEN);
+		memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN);
+		hdrlen = 30;
+	} else if (sdata->type == IEEE80211_IF_TYPE_STA) {
+		fc |= IEEE80211_FCTL_TODS;
+		/* BSSID SA DA */
+		memcpy(hdr.addr1, sdata->u.sta.bssid, ETH_ALEN);
+		memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN);
+		memcpy(hdr.addr3, skb->data, ETH_ALEN);
+		hdrlen = 24;
+	} else if (sdata->type == IEEE80211_IF_TYPE_IBSS) {
+		/* DA SA BSSID */
+		memcpy(hdr.addr1, skb->data, ETH_ALEN);
+		memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN);
+		memcpy(hdr.addr3, sdata->u.sta.bssid, ETH_ALEN);
+		hdrlen = 24;
+	} else {
+		ret = 0;
+		goto fail;
+	}
+
+	/* receiver is QoS enabled, use a QoS type frame */
+	sta = sta_info_get(local, hdr.addr1);
+	if (sta) {
+		if (sta->flags & WLAN_STA_WME) {
+			fc |= IEEE80211_STYPE_QOS_DATA;
+			hdrlen += 2;
+		}
+		sta_info_put(sta);
+	}
+
+	hdr.frame_control = cpu_to_le16(fc);
+	hdr.duration_id = 0;
+	hdr.seq_ctrl = 0;
+
+	skip_header_bytes = ETH_HLEN;
+	if (ethertype == ETH_P_AARP || ethertype == ETH_P_IPX) {
+		encaps_data = bridge_tunnel_header;
+		encaps_len = sizeof(bridge_tunnel_header);
+		skip_header_bytes -= 2;
+	} else if (ethertype >= 0x600) {
+		encaps_data = rfc1042_header;
+		encaps_len = sizeof(rfc1042_header);
+		skip_header_bytes -= 2;
+	} else {
+		encaps_data = NULL;
+		encaps_len = 0;
+	}
+
+	skb_pull(skb, skip_header_bytes);
+	nh_pos -= skip_header_bytes;
+	h_pos -= skip_header_bytes;
+
+	/* TODO: implement support for fragments so that there is no need to
+	 * reallocate and copy payload; it might be enough to support one
+	 * extra fragment that would be copied in the beginning of the frame
+	 * data.. anyway, it would be nice to include this into skb structure
+	 * somehow
+	 *
+	 * There are few options for this:
+	 * use skb->cb as an extra space for 802.11 header
+	 * allocate new buffer if not enough headroom
+	 * make sure that there is enough headroom in every skb by increasing
+	 * build in headroom in __dev_alloc_skb() (linux/skbuff.h) and
+	 * alloc_skb() (net/core/skbuff.c)
+	 */
+	head_need = hdrlen + encaps_len + local->hw.extra_tx_headroom;
+	head_need -= skb_headroom(skb);
+
+	/* We are going to modify skb data, so make a copy of it if happens to
+	 * be cloned. This could happen, e.g., with Linux bridge code passing
+	 * us broadcast frames. */
+
+	if (head_need > 0 || skb_cloned(skb)) {
+#if 0
+		printk(KERN_DEBUG "%s: need to reallocate buffer for %d bytes "
+		       "of headroom\n", dev->name, head_need);
+#endif
+
+		if (skb_cloned(skb))
+			I802_DEBUG_INC(local->tx_expand_skb_head_cloned);
+		else
+			I802_DEBUG_INC(local->tx_expand_skb_head);
+		/* Since we have to reallocate the buffer, make sure that there
+		 * is enough room for possible WEP IV/ICV and TKIP (8 bytes
+		 * before payload and 12 after). */
+		if (pskb_expand_head(skb, (head_need > 0 ? head_need + 8 : 8),
+				     12, GFP_ATOMIC)) {
+			printk(KERN_DEBUG "%s: failed to reallocate TX buffer"
+			       "\n", dev->name);
+			goto fail;
+		}
+	}
+
+	if (encaps_data) {
+		memcpy(skb_push(skb, encaps_len), encaps_data, encaps_len);
+		nh_pos += encaps_len;
+		h_pos += encaps_len;
+	}
+	memcpy(skb_push(skb, hdrlen), &hdr, hdrlen);
+	nh_pos += hdrlen;
+	h_pos += hdrlen;
+
+	pkt_data = (struct ieee80211_tx_packet_data *)skb->cb;
+	memset(pkt_data, 0, sizeof(struct ieee80211_tx_packet_data));
+	pkt_data->ifindex = sdata->dev->ifindex;
+	pkt_data->mgmt_iface = (sdata->type == IEEE80211_IF_TYPE_MGMT);
+	pkt_data->do_not_encrypt = no_encrypt;
+
+	skb->dev = local->mdev;
+	sdata->stats.tx_packets++;
+	sdata->stats.tx_bytes += skb->len;
+
+	/* Update skb pointers to various headers since this modified frame
+	 * is going to go through Linux networking code that may potentially
+	 * need things like pointer to IP header. */
+	skb_set_mac_header(skb, 0);
+	skb_set_network_header(skb, nh_pos);
+	skb_set_transport_header(skb, h_pos);
+
+	dev->trans_start = jiffies;
+	dev_queue_xmit(skb);
+
+	return 0;
+
+ fail:
+	if (!ret)
+		dev_kfree_skb(skb);
+
+	return ret;
+}
+
+
+/*
+ * This is the transmit routine for the 802.11 type interfaces
+ * called by upper layers of the linux networking
+ * stack when it has a frame to transmit
+ */
+static int
+ieee80211_mgmt_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct ieee80211_sub_if_data *sdata;
+	struct ieee80211_tx_packet_data *pkt_data;
+	struct ieee80211_hdr *hdr;
+	u16 fc;
+
+	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+
+	if (skb->len < 10) {
+		dev_kfree_skb(skb);
+		return 0;
+	}
+
+	if (skb_headroom(skb) < sdata->local->hw.extra_tx_headroom) {
+		if (pskb_expand_head(skb,
+		    sdata->local->hw.extra_tx_headroom, 0, GFP_ATOMIC)) {
+			dev_kfree_skb(skb);
+			return 0;
+		}
+	}
+
+	hdr = (struct ieee80211_hdr *) skb->data;
+	fc = le16_to_cpu(hdr->frame_control);
+
+	pkt_data = (struct ieee80211_tx_packet_data *) skb->cb;
+	memset(pkt_data, 0, sizeof(struct ieee80211_tx_packet_data));
+	pkt_data->ifindex = sdata->dev->ifindex;
+	pkt_data->mgmt_iface = (sdata->type == IEEE80211_IF_TYPE_MGMT);
+
+	skb->priority = 20; /* use hardcoded priority for mgmt TX queue */
+	skb->dev = sdata->local->mdev;
+
+	/*
+	 * We're using the protocol field of the the frame control header
+	 * to request TX callback for hostapd. BIT(1) is checked.
+	 */
+	if ((fc & BIT(1)) == BIT(1)) {
+		pkt_data->req_tx_status = 1;
+		fc &= ~BIT(1);
+		hdr->frame_control = cpu_to_le16(fc);
+	}
+
+	pkt_data->do_not_encrypt = !(fc & IEEE80211_FCTL_PROTECTED);
+
+	sdata->stats.tx_packets++;
+	sdata->stats.tx_bytes += skb->len;
+
+	dev_queue_xmit(skb);
+
+	return 0;
+}
+
+
+static void ieee80211_beacon_add_tim(struct ieee80211_local *local,
+				     struct ieee80211_if_ap *bss,
+				     struct sk_buff *skb)
+{
+	u8 *pos, *tim;
+	int aid0 = 0;
+	int i, have_bits = 0, n1, n2;
+
+	/* Generate bitmap for TIM only if there are any STAs in power save
+	 * mode. */
+	spin_lock_bh(&local->sta_lock);
+	if (atomic_read(&bss->num_sta_ps) > 0)
+		/* in the hope that this is faster than
+		 * checking byte-for-byte */
+		have_bits = !bitmap_empty((unsigned long*)bss->tim,
+					  IEEE80211_MAX_AID+1);
+
+	if (bss->dtim_count == 0)
+		bss->dtim_count = bss->dtim_period - 1;
+	else
+		bss->dtim_count--;
+
+	tim = pos = (u8 *) skb_put(skb, 6);
+	*pos++ = WLAN_EID_TIM;
+	*pos++ = 4;
+	*pos++ = bss->dtim_count;
+	*pos++ = bss->dtim_period;
+
+	if (bss->dtim_count == 0 && !skb_queue_empty(&bss->ps_bc_buf))
+		aid0 = 1;
+
+	if (have_bits) {
+		/* Find largest even number N1 so that bits numbered 1 through
+		 * (N1 x 8) - 1 in the bitmap are 0 and number N2 so that bits
+		 * (N2 + 1) x 8 through 2007 are 0. */
+		n1 = 0;
+		for (i = 0; i < IEEE80211_MAX_TIM_LEN; i++) {
+			if (bss->tim[i]) {
+				n1 = i & 0xfe;
+				break;
+			}
+		}
+		n2 = n1;
+		for (i = IEEE80211_MAX_TIM_LEN - 1; i >= n1; i--) {
+			if (bss->tim[i]) {
+				n2 = i;
+				break;
+			}
+		}
+
+		/* Bitmap control */
+		*pos++ = n1 | aid0;
+		/* Part Virt Bitmap */
+		memcpy(pos, bss->tim + n1, n2 - n1 + 1);
+
+		tim[1] = n2 - n1 + 4;
+		skb_put(skb, n2 - n1);
+	} else {
+		*pos++ = aid0; /* Bitmap control */
+		*pos++ = 0; /* Part Virt Bitmap */
+	}
+	spin_unlock_bh(&local->sta_lock);
+}
+
+
+struct sk_buff * ieee80211_beacon_get(struct ieee80211_hw *hw, int if_id,
+				      struct ieee80211_tx_control *control)
+{
+	struct ieee80211_local *local = hw_to_local(hw);
+	struct sk_buff *skb;
+	struct net_device *bdev;
+	struct ieee80211_sub_if_data *sdata = NULL;
+	struct ieee80211_if_ap *ap = NULL;
+	struct ieee80211_rate *rate;
+	struct rate_control_extra extra;
+	u8 *b_head, *b_tail;
+	int bh_len, bt_len;
+
+	bdev = dev_get_by_index(if_id);
+	if (bdev) {
+		sdata = IEEE80211_DEV_TO_SUB_IF(bdev);
+		ap = &sdata->u.ap;
+		dev_put(bdev);
+	}
+
+	if (!ap || sdata->type != IEEE80211_IF_TYPE_AP ||
+	    !ap->beacon_head) {
+#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
+		if (net_ratelimit())
+			printk(KERN_DEBUG "no beacon data avail for idx=%d "
+			       "(%s)\n", if_id, bdev ? bdev->name : "N/A");
+#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
+		return NULL;
+	}
+
+	/* Assume we are generating the normal beacon locally */
+	b_head = ap->beacon_head;
+	b_tail = ap->beacon_tail;
+	bh_len = ap->beacon_head_len;
+	bt_len = ap->beacon_tail_len;
+
+	skb = dev_alloc_skb(local->hw.extra_tx_headroom +
+		bh_len + bt_len + 256 /* maximum TIM len */);
+	if (!skb)
+		return NULL;
+
+	skb_reserve(skb, local->hw.extra_tx_headroom);
+	memcpy(skb_put(skb, bh_len), b_head, bh_len);
+
+	ieee80211_include_sequence(sdata, (struct ieee80211_hdr *)skb->data);
+
+	ieee80211_beacon_add_tim(local, ap, skb);
+
+	if (b_tail) {
+		memcpy(skb_put(skb, bt_len), b_tail, bt_len);
+	}
+
+	if (control) {
+		memset(&extra, 0, sizeof(extra));
+		extra.mode = local->oper_hw_mode;
+
+		rate = rate_control_get_rate(local, local->mdev, skb, &extra);
+		if (!rate) {
+			if (net_ratelimit()) {
+				printk(KERN_DEBUG "%s: ieee80211_beacon_get: no rate "
+				       "found\n", local->mdev->name);
+			}
+			dev_kfree_skb(skb);
+			return NULL;
+		}
+
+		control->tx_rate = (local->short_preamble &&
+				    (rate->flags & IEEE80211_RATE_PREAMBLE2)) ?
+			rate->val2 : rate->val;
+		control->antenna_sel_tx = local->hw.conf.antenna_sel_tx;
+		control->power_level = local->hw.conf.power_level;
+		control->flags |= IEEE80211_TXCTL_NO_ACK;
+		control->retry_limit = 1;
+		control->flags |= IEEE80211_TXCTL_CLEAR_DST_MASK;
+	}
+
+	ap->num_beacons++;
+	return skb;
+}
+EXPORT_SYMBOL(ieee80211_beacon_get);
+
+__le16 ieee80211_rts_duration(struct ieee80211_hw *hw,
+			      size_t frame_len,
+			      const struct ieee80211_tx_control *frame_txctl)
+{
+	struct ieee80211_local *local = hw_to_local(hw);
+	struct ieee80211_rate *rate;
+	int short_preamble = local->short_preamble;
+	int erp;
+	u16 dur;
+
+	rate = frame_txctl->rts_rate;
+	erp = !!(rate->flags & IEEE80211_RATE_ERP);
+
+	/* CTS duration */
+	dur = ieee80211_frame_duration(local, 10, rate->rate,
+				       erp, short_preamble);
+	/* Data frame duration */
+	dur += ieee80211_frame_duration(local, frame_len, rate->rate,
+					erp, short_preamble);
+	/* ACK duration */
+	dur += ieee80211_frame_duration(local, 10, rate->rate,
+					erp, short_preamble);
+
+	return cpu_to_le16(dur);
+}
+EXPORT_SYMBOL(ieee80211_rts_duration);
+
+
+__le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw,
+				    size_t frame_len,
+				    const struct ieee80211_tx_control *frame_txctl)
+{
+	struct ieee80211_local *local = hw_to_local(hw);
+	struct ieee80211_rate *rate;
+	int short_preamble = local->short_preamble;
+	int erp;
+	u16 dur;
+
+	rate = frame_txctl->rts_rate;
+	erp = !!(rate->flags & IEEE80211_RATE_ERP);
+
+	/* Data frame duration */
+	dur = ieee80211_frame_duration(local, frame_len, rate->rate,
+				       erp, short_preamble);
+	if (!(frame_txctl->flags & IEEE80211_TXCTL_NO_ACK)) {
+		/* ACK duration */
+		dur += ieee80211_frame_duration(local, 10, rate->rate,
+						erp, short_preamble);
+	}
+
+	return cpu_to_le16(dur);
+}
+EXPORT_SYMBOL(ieee80211_ctstoself_duration);
+
+void ieee80211_rts_get(struct ieee80211_hw *hw,
+		       const void *frame, size_t frame_len,
+		       const struct ieee80211_tx_control *frame_txctl,
+		       struct ieee80211_rts *rts)
+{
+	const struct ieee80211_hdr *hdr = frame;
+	u16 fctl;
+
+	fctl = IEEE80211_FTYPE_CTL | IEEE80211_STYPE_RTS;
+	rts->frame_control = cpu_to_le16(fctl);
+	rts->duration = ieee80211_rts_duration(hw, frame_len, frame_txctl);
+	memcpy(rts->ra, hdr->addr1, sizeof(rts->ra));
+	memcpy(rts->ta, hdr->addr2, sizeof(rts->ta));
+}
+EXPORT_SYMBOL(ieee80211_rts_get);
+
+void ieee80211_ctstoself_get(struct ieee80211_hw *hw,
+			     const void *frame, size_t frame_len,
+			     const struct ieee80211_tx_control *frame_txctl,
+			     struct ieee80211_cts *cts)
+{
+	const struct ieee80211_hdr *hdr = frame;
+	u16 fctl;
+
+	fctl = IEEE80211_FTYPE_CTL | IEEE80211_STYPE_CTS;
+	cts->frame_control = cpu_to_le16(fctl);
+	cts->duration = ieee80211_ctstoself_duration(hw, frame_len, frame_txctl);
+	memcpy(cts->ra, hdr->addr1, sizeof(cts->ra));
+}
+EXPORT_SYMBOL(ieee80211_ctstoself_get);
+
+struct sk_buff *
+ieee80211_get_buffered_bc(struct ieee80211_hw *hw, int if_id,
+			  struct ieee80211_tx_control *control)
+{
+	struct ieee80211_local *local = hw_to_local(hw);
+	struct sk_buff *skb;
+	struct sta_info *sta;
+	ieee80211_tx_handler *handler;
+	struct ieee80211_txrx_data tx;
+	ieee80211_txrx_result res = TXRX_DROP;
+	struct net_device *bdev;
+	struct ieee80211_sub_if_data *sdata;
+	struct ieee80211_if_ap *bss = NULL;
+
+	bdev = dev_get_by_index(if_id);
+	if (bdev) {
+		sdata = IEEE80211_DEV_TO_SUB_IF(bdev);
+		bss = &sdata->u.ap;
+		dev_put(bdev);
+	}
+	if (!bss || sdata->type != IEEE80211_IF_TYPE_AP || !bss->beacon_head)
+		return NULL;
+
+	if (bss->dtim_count != 0)
+		return NULL; /* send buffered bc/mc only after DTIM beacon */
+	memset(control, 0, sizeof(*control));
+	while (1) {
+		skb = skb_dequeue(&bss->ps_bc_buf);
+		if (!skb)
+			return NULL;
+		local->total_ps_buffered--;
+
+		if (!skb_queue_empty(&bss->ps_bc_buf) && skb->len >= 2) {
+			struct ieee80211_hdr *hdr =
+				(struct ieee80211_hdr *) skb->data;
+			/* more buffered multicast/broadcast frames ==> set
+			 * MoreData flag in IEEE 802.11 header to inform PS
+			 * STAs */
+			hdr->frame_control |=
+				cpu_to_le16(IEEE80211_FCTL_MOREDATA);
+		}
+
+		if (ieee80211_tx_prepare(&tx, skb, local->mdev, control) == 0)
+			break;
+		dev_kfree_skb_any(skb);
+	}
+	sta = tx.sta;
+	tx.u.tx.ps_buffered = 1;
+
+	for (handler = local->tx_handlers; *handler != NULL; handler++) {
+		res = (*handler)(&tx);
+		if (res == TXRX_DROP || res == TXRX_QUEUED)
+			break;
+	}
+	dev_put(tx.dev);
+	skb = tx.skb; /* handlers are allowed to change skb */
+
+	if (res == TXRX_DROP) {
+		I802_DEBUG_INC(local->tx_handlers_drop);
+		dev_kfree_skb(skb);
+		skb = NULL;
+	} else if (res == TXRX_QUEUED) {
+		I802_DEBUG_INC(local->tx_handlers_queued);
+		skb = NULL;
+	}
+
+	if (sta)
+		sta_info_put(sta);
+
+	return skb;
+}
+EXPORT_SYMBOL(ieee80211_get_buffered_bc);
+
+static int __ieee80211_if_config(struct net_device *dev,
+				 struct sk_buff *beacon,
+				 struct ieee80211_tx_control *control)
+{
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+	struct ieee80211_if_conf conf;
+	static u8 scan_bssid[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+
+	if (!local->ops->config_interface || !netif_running(dev))
+		return 0;
+
+	memset(&conf, 0, sizeof(conf));
+	conf.type = sdata->type;
+	if (sdata->type == IEEE80211_IF_TYPE_STA ||
+	    sdata->type == IEEE80211_IF_TYPE_IBSS) {
+		if (local->sta_scanning &&
+		    local->scan_dev == dev)
+			conf.bssid = scan_bssid;
+		else
+			conf.bssid = sdata->u.sta.bssid;
+		conf.ssid = sdata->u.sta.ssid;
+		conf.ssid_len = sdata->u.sta.ssid_len;
+		conf.generic_elem = sdata->u.sta.extra_ie;
+		conf.generic_elem_len = sdata->u.sta.extra_ie_len;
+	} else if (sdata->type == IEEE80211_IF_TYPE_AP) {
+		conf.ssid = sdata->u.ap.ssid;
+		conf.ssid_len = sdata->u.ap.ssid_len;
+		conf.generic_elem = sdata->u.ap.generic_elem;
+		conf.generic_elem_len = sdata->u.ap.generic_elem_len;
+		conf.beacon = beacon;
+		conf.beacon_control = control;
+	}
+	return local->ops->config_interface(local_to_hw(local),
+					   dev->ifindex, &conf);
+}
+
+int ieee80211_if_config(struct net_device *dev)
+{
+	return __ieee80211_if_config(dev, NULL, NULL);
+}
+
+int ieee80211_if_config_beacon(struct net_device *dev)
+{
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+	struct ieee80211_tx_control control;
+	struct sk_buff *skb;
+
+	if (!(local->hw.flags & IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE))
+		return 0;
+	skb = ieee80211_beacon_get(local_to_hw(local), dev->ifindex, &control);
+	if (!skb)
+		return -ENOMEM;
+	return __ieee80211_if_config(dev, skb, &control);
+}
+
+int ieee80211_hw_config(struct ieee80211_local *local)
+{
+	struct ieee80211_hw_mode *mode;
+	struct ieee80211_channel *chan;
+	int ret = 0;
+
+	if (local->sta_scanning) {
+		chan = local->scan_channel;
+		mode = local->scan_hw_mode;
+	} else {
+		chan = local->oper_channel;
+		mode = local->oper_hw_mode;
+	}
+
+	local->hw.conf.channel = chan->chan;
+	local->hw.conf.channel_val = chan->val;
+	local->hw.conf.power_level = chan->power_level;
+	local->hw.conf.freq = chan->freq;
+	local->hw.conf.phymode = mode->mode;
+	local->hw.conf.antenna_max = chan->antenna_max;
+	local->hw.conf.chan = chan;
+	local->hw.conf.mode = mode;
+
+#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
+	printk(KERN_DEBUG "HW CONFIG: channel=%d freq=%d "
+	       "phymode=%d\n", local->hw.conf.channel, local->hw.conf.freq,
+	       local->hw.conf.phymode);
+#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
+
+	if (local->ops->config)
+		ret = local->ops->config(local_to_hw(local), &local->hw.conf);
+
+	return ret;
+}
+
+
+static int ieee80211_change_mtu(struct net_device *dev, int new_mtu)
+{
+	/* FIX: what would be proper limits for MTU?
+	 * This interface uses 802.3 frames. */
+	if (new_mtu < 256 || new_mtu > IEEE80211_MAX_DATA_LEN - 24 - 6) {
+		printk(KERN_WARNING "%s: invalid MTU %d\n",
+		       dev->name, new_mtu);
+		return -EINVAL;
+	}
+
+#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
+	printk(KERN_DEBUG "%s: setting MTU %d\n", dev->name, new_mtu);
+#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
+	dev->mtu = new_mtu;
+	return 0;
+}
+
+
+static int ieee80211_change_mtu_apdev(struct net_device *dev, int new_mtu)
+{
+	/* FIX: what would be proper limits for MTU?
+	 * This interface uses 802.11 frames. */
+	if (new_mtu < 256 || new_mtu > IEEE80211_MAX_DATA_LEN) {
+		printk(KERN_WARNING "%s: invalid MTU %d\n",
+		       dev->name, new_mtu);
+		return -EINVAL;
+	}
+
+#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
+	printk(KERN_DEBUG "%s: setting MTU %d\n", dev->name, new_mtu);
+#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
+	dev->mtu = new_mtu;
+	return 0;
+}
+
+enum netif_tx_lock_class {
+	TX_LOCK_NORMAL,
+	TX_LOCK_MASTER,
+};
+
+static inline void netif_tx_lock_nested(struct net_device *dev, int subclass)
+{
+	spin_lock_nested(&dev->_xmit_lock, subclass);
+	dev->xmit_lock_owner = smp_processor_id();
+}
+
+static void ieee80211_set_multicast_list(struct net_device *dev)
+{
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	unsigned short flags;
+
+	netif_tx_lock_nested(local->mdev, TX_LOCK_MASTER);
+	if (((dev->flags & IFF_ALLMULTI) != 0) ^ (sdata->allmulti != 0)) {
+		if (sdata->allmulti) {
+			sdata->allmulti = 0;
+			local->iff_allmultis--;
+		} else {
+			sdata->allmulti = 1;
+			local->iff_allmultis++;
+		}
+	}
+	if (((dev->flags & IFF_PROMISC) != 0) ^ (sdata->promisc != 0)) {
+		if (sdata->promisc) {
+			sdata->promisc = 0;
+			local->iff_promiscs--;
+		} else {
+			sdata->promisc = 1;
+			local->iff_promiscs++;
+		}
+	}
+	if (dev->mc_count != sdata->mc_count) {
+		local->mc_count = local->mc_count - sdata->mc_count +
+				  dev->mc_count;
+		sdata->mc_count = dev->mc_count;
+	}
+	if (local->ops->set_multicast_list) {
+		flags = local->mdev->flags;
+		if (local->iff_allmultis)
+			flags |= IFF_ALLMULTI;
+		if (local->iff_promiscs)
+			flags |= IFF_PROMISC;
+		read_lock(&local->sub_if_lock);
+		local->ops->set_multicast_list(local_to_hw(local), flags,
+					      local->mc_count);
+		read_unlock(&local->sub_if_lock);
+	}
+	netif_tx_unlock(local->mdev);
+}
+
+struct dev_mc_list *ieee80211_get_mc_list_item(struct ieee80211_hw *hw,
+					       struct dev_mc_list *prev,
+					       void **ptr)
+{
+	struct ieee80211_local *local = hw_to_local(hw);
+	struct ieee80211_sub_if_data *sdata = *ptr;
+	struct dev_mc_list *mc;
+
+	if (!prev) {
+		WARN_ON(sdata);
+		sdata = NULL;
+	}
+	if (!prev || !prev->next) {
+		if (sdata)
+			sdata = list_entry(sdata->list.next,
+					   struct ieee80211_sub_if_data, list);
+		else
+			sdata = list_entry(local->sub_if_list.next,
+					   struct ieee80211_sub_if_data, list);
+		if (&sdata->list != &local->sub_if_list)
+			mc = sdata->dev->mc_list;
+		else
+			mc = NULL;
+	} else
+		mc = prev->next;
+
+	*ptr = sdata;
+	return mc;
+}
+EXPORT_SYMBOL(ieee80211_get_mc_list_item);
+
+static struct net_device_stats *ieee80211_get_stats(struct net_device *dev)
+{
+	struct ieee80211_sub_if_data *sdata;
+	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	return &(sdata->stats);
+}
+
+static void ieee80211_if_shutdown(struct net_device *dev)
+{
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+
+	ASSERT_RTNL();
+	switch (sdata->type) {
+	case IEEE80211_IF_TYPE_STA:
+	case IEEE80211_IF_TYPE_IBSS:
+		sdata->u.sta.state = IEEE80211_DISABLED;
+		del_timer_sync(&sdata->u.sta.timer);
+		skb_queue_purge(&sdata->u.sta.skb_queue);
+		if (!local->ops->hw_scan &&
+		    local->scan_dev == sdata->dev) {
+			local->sta_scanning = 0;
+			cancel_delayed_work(&local->scan_work);
+		}
+		flush_workqueue(local->hw.workqueue);
+		break;
+	}
+}
+
+static inline int identical_mac_addr_allowed(int type1, int type2)
+{
+	return (type1 == IEEE80211_IF_TYPE_MNTR ||
+		type2 == IEEE80211_IF_TYPE_MNTR ||
+		(type1 == IEEE80211_IF_TYPE_AP &&
+		 type2 == IEEE80211_IF_TYPE_WDS) ||
+		(type1 == IEEE80211_IF_TYPE_WDS &&
+		 (type2 == IEEE80211_IF_TYPE_WDS ||
+		  type2 == IEEE80211_IF_TYPE_AP)) ||
+		(type1 == IEEE80211_IF_TYPE_AP &&
+		 type2 == IEEE80211_IF_TYPE_VLAN) ||
+		(type1 == IEEE80211_IF_TYPE_VLAN &&
+		 (type2 == IEEE80211_IF_TYPE_AP ||
+		  type2 == IEEE80211_IF_TYPE_VLAN)));
+}
+
+static int ieee80211_master_open(struct net_device *dev)
+{
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+	struct ieee80211_sub_if_data *sdata;
+	int res = -EOPNOTSUPP;
+
+	read_lock(&local->sub_if_lock);
+	list_for_each_entry(sdata, &local->sub_if_list, list) {
+		if (sdata->dev != dev && netif_running(sdata->dev)) {
+			res = 0;
+			break;
+		}
+	}
+	read_unlock(&local->sub_if_lock);
+	return res;
+}
+
+static int ieee80211_master_stop(struct net_device *dev)
+{
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+	struct ieee80211_sub_if_data *sdata;
+
+	read_lock(&local->sub_if_lock);
+	list_for_each_entry(sdata, &local->sub_if_list, list)
+		if (sdata->dev != dev && netif_running(sdata->dev))
+			dev_close(sdata->dev);
+	read_unlock(&local->sub_if_lock);
+
+	return 0;
+}
+
+static int ieee80211_mgmt_open(struct net_device *dev)
+{
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+
+	if (!netif_running(local->mdev))
+		return -EOPNOTSUPP;
+	return 0;
+}
+
+static int ieee80211_mgmt_stop(struct net_device *dev)
+{
+	return 0;
+}
+
+/* Check if running monitor interfaces should go to a "soft monitor" mode
+ * and switch them if necessary. */
+static inline void ieee80211_start_soft_monitor(struct ieee80211_local *local)
+{
+	struct ieee80211_if_init_conf conf;
+
+	if (local->open_count && local->open_count == local->monitors &&
+	    !(local->hw.flags & IEEE80211_HW_MONITOR_DURING_OPER) &&
+	    local->ops->remove_interface) {
+		conf.if_id = -1;
+		conf.type = IEEE80211_IF_TYPE_MNTR;
+		conf.mac_addr = NULL;
+		local->ops->remove_interface(local_to_hw(local), &conf);
+	}
+}
+
+/* Check if running monitor interfaces should go to a "hard monitor" mode
+ * and switch them if necessary. */
+static void ieee80211_start_hard_monitor(struct ieee80211_local *local)
+{
+	struct ieee80211_if_init_conf conf;
+
+	if (local->open_count && local->open_count == local->monitors &&
+	    !(local->hw.flags & IEEE80211_HW_MONITOR_DURING_OPER) &&
+	    local->ops->add_interface) {
+		conf.if_id = -1;
+		conf.type = IEEE80211_IF_TYPE_MNTR;
+		conf.mac_addr = NULL;
+		local->ops->add_interface(local_to_hw(local), &conf);
+	}
+}
+
+static int ieee80211_open(struct net_device *dev)
+{
+	struct ieee80211_sub_if_data *sdata, *nsdata;
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+	struct ieee80211_if_init_conf conf;
+	int res;
+
+	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	read_lock(&local->sub_if_lock);
+	list_for_each_entry(nsdata, &local->sub_if_list, list) {
+		struct net_device *ndev = nsdata->dev;
+
+		if (ndev != dev && ndev != local->mdev && netif_running(ndev) &&
+		    compare_ether_addr(dev->dev_addr, ndev->dev_addr) == 0 &&
+		    !identical_mac_addr_allowed(sdata->type, nsdata->type)) {
+			read_unlock(&local->sub_if_lock);
+			return -ENOTUNIQ;
+		}
+	}
+	read_unlock(&local->sub_if_lock);
+
+	if (sdata->type == IEEE80211_IF_TYPE_WDS &&
+	    is_zero_ether_addr(sdata->u.wds.remote_addr))
+		return -ENOLINK;
+
+	if (sdata->type == IEEE80211_IF_TYPE_MNTR && local->open_count &&
+	    !(local->hw.flags & IEEE80211_HW_MONITOR_DURING_OPER)) {
+		/* run the interface in a "soft monitor" mode */
+		local->monitors++;
+		local->open_count++;
+		local->hw.conf.flags |= IEEE80211_CONF_RADIOTAP;
+		return 0;
+	}
+	ieee80211_start_soft_monitor(local);
+
+	if (local->ops->add_interface) {
+		conf.if_id = dev->ifindex;
+		conf.type = sdata->type;
+		conf.mac_addr = dev->dev_addr;
+		res = local->ops->add_interface(local_to_hw(local), &conf);
+		if (res) {
+			if (sdata->type == IEEE80211_IF_TYPE_MNTR)
+				ieee80211_start_hard_monitor(local);
+			return res;
+		}
+	} else {
+		if (sdata->type != IEEE80211_IF_TYPE_STA)
+			return -EOPNOTSUPP;
+		if (local->open_count > 0)
+			return -ENOBUFS;
+	}
+
+	if (local->open_count == 0) {
+		res = 0;
+		tasklet_enable(&local->tx_pending_tasklet);
+		tasklet_enable(&local->tasklet);
+		if (local->ops->open)
+			res = local->ops->open(local_to_hw(local));
+		if (res == 0) {
+			res = dev_open(local->mdev);
+			if (res) {
+				if (local->ops->stop)
+					local->ops->stop(local_to_hw(local));
+			} else {
+				res = ieee80211_hw_config(local);
+				if (res && local->ops->stop)
+					local->ops->stop(local_to_hw(local));
+				else if (!res && local->apdev)
+					dev_open(local->apdev);
+			}
+		}
+		if (res) {
+			if (local->ops->remove_interface)
+				local->ops->remove_interface(local_to_hw(local),
+							    &conf);
+			return res;
+		}
+	}
+	local->open_count++;
+
+	if (sdata->type == IEEE80211_IF_TYPE_MNTR) {
+		local->monitors++;
+		local->hw.conf.flags |= IEEE80211_CONF_RADIOTAP;
+	} else
+		ieee80211_if_config(dev);
+
+	if (sdata->type == IEEE80211_IF_TYPE_STA &&
+	    !local->user_space_mlme)
+		netif_carrier_off(dev);
+
+	netif_start_queue(dev);
+	return 0;
+}
+
+
+static int ieee80211_stop(struct net_device *dev)
+{
+	struct ieee80211_sub_if_data *sdata;
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+
+	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+
+	if (sdata->type == IEEE80211_IF_TYPE_MNTR &&
+	    local->open_count > 1 &&
+	    !(local->hw.flags & IEEE80211_HW_MONITOR_DURING_OPER)) {
+		/* remove "soft monitor" interface */
+		local->open_count--;
+		local->monitors--;
+		if (!local->monitors)
+			local->hw.conf.flags &= ~IEEE80211_CONF_RADIOTAP;
+		return 0;
+	}
+
+	netif_stop_queue(dev);
+	ieee80211_if_shutdown(dev);
+
+	if (sdata->type == IEEE80211_IF_TYPE_MNTR) {
+		local->monitors--;
+		if (!local->monitors)
+			local->hw.conf.flags &= ~IEEE80211_CONF_RADIOTAP;
+	}
+
+	local->open_count--;
+	if (local->open_count == 0) {
+		if (netif_running(local->mdev))
+			dev_close(local->mdev);
+		if (local->apdev)
+			dev_close(local->apdev);
+		if (local->ops->stop)
+			local->ops->stop(local_to_hw(local));
+		tasklet_disable(&local->tx_pending_tasklet);
+		tasklet_disable(&local->tasklet);
+	}
+	if (local->ops->remove_interface) {
+		struct ieee80211_if_init_conf conf;
+
+		conf.if_id = dev->ifindex;
+		conf.type = sdata->type;
+		conf.mac_addr = dev->dev_addr;
+		local->ops->remove_interface(local_to_hw(local), &conf);
+	}
+
+	ieee80211_start_hard_monitor(local);
+
+	return 0;
+}
+
+
+static int header_parse_80211(struct sk_buff *skb, unsigned char *haddr)
+{
+	memcpy(haddr, skb_mac_header(skb) + 10, ETH_ALEN); /* addr2 */
+	return ETH_ALEN;
+}
+
+static inline int ieee80211_bssid_match(const u8 *raddr, const u8 *addr)
+{
+	return compare_ether_addr(raddr, addr) == 0 ||
+	       is_broadcast_ether_addr(raddr);
+}
+
+
+static ieee80211_txrx_result
+ieee80211_rx_h_data(struct ieee80211_txrx_data *rx)
+{
+	struct net_device *dev = rx->dev;
+	struct ieee80211_local *local = rx->local;
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data;
+	u16 fc, hdrlen, ethertype;
+	u8 *payload;
+	u8 dst[ETH_ALEN];
+	u8 src[ETH_ALEN];
+	struct sk_buff *skb = rx->skb, *skb2;
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+
+	fc = rx->fc;
+	if (unlikely((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA))
+		return TXRX_CONTINUE;
+
+	if (unlikely(!WLAN_FC_DATA_PRESENT(fc)))
+		return TXRX_DROP;
+
+	hdrlen = ieee80211_get_hdrlen(fc);
+
+	/* convert IEEE 802.11 header + possible LLC headers into Ethernet
+	 * header
+	 * IEEE 802.11 address fields:
+	 * ToDS FromDS Addr1 Addr2 Addr3 Addr4
+	 *   0     0   DA    SA    BSSID n/a
+	 *   0     1   DA    BSSID SA    n/a
+	 *   1     0   BSSID SA    DA    n/a
+	 *   1     1   RA    TA    DA    SA
+	 */
+
+	switch (fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) {
+	case IEEE80211_FCTL_TODS:
+		/* BSSID SA DA */
+		memcpy(dst, hdr->addr3, ETH_ALEN);
+		memcpy(src, hdr->addr2, ETH_ALEN);
+
+		if (unlikely(sdata->type != IEEE80211_IF_TYPE_AP &&
+			     sdata->type != IEEE80211_IF_TYPE_VLAN)) {
+			printk(KERN_DEBUG "%s: dropped ToDS frame (BSSID="
+			       MAC_FMT " SA=" MAC_FMT " DA=" MAC_FMT ")\n",
+			       dev->name, MAC_ARG(hdr->addr1),
+			       MAC_ARG(hdr->addr2), MAC_ARG(hdr->addr3));
+			return TXRX_DROP;
+		}
+		break;
+	case (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS):
+		/* RA TA DA SA */
+		memcpy(dst, hdr->addr3, ETH_ALEN);
+		memcpy(src, hdr->addr4, ETH_ALEN);
+
+		if (unlikely(sdata->type != IEEE80211_IF_TYPE_WDS)) {
+			printk(KERN_DEBUG "%s: dropped FromDS&ToDS frame (RA="
+			       MAC_FMT " TA=" MAC_FMT " DA=" MAC_FMT " SA="
+			       MAC_FMT ")\n",
+			       rx->dev->name, MAC_ARG(hdr->addr1),
+			       MAC_ARG(hdr->addr2), MAC_ARG(hdr->addr3),
+			       MAC_ARG(hdr->addr4));
+			return TXRX_DROP;
+		}
+		break;
+	case IEEE80211_FCTL_FROMDS:
+		/* DA BSSID SA */
+		memcpy(dst, hdr->addr1, ETH_ALEN);
+		memcpy(src, hdr->addr3, ETH_ALEN);
+
+		if (sdata->type != IEEE80211_IF_TYPE_STA) {
+			return TXRX_DROP;
+		}
+		break;
+	case 0:
+		/* DA SA BSSID */
+		memcpy(dst, hdr->addr1, ETH_ALEN);
+		memcpy(src, hdr->addr2, ETH_ALEN);
+
+		if (sdata->type != IEEE80211_IF_TYPE_IBSS) {
+			if (net_ratelimit()) {
+				printk(KERN_DEBUG "%s: dropped IBSS frame (DA="
+				       MAC_FMT " SA=" MAC_FMT " BSSID=" MAC_FMT
+				       ")\n",
+				       dev->name, MAC_ARG(hdr->addr1),
+				       MAC_ARG(hdr->addr2),
+				       MAC_ARG(hdr->addr3));
+			}
+			return TXRX_DROP;
+		}
+		break;
+	}
+
+	payload = skb->data + hdrlen;
+
+	if (unlikely(skb->len - hdrlen < 8)) {
+		if (net_ratelimit()) {
+			printk(KERN_DEBUG "%s: RX too short data frame "
+			       "payload\n", dev->name);
+		}
+		return TXRX_DROP;
+	}
+
+	ethertype = (payload[6] << 8) | payload[7];
+
+	if (likely((compare_ether_addr(payload, rfc1042_header) == 0 &&
+		    ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) ||
+		   compare_ether_addr(payload, bridge_tunnel_header) == 0)) {
+		/* remove RFC1042 or Bridge-Tunnel encapsulation and
+		 * replace EtherType */
+		skb_pull(skb, hdrlen + 6);
+		memcpy(skb_push(skb, ETH_ALEN), src, ETH_ALEN);
+		memcpy(skb_push(skb, ETH_ALEN), dst, ETH_ALEN);
+	} else {
+		struct ethhdr *ehdr;
+		__be16 len;
+		skb_pull(skb, hdrlen);
+		len = htons(skb->len);
+		ehdr = (struct ethhdr *) skb_push(skb, sizeof(struct ethhdr));
+		memcpy(ehdr->h_dest, dst, ETH_ALEN);
+		memcpy(ehdr->h_source, src, ETH_ALEN);
+		ehdr->h_proto = len;
+	}
+	skb->dev = dev;
+
+	skb2 = NULL;
+
+	sdata->stats.rx_packets++;
+	sdata->stats.rx_bytes += skb->len;
+
+	if (local->bridge_packets && (sdata->type == IEEE80211_IF_TYPE_AP
+	    || sdata->type == IEEE80211_IF_TYPE_VLAN) && rx->u.rx.ra_match) {
+		if (is_multicast_ether_addr(skb->data)) {
+			/* send multicast frames both to higher layers in
+			 * local net stack and back to the wireless media */
+			skb2 = skb_copy(skb, GFP_ATOMIC);
+			if (!skb2)
+				printk(KERN_DEBUG "%s: failed to clone "
+				       "multicast frame\n", dev->name);
+		} else {
+			struct sta_info *dsta;
+			dsta = sta_info_get(local, skb->data);
+			if (dsta && !dsta->dev) {
+				printk(KERN_DEBUG "Station with null dev "
+				       "structure!\n");
+			} else if (dsta && dsta->dev == dev) {
+				/* Destination station is associated to this
+				 * AP, so send the frame directly to it and
+				 * do not pass the frame to local net stack.
+				 */
+				skb2 = skb;
+				skb = NULL;
+			}
+			if (dsta)
+				sta_info_put(dsta);
+		}
+	}
+
+	if (skb) {
+		/* deliver to local stack */
+		skb->protocol = eth_type_trans(skb, dev);
+		memset(skb->cb, 0, sizeof(skb->cb));
+		netif_rx(skb);
+	}
+
+	if (skb2) {
+		/* send to wireless media */
+		skb2->protocol = __constant_htons(ETH_P_802_3);
+		skb_set_network_header(skb2, 0);
+		skb_set_mac_header(skb2, 0);
+		dev_queue_xmit(skb2);
+	}
+
+	return TXRX_QUEUED;
+}
+
+
+static struct ieee80211_rate *
+ieee80211_get_rate(struct ieee80211_local *local, int phymode, int hw_rate)
+{
+	struct ieee80211_hw_mode *mode;
+	int r;
+
+	list_for_each_entry(mode, &local->modes_list, list) {
+		if (mode->mode != phymode)
+			continue;
+		for (r = 0; r < mode->num_rates; r++) {
+			struct ieee80211_rate *rate = &mode->rates[r];
+			if (rate->val == hw_rate ||
+			    (rate->flags & IEEE80211_RATE_PREAMBLE2 &&
+			     rate->val2 == hw_rate))
+				return rate;
+		}
+	}
+
+	return NULL;
+}
+
+static void
+ieee80211_fill_frame_info(struct ieee80211_local *local,
+			  struct ieee80211_frame_info *fi,
+			  struct ieee80211_rx_status *status)
+{
+	if (status) {
+		struct timespec ts;
+		struct ieee80211_rate *rate;
+
+		jiffies_to_timespec(jiffies, &ts);
+		fi->hosttime = cpu_to_be64((u64) ts.tv_sec * 1000000 +
+					   ts.tv_nsec / 1000);
+		fi->mactime = cpu_to_be64(status->mactime);
+		switch (status->phymode) {
+		case MODE_IEEE80211A:
+			fi->phytype = htonl(ieee80211_phytype_ofdm_dot11_a);
+			break;
+		case MODE_IEEE80211B:
+			fi->phytype = htonl(ieee80211_phytype_dsss_dot11_b);
+			break;
+		case MODE_IEEE80211G:
+			fi->phytype = htonl(ieee80211_phytype_pbcc_dot11_g);
+			break;
+		case MODE_ATHEROS_TURBO:
+			fi->phytype =
+				htonl(ieee80211_phytype_dsss_dot11_turbo);
+			break;
+		default:
+			fi->phytype = htonl(0xAAAAAAAA);
+			break;
+		}
+		fi->channel = htonl(status->channel);
+		rate = ieee80211_get_rate(local, status->phymode,
+					  status->rate);
+		if (rate) {
+			fi->datarate = htonl(rate->rate);
+			if (rate->flags & IEEE80211_RATE_PREAMBLE2) {
+				if (status->rate == rate->val)
+					fi->preamble = htonl(2); /* long */
+				else if (status->rate == rate->val2)
+					fi->preamble = htonl(1); /* short */
+			} else
+				fi->preamble = htonl(0);
+		} else {
+			fi->datarate = htonl(0);
+			fi->preamble = htonl(0);
+		}
+
+		fi->antenna = htonl(status->antenna);
+		fi->priority = htonl(0xffffffff); /* no clue */
+		fi->ssi_type = htonl(ieee80211_ssi_raw);
+		fi->ssi_signal = htonl(status->ssi);
+		fi->ssi_noise = 0x00000000;
+		fi->encoding = 0;
+	} else {
+		/* clear everything because we really don't know.
+		 * the msg_type field isn't present on monitor frames
+		 * so we don't know whether it will be present or not,
+		 * but it's ok to not clear it since it'll be assigned
+		 * anyway */
+		memset(fi, 0, sizeof(*fi) - sizeof(fi->msg_type));
+
+		fi->ssi_type = htonl(ieee80211_ssi_none);
+	}
+	fi->version = htonl(IEEE80211_FI_VERSION);
+	fi->length = cpu_to_be32(sizeof(*fi) - sizeof(fi->msg_type));
+}
+
+/* this routine is actually not just for this, but also
+ * for pushing fake 'management' frames into userspace.
+ * it shall be replaced by a netlink-based system. */
+void
+ieee80211_rx_mgmt(struct ieee80211_local *local, struct sk_buff *skb,
+		  struct ieee80211_rx_status *status, u32 msg_type)
+{
+	struct ieee80211_frame_info *fi;
+	const size_t hlen = sizeof(struct ieee80211_frame_info);
+	struct ieee80211_sub_if_data *sdata;
+
+	skb->dev = local->apdev;
+
+	sdata = IEEE80211_DEV_TO_SUB_IF(local->apdev);
+
+	if (skb_headroom(skb) < hlen) {
+		I802_DEBUG_INC(local->rx_expand_skb_head);
+		if (pskb_expand_head(skb, hlen, 0, GFP_ATOMIC)) {
+			dev_kfree_skb(skb);
+			return;
+		}
+	}
+
+	fi = (struct ieee80211_frame_info *) skb_push(skb, hlen);
+
+	ieee80211_fill_frame_info(local, fi, status);
+	fi->msg_type = htonl(msg_type);
+
+	sdata->stats.rx_packets++;
+	sdata->stats.rx_bytes += skb->len;
+
+	skb_set_mac_header(skb, 0);
+	skb->ip_summed = CHECKSUM_UNNECESSARY;
+	skb->pkt_type = PACKET_OTHERHOST;
+	skb->protocol = htons(ETH_P_802_2);
+	memset(skb->cb, 0, sizeof(skb->cb));
+	netif_rx(skb);
+}
+
+static void
+ieee80211_rx_monitor(struct net_device *dev, struct sk_buff *skb,
+		     struct ieee80211_rx_status *status)
+{
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+	struct ieee80211_sub_if_data *sdata;
+	struct ieee80211_rate *rate;
+	struct ieee80211_rtap_hdr {
+		struct ieee80211_radiotap_header hdr;
+		u8 flags;
+		u8 rate;
+		__le16 chan_freq;
+		__le16 chan_flags;
+		u8 antsignal;
+	} __attribute__ ((packed)) *rthdr;
+
+	skb->dev = dev;
+
+	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+
+	if (status->flag & RX_FLAG_RADIOTAP)
+		goto out;
+
+	if (skb_headroom(skb) < sizeof(*rthdr)) {
+		I802_DEBUG_INC(local->rx_expand_skb_head);
+		if (pskb_expand_head(skb, sizeof(*rthdr), 0, GFP_ATOMIC)) {
+			dev_kfree_skb(skb);
+			return;
+		}
+	}
+
+	rthdr = (struct ieee80211_rtap_hdr *) skb_push(skb, sizeof(*rthdr));
+	memset(rthdr, 0, sizeof(*rthdr));
+	rthdr->hdr.it_len = cpu_to_le16(sizeof(*rthdr));
+	rthdr->hdr.it_present =
+		cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) |
+			    (1 << IEEE80211_RADIOTAP_RATE) |
+			    (1 << IEEE80211_RADIOTAP_CHANNEL) |
+			    (1 << IEEE80211_RADIOTAP_DB_ANTSIGNAL));
+	rthdr->flags = local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS ?
+		       IEEE80211_RADIOTAP_F_FCS : 0;
+	rate = ieee80211_get_rate(local, status->phymode, status->rate);
+	if (rate)
+		rthdr->rate = rate->rate / 5;
+	rthdr->chan_freq = cpu_to_le16(status->freq);
+	rthdr->chan_flags =
+		status->phymode == MODE_IEEE80211A ?
+		cpu_to_le16(IEEE80211_CHAN_OFDM | IEEE80211_CHAN_5GHZ) :
+		cpu_to_le16(IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ);
+	rthdr->antsignal = status->ssi;
+
+ out:
+	sdata->stats.rx_packets++;
+	sdata->stats.rx_bytes += skb->len;
+
+	skb_set_mac_header(skb, 0);
+	skb->ip_summed = CHECKSUM_UNNECESSARY;
+	skb->pkt_type = PACKET_OTHERHOST;
+	skb->protocol = htons(ETH_P_802_2);
+	memset(skb->cb, 0, sizeof(skb->cb));
+	netif_rx(skb);
+}
+
+int ieee80211_radar_status(struct ieee80211_hw *hw, int channel,
+			   int radar, int radar_type)
+{
+	struct sk_buff *skb;
+	struct ieee80211_radar_info *msg;
+	struct ieee80211_local *local = hw_to_local(hw);
+
+	if (!local->apdev)
+		return 0;
+
+	skb = dev_alloc_skb(sizeof(struct ieee80211_frame_info) +
+			    sizeof(struct ieee80211_radar_info));
+
+	if (!skb)
+		return -ENOMEM;
+	skb_reserve(skb, sizeof(struct ieee80211_frame_info));
+
+	msg = (struct ieee80211_radar_info *)
+		skb_put(skb, sizeof(struct ieee80211_radar_info));
+	msg->channel = channel;
+	msg->radar = radar;
+	msg->radar_type = radar_type;
+
+	ieee80211_rx_mgmt(local, skb, NULL, ieee80211_msg_radar);
+	return 0;
+}
+EXPORT_SYMBOL(ieee80211_radar_status);
+
+int ieee80211_set_aid_for_sta(struct ieee80211_hw *hw, u8 *peer_address,
+			      u16 aid)
+{
+	struct sk_buff *skb;
+	struct ieee80211_msg_set_aid_for_sta *msg;
+	struct ieee80211_local *local = hw_to_local(hw);
+
+	/* unlikely because if this event only happens for APs,
+	 * which require an open ap device. */
+	if (unlikely(!local->apdev))
+		return 0;
+
+	skb = dev_alloc_skb(sizeof(struct ieee80211_frame_info) +
+			    sizeof(struct ieee80211_msg_set_aid_for_sta));
+
+	if (!skb)
+		return -ENOMEM;
+	skb_reserve(skb, sizeof(struct ieee80211_frame_info));
+
+	msg = (struct ieee80211_msg_set_aid_for_sta *)
+		skb_put(skb, sizeof(struct ieee80211_msg_set_aid_for_sta));
+	memcpy(msg->sta_address, peer_address, ETH_ALEN);
+	msg->aid = aid;
+
+	ieee80211_rx_mgmt(local, skb, NULL, ieee80211_msg_set_aid_for_sta);
+	return 0;
+}
+EXPORT_SYMBOL(ieee80211_set_aid_for_sta);
+
+static void ap_sta_ps_start(struct net_device *dev, struct sta_info *sta)
+{
+	struct ieee80211_sub_if_data *sdata;
+	sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev);
+
+	if (sdata->bss)
+		atomic_inc(&sdata->bss->num_sta_ps);
+	sta->flags |= WLAN_STA_PS;
+	sta->pspoll = 0;
+#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
+	printk(KERN_DEBUG "%s: STA " MAC_FMT " aid %d enters power "
+	       "save mode\n", dev->name, MAC_ARG(sta->addr), sta->aid);
+#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
+}
+
+
+static int ap_sta_ps_end(struct net_device *dev, struct sta_info *sta)
+{
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+	struct sk_buff *skb;
+	int sent = 0;
+	struct ieee80211_sub_if_data *sdata;
+	struct ieee80211_tx_packet_data *pkt_data;
+
+	sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev);
+	if (sdata->bss)
+		atomic_dec(&sdata->bss->num_sta_ps);
+	sta->flags &= ~(WLAN_STA_PS | WLAN_STA_TIM);
+	sta->pspoll = 0;
+	if (!skb_queue_empty(&sta->ps_tx_buf)) {
+		if (local->ops->set_tim)
+			local->ops->set_tim(local_to_hw(local), sta->aid, 0);
+		if (sdata->bss)
+			bss_tim_clear(local, sdata->bss, sta->aid);
+	}
+#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
+	printk(KERN_DEBUG "%s: STA " MAC_FMT " aid %d exits power "
+	       "save mode\n", dev->name, MAC_ARG(sta->addr), sta->aid);
+#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
+	/* Send all buffered frames to the station */
+	while ((skb = skb_dequeue(&sta->tx_filtered)) != NULL) {
+		pkt_data = (struct ieee80211_tx_packet_data *) skb->cb;
+		sent++;
+		pkt_data->requeue = 1;
+		dev_queue_xmit(skb);
+	}
+	while ((skb = skb_dequeue(&sta->ps_tx_buf)) != NULL) {
+		pkt_data = (struct ieee80211_tx_packet_data *) skb->cb;
+		local->total_ps_buffered--;
+		sent++;
+#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
+		printk(KERN_DEBUG "%s: STA " MAC_FMT " aid %d send PS frame "
+		       "since STA not sleeping anymore\n", dev->name,
+		       MAC_ARG(sta->addr), sta->aid);
+#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
+		pkt_data->requeue = 1;
+		dev_queue_xmit(skb);
+	}
+
+	return sent;
+}
+
+
+static ieee80211_txrx_result
+ieee80211_rx_h_ps_poll(struct ieee80211_txrx_data *rx)
+{
+	struct sk_buff *skb;
+	int no_pending_pkts;
+
+	if (likely(!rx->sta ||
+		   (rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_CTL ||
+		   (rx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_PSPOLL ||
+		   !rx->u.rx.ra_match))
+		return TXRX_CONTINUE;
+
+	skb = skb_dequeue(&rx->sta->tx_filtered);
+	if (!skb) {
+		skb = skb_dequeue(&rx->sta->ps_tx_buf);
+		if (skb)
+			rx->local->total_ps_buffered--;
+	}
+	no_pending_pkts = skb_queue_empty(&rx->sta->tx_filtered) &&
+		skb_queue_empty(&rx->sta->ps_tx_buf);
+
+	if (skb) {
+		struct ieee80211_hdr *hdr =
+			(struct ieee80211_hdr *) skb->data;
+
+		/* tell TX path to send one frame even though the STA may
+		 * still remain is PS mode after this frame exchange */
+		rx->sta->pspoll = 1;
+
+#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
+		printk(KERN_DEBUG "STA " MAC_FMT " aid %d: PS Poll (entries "
+		       "after %d)\n",
+		       MAC_ARG(rx->sta->addr), rx->sta->aid,
+		       skb_queue_len(&rx->sta->ps_tx_buf));
+#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
+
+		/* Use MoreData flag to indicate whether there are more
+		 * buffered frames for this STA */
+		if (no_pending_pkts) {
+			hdr->frame_control &= cpu_to_le16(~IEEE80211_FCTL_MOREDATA);
+			rx->sta->flags &= ~WLAN_STA_TIM;
+		} else
+			hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA);
+
+		dev_queue_xmit(skb);
+
+		if (no_pending_pkts) {
+			if (rx->local->ops->set_tim)
+				rx->local->ops->set_tim(local_to_hw(rx->local),
+						       rx->sta->aid, 0);
+			if (rx->sdata->bss)
+				bss_tim_clear(rx->local, rx->sdata->bss, rx->sta->aid);
+		}
+#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
+	} else if (!rx->u.rx.sent_ps_buffered) {
+		printk(KERN_DEBUG "%s: STA " MAC_FMT " sent PS Poll even "
+		       "though there is no buffered frames for it\n",
+		       rx->dev->name, MAC_ARG(rx->sta->addr));
+#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
+
+	}
+
+	/* Free PS Poll skb here instead of returning TXRX_DROP that would
+	 * count as an dropped frame. */
+	dev_kfree_skb(rx->skb);
+
+	return TXRX_QUEUED;
+}
+
+
+static inline struct ieee80211_fragment_entry *
+ieee80211_reassemble_add(struct ieee80211_sub_if_data *sdata,
+			 unsigned int frag, unsigned int seq, int rx_queue,
+			 struct sk_buff **skb)
+{
+	struct ieee80211_fragment_entry *entry;
+	int idx;
+
+	idx = sdata->fragment_next;
+	entry = &sdata->fragments[sdata->fragment_next++];
+	if (sdata->fragment_next >= IEEE80211_FRAGMENT_MAX)
+		sdata->fragment_next = 0;
+
+	if (!skb_queue_empty(&entry->skb_list)) {
+#ifdef CONFIG_MAC80211_DEBUG
+		struct ieee80211_hdr *hdr =
+			(struct ieee80211_hdr *) entry->skb_list.next->data;
+		printk(KERN_DEBUG "%s: RX reassembly removed oldest "
+		       "fragment entry (idx=%d age=%lu seq=%d last_frag=%d "
+		       "addr1=" MAC_FMT " addr2=" MAC_FMT "\n",
+		       sdata->dev->name, idx,
+		       jiffies - entry->first_frag_time, entry->seq,
+		       entry->last_frag, MAC_ARG(hdr->addr1),
+		       MAC_ARG(hdr->addr2));
+#endif /* CONFIG_MAC80211_DEBUG */
+		__skb_queue_purge(&entry->skb_list);
+	}
+
+	__skb_queue_tail(&entry->skb_list, *skb); /* no need for locking */
+	*skb = NULL;
+	entry->first_frag_time = jiffies;
+	entry->seq = seq;
+	entry->rx_queue = rx_queue;
+	entry->last_frag = frag;
+	entry->ccmp = 0;
+	entry->extra_len = 0;
+
+	return entry;
+}
+
+
+static inline struct ieee80211_fragment_entry *
+ieee80211_reassemble_find(struct ieee80211_sub_if_data *sdata,
+			  u16 fc, unsigned int frag, unsigned int seq,
+			  int rx_queue, struct ieee80211_hdr *hdr)
+{
+	struct ieee80211_fragment_entry *entry;
+	int i, idx;
+
+	idx = sdata->fragment_next;
+	for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++) {
+		struct ieee80211_hdr *f_hdr;
+		u16 f_fc;
+
+		idx--;
+		if (idx < 0)
+			idx = IEEE80211_FRAGMENT_MAX - 1;
+
+		entry = &sdata->fragments[idx];
+		if (skb_queue_empty(&entry->skb_list) || entry->seq != seq ||
+		    entry->rx_queue != rx_queue ||
+		    entry->last_frag + 1 != frag)
+			continue;
+
+		f_hdr = (struct ieee80211_hdr *) entry->skb_list.next->data;
+		f_fc = le16_to_cpu(f_hdr->frame_control);
+
+		if ((fc & IEEE80211_FCTL_FTYPE) != (f_fc & IEEE80211_FCTL_FTYPE) ||
+		    compare_ether_addr(hdr->addr1, f_hdr->addr1) != 0 ||
+		    compare_ether_addr(hdr->addr2, f_hdr->addr2) != 0)
+			continue;
+
+		if (entry->first_frag_time + 2 * HZ < jiffies) {
+			__skb_queue_purge(&entry->skb_list);
+			continue;
+		}
+		return entry;
+	}
+
+	return NULL;
+}
+
+
+static ieee80211_txrx_result
+ieee80211_rx_h_defragment(struct ieee80211_txrx_data *rx)
+{
+	struct ieee80211_hdr *hdr;
+	u16 sc;
+	unsigned int frag, seq;
+	struct ieee80211_fragment_entry *entry;
+	struct sk_buff *skb;
+
+	hdr = (struct ieee80211_hdr *) rx->skb->data;
+	sc = le16_to_cpu(hdr->seq_ctrl);
+	frag = sc & IEEE80211_SCTL_FRAG;
+
+	if (likely((!(rx->fc & IEEE80211_FCTL_MOREFRAGS) && frag == 0) ||
+		   (rx->skb)->len < 24 ||
+		   is_multicast_ether_addr(hdr->addr1))) {
+		/* not fragmented */
+		goto out;
+	}
+	I802_DEBUG_INC(rx->local->rx_handlers_fragments);
+
+	seq = (sc & IEEE80211_SCTL_SEQ) >> 4;
+
+	if (frag == 0) {
+		/* This is the first fragment of a new frame. */
+		entry = ieee80211_reassemble_add(rx->sdata, frag, seq,
+						 rx->u.rx.queue, &(rx->skb));
+		if (rx->key && rx->key->alg == ALG_CCMP &&
+		    (rx->fc & IEEE80211_FCTL_PROTECTED)) {
+			/* Store CCMP PN so that we can verify that the next
+			 * fragment has a sequential PN value. */
+			entry->ccmp = 1;
+			memcpy(entry->last_pn,
+			       rx->key->u.ccmp.rx_pn[rx->u.rx.queue],
+			       CCMP_PN_LEN);
+		}
+		return TXRX_QUEUED;
+	}
+
+	/* This is a fragment for a frame that should already be pending in
+	 * fragment cache. Add this fragment to the end of the pending entry.
+	 */
+	entry = ieee80211_reassemble_find(rx->sdata, rx->fc, frag, seq,
+					  rx->u.rx.queue, hdr);
+	if (!entry) {
+		I802_DEBUG_INC(rx->local->rx_handlers_drop_defrag);
+		return TXRX_DROP;
+	}
+
+	/* Verify that MPDUs within one MSDU have sequential PN values.
+	 * (IEEE 802.11i, 8.3.3.4.5) */
+	if (entry->ccmp) {
+		int i;
+		u8 pn[CCMP_PN_LEN], *rpn;
+		if (!rx->key || rx->key->alg != ALG_CCMP)
+			return TXRX_DROP;
+		memcpy(pn, entry->last_pn, CCMP_PN_LEN);
+		for (i = CCMP_PN_LEN - 1; i >= 0; i--) {
+			pn[i]++;
+			if (pn[i])
+				break;
+		}
+		rpn = rx->key->u.ccmp.rx_pn[rx->u.rx.queue];
+		if (memcmp(pn, rpn, CCMP_PN_LEN) != 0) {
+			printk(KERN_DEBUG "%s: defrag: CCMP PN not sequential"
+			       " A2=" MAC_FMT " PN=%02x%02x%02x%02x%02x%02x "
+			       "(expected %02x%02x%02x%02x%02x%02x)\n",
+			       rx->dev->name, MAC_ARG(hdr->addr2),
+			       rpn[0], rpn[1], rpn[2], rpn[3], rpn[4], rpn[5],
+			       pn[0], pn[1], pn[2], pn[3], pn[4], pn[5]);
+			return TXRX_DROP;
+		}
+		memcpy(entry->last_pn, pn, CCMP_PN_LEN);
+	}
+
+	skb_pull(rx->skb, ieee80211_get_hdrlen(rx->fc));
+	__skb_queue_tail(&entry->skb_list, rx->skb);
+	entry->last_frag = frag;
+	entry->extra_len += rx->skb->len;
+	if (rx->fc & IEEE80211_FCTL_MOREFRAGS) {
+		rx->skb = NULL;
+		return TXRX_QUEUED;
+	}
+
+	rx->skb = __skb_dequeue(&entry->skb_list);
+	if (skb_tailroom(rx->skb) < entry->extra_len) {
+		I802_DEBUG_INC(rx->local->rx_expand_skb_head2);
+		if (unlikely(pskb_expand_head(rx->skb, 0, entry->extra_len,
+					      GFP_ATOMIC))) {
+			I802_DEBUG_INC(rx->local->rx_handlers_drop_defrag);
+			__skb_queue_purge(&entry->skb_list);
+			return TXRX_DROP;
+		}
+	}
+	while ((skb = __skb_dequeue(&entry->skb_list)))
+		memcpy(skb_put(rx->skb, skb->len), skb->data, skb->len);
+
+	/* Complete frame has been reassembled - process it now */
+	rx->fragmented = 1;
+
+ out:
+	if (rx->sta)
+		rx->sta->rx_packets++;
+	if (is_multicast_ether_addr(hdr->addr1))
+		rx->local->dot11MulticastReceivedFrameCount++;
+	else
+		ieee80211_led_rx(rx->local);
+	return TXRX_CONTINUE;
+}
+
+
+static ieee80211_txrx_result
+ieee80211_rx_h_monitor(struct ieee80211_txrx_data *rx)
+{
+	if (rx->sdata->type == IEEE80211_IF_TYPE_MNTR) {
+		ieee80211_rx_monitor(rx->dev, rx->skb, rx->u.rx.status);
+		return TXRX_QUEUED;
+	}
+
+	if (rx->u.rx.status->flag & RX_FLAG_RADIOTAP)
+		skb_pull(rx->skb, ieee80211_get_radiotap_len(rx->skb));
+
+	return TXRX_CONTINUE;
+}
+
+
+static ieee80211_txrx_result
+ieee80211_rx_h_check(struct ieee80211_txrx_data *rx)
+{
+	struct ieee80211_hdr *hdr;
+	int always_sta_key;
+	hdr = (struct ieee80211_hdr *) rx->skb->data;
+
+	/* Drop duplicate 802.11 retransmissions (IEEE 802.11 Chap. 9.2.9) */
+	if (rx->sta && !is_multicast_ether_addr(hdr->addr1)) {
+		if (unlikely(rx->fc & IEEE80211_FCTL_RETRY &&
+			     rx->sta->last_seq_ctrl[rx->u.rx.queue] ==
+			     hdr->seq_ctrl)) {
+			if (rx->u.rx.ra_match) {
+				rx->local->dot11FrameDuplicateCount++;
+				rx->sta->num_duplicates++;
+			}
+			return TXRX_DROP;
+		} else
+			rx->sta->last_seq_ctrl[rx->u.rx.queue] = hdr->seq_ctrl;
+	}
+
+	if ((rx->local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) &&
+	    rx->skb->len > FCS_LEN)
+		skb_trim(rx->skb, rx->skb->len - FCS_LEN);
+
+	if (unlikely(rx->skb->len < 16)) {
+		I802_DEBUG_INC(rx->local->rx_handlers_drop_short);
+		return TXRX_DROP;
+	}
+
+	if (!rx->u.rx.ra_match)
+		rx->skb->pkt_type = PACKET_OTHERHOST;
+	else if (compare_ether_addr(rx->dev->dev_addr, hdr->addr1) == 0)
+		rx->skb->pkt_type = PACKET_HOST;
+	else if (is_multicast_ether_addr(hdr->addr1)) {
+		if (is_broadcast_ether_addr(hdr->addr1))
+			rx->skb->pkt_type = PACKET_BROADCAST;
+		else
+			rx->skb->pkt_type = PACKET_MULTICAST;
+	} else
+		rx->skb->pkt_type = PACKET_OTHERHOST;
+
+	/* Drop disallowed frame classes based on STA auth/assoc state;
+	 * IEEE 802.11, Chap 5.5.
+	 *
+	 * 80211.o does filtering only based on association state, i.e., it
+	 * drops Class 3 frames from not associated stations. hostapd sends
+	 * deauth/disassoc frames when needed. In addition, hostapd is
+	 * responsible for filtering on both auth and assoc states.
+	 */
+	if (unlikely(((rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA ||
+		      ((rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL &&
+		       (rx->fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PSPOLL)) &&
+		     rx->sdata->type != IEEE80211_IF_TYPE_IBSS &&
+		     (!rx->sta || !(rx->sta->flags & WLAN_STA_ASSOC)))) {
+		if ((!(rx->fc & IEEE80211_FCTL_FROMDS) &&
+		     !(rx->fc & IEEE80211_FCTL_TODS) &&
+		     (rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA)
+		    || !rx->u.rx.ra_match) {
+			/* Drop IBSS frames and frames for other hosts
+			 * silently. */
+			return TXRX_DROP;
+		}
+
+		if (!rx->local->apdev)
+			return TXRX_DROP;
+
+		ieee80211_rx_mgmt(rx->local, rx->skb, rx->u.rx.status,
+				  ieee80211_msg_sta_not_assoc);
+		return TXRX_QUEUED;
+	}
+
+	if (rx->sdata->type == IEEE80211_IF_TYPE_STA)
+		always_sta_key = 0;
+	else
+		always_sta_key = 1;
+
+	if (rx->sta && rx->sta->key && always_sta_key) {
+		rx->key = rx->sta->key;
+	} else {
+		if (rx->sta && rx->sta->key)
+			rx->key = rx->sta->key;
+		else
+			rx->key = rx->sdata->default_key;
+
+		if ((rx->local->hw.flags & IEEE80211_HW_WEP_INCLUDE_IV) &&
+		    rx->fc & IEEE80211_FCTL_PROTECTED) {
+			int keyidx = ieee80211_wep_get_keyidx(rx->skb);
+
+			if (keyidx >= 0 && keyidx < NUM_DEFAULT_KEYS &&
+			    (!rx->sta || !rx->sta->key || keyidx > 0))
+				rx->key = rx->sdata->keys[keyidx];
+
+			if (!rx->key) {
+				if (!rx->u.rx.ra_match)
+					return TXRX_DROP;
+				printk(KERN_DEBUG "%s: RX WEP frame with "
+				       "unknown keyidx %d (A1=" MAC_FMT " A2="
+				       MAC_FMT " A3=" MAC_FMT ")\n",
+				       rx->dev->name, keyidx,
+				       MAC_ARG(hdr->addr1),
+				       MAC_ARG(hdr->addr2),
+				       MAC_ARG(hdr->addr3));
+				if (!rx->local->apdev)
+					return TXRX_DROP;
+				ieee80211_rx_mgmt(
+					rx->local, rx->skb, rx->u.rx.status,
+					ieee80211_msg_wep_frame_unknown_key);
+				return TXRX_QUEUED;
+			}
+		}
+	}
+
+	if (rx->fc & IEEE80211_FCTL_PROTECTED && rx->key && rx->u.rx.ra_match) {
+		rx->key->tx_rx_count++;
+		if (unlikely(rx->local->key_tx_rx_threshold &&
+			     rx->key->tx_rx_count >
+			     rx->local->key_tx_rx_threshold)) {
+			ieee80211_key_threshold_notify(rx->dev, rx->key,
+						       rx->sta);
+		}
+	}
+
+	return TXRX_CONTINUE;
+}
+
+
+static ieee80211_txrx_result
+ieee80211_rx_h_sta_process(struct ieee80211_txrx_data *rx)
+{
+	struct sta_info *sta = rx->sta;
+	struct net_device *dev = rx->dev;
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data;
+
+	if (!sta)
+		return TXRX_CONTINUE;
+
+	/* Update last_rx only for IBSS packets which are for the current
+	 * BSSID to avoid keeping the current IBSS network alive in cases where
+	 * other STAs are using different BSSID. */
+	if (rx->sdata->type == IEEE80211_IF_TYPE_IBSS) {
+		u8 *bssid = ieee80211_get_bssid(hdr, rx->skb->len);
+		if (compare_ether_addr(bssid, rx->sdata->u.sta.bssid) == 0)
+			sta->last_rx = jiffies;
+	} else
+	if (!is_multicast_ether_addr(hdr->addr1) ||
+	    rx->sdata->type == IEEE80211_IF_TYPE_STA) {
+		/* Update last_rx only for unicast frames in order to prevent
+		 * the Probe Request frames (the only broadcast frames from a
+		 * STA in infrastructure mode) from keeping a connection alive.
+		 */
+		sta->last_rx = jiffies;
+	}
+
+	if (!rx->u.rx.ra_match)
+		return TXRX_CONTINUE;
+
+	sta->rx_fragments++;
+	sta->rx_bytes += rx->skb->len;
+	sta->last_rssi = (sta->last_rssi * 15 +
+			  rx->u.rx.status->ssi) / 16;
+	sta->last_signal = (sta->last_signal * 15 +
+			    rx->u.rx.status->signal) / 16;
+	sta->last_noise = (sta->last_noise * 15 +
+			   rx->u.rx.status->noise) / 16;
+
+	if (!(rx->fc & IEEE80211_FCTL_MOREFRAGS)) {
+		/* Change STA power saving mode only in the end of a frame
+		 * exchange sequence */
+		if ((sta->flags & WLAN_STA_PS) && !(rx->fc & IEEE80211_FCTL_PM))
+			rx->u.rx.sent_ps_buffered += ap_sta_ps_end(dev, sta);
+		else if (!(sta->flags & WLAN_STA_PS) &&
+			 (rx->fc & IEEE80211_FCTL_PM))
+			ap_sta_ps_start(dev, sta);
+	}
+
+	/* Drop data::nullfunc frames silently, since they are used only to
+	 * control station power saving mode. */
+	if ((rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA &&
+	    (rx->fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_NULLFUNC) {
+		I802_DEBUG_INC(rx->local->rx_handlers_drop_nullfunc);
+		/* Update counter and free packet here to avoid counting this
+		 * as a dropped packed. */
+		sta->rx_packets++;
+		dev_kfree_skb(rx->skb);
+		return TXRX_QUEUED;
+	}
+
+	return TXRX_CONTINUE;
+} /* ieee80211_rx_h_sta_process */
+
+
+static ieee80211_txrx_result
+ieee80211_rx_h_wep_weak_iv_detection(struct ieee80211_txrx_data *rx)
+{
+	if (!rx->sta || !(rx->fc & IEEE80211_FCTL_PROTECTED) ||
+	    (rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA ||
+	    !rx->key || rx->key->alg != ALG_WEP || !rx->u.rx.ra_match)
+		return TXRX_CONTINUE;
+
+	/* Check for weak IVs, if hwaccel did not remove IV from the frame */
+	if ((rx->local->hw.flags & IEEE80211_HW_WEP_INCLUDE_IV) ||
+	    rx->key->force_sw_encrypt) {
+		u8 *iv = ieee80211_wep_is_weak_iv(rx->skb, rx->key);
+		if (iv) {
+			rx->sta->wep_weak_iv_count++;
+		}
+	}
+
+	return TXRX_CONTINUE;
+}
+
+
+static ieee80211_txrx_result
+ieee80211_rx_h_wep_decrypt(struct ieee80211_txrx_data *rx)
+{
+	/* If the device handles decryption totally, skip this test */
+	if (rx->local->hw.flags & IEEE80211_HW_DEVICE_HIDES_WEP)
+		return TXRX_CONTINUE;
+
+	if ((rx->key && rx->key->alg != ALG_WEP) ||
+	    !(rx->fc & IEEE80211_FCTL_PROTECTED) ||
+	    ((rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA &&
+	     ((rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_MGMT ||
+	      (rx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_AUTH)))
+		return TXRX_CONTINUE;
+
+	if (!rx->key) {
+		printk(KERN_DEBUG "%s: RX WEP frame, but no key set\n",
+		       rx->dev->name);
+		return TXRX_DROP;
+	}
+
+	if (!(rx->u.rx.status->flag & RX_FLAG_DECRYPTED) ||
+	    rx->key->force_sw_encrypt) {
+		if (ieee80211_wep_decrypt(rx->local, rx->skb, rx->key)) {
+			printk(KERN_DEBUG "%s: RX WEP frame, decrypt "
+			       "failed\n", rx->dev->name);
+			return TXRX_DROP;
+		}
+	} else if (rx->local->hw.flags & IEEE80211_HW_WEP_INCLUDE_IV) {
+		ieee80211_wep_remove_iv(rx->local, rx->skb, rx->key);
+		/* remove ICV */
+		skb_trim(rx->skb, rx->skb->len - 4);
+	}
+
+	return TXRX_CONTINUE;
+}
+
+
+static ieee80211_txrx_result
+ieee80211_rx_h_802_1x_pae(struct ieee80211_txrx_data *rx)
+{
+	if (rx->sdata->eapol && ieee80211_is_eapol(rx->skb) &&
+	    rx->sdata->type != IEEE80211_IF_TYPE_STA && rx->u.rx.ra_match) {
+		/* Pass both encrypted and unencrypted EAPOL frames to user
+		 * space for processing. */
+		if (!rx->local->apdev)
+			return TXRX_DROP;
+		ieee80211_rx_mgmt(rx->local, rx->skb, rx->u.rx.status,
+				  ieee80211_msg_normal);
+		return TXRX_QUEUED;
+	}
+
+	if (unlikely(rx->sdata->ieee802_1x &&
+		     (rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA &&
+		     (rx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_NULLFUNC &&
+		     (!rx->sta || !(rx->sta->flags & WLAN_STA_AUTHORIZED)) &&
+		     !ieee80211_is_eapol(rx->skb))) {
+#ifdef CONFIG_MAC80211_DEBUG
+		struct ieee80211_hdr *hdr =
+			(struct ieee80211_hdr *) rx->skb->data;
+		printk(KERN_DEBUG "%s: dropped frame from " MAC_FMT
+		       " (unauthorized port)\n", rx->dev->name,
+		       MAC_ARG(hdr->addr2));
+#endif /* CONFIG_MAC80211_DEBUG */
+		return TXRX_DROP;
+	}
+
+	return TXRX_CONTINUE;
+}
+
+
+static ieee80211_txrx_result
+ieee80211_rx_h_drop_unencrypted(struct ieee80211_txrx_data *rx)
+{
+	/*  If the device handles decryption totally, skip this test */
+	if (rx->local->hw.flags & IEEE80211_HW_DEVICE_HIDES_WEP)
+		return TXRX_CONTINUE;
+
+	/* Drop unencrypted frames if key is set. */
+	if (unlikely(!(rx->fc & IEEE80211_FCTL_PROTECTED) &&
+		     (rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA &&
+		     (rx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_NULLFUNC &&
+		     (rx->key || rx->sdata->drop_unencrypted) &&
+		     (rx->sdata->eapol == 0 ||
+		      !ieee80211_is_eapol(rx->skb)))) {
+		printk(KERN_DEBUG "%s: RX non-WEP frame, but expected "
+		       "encryption\n", rx->dev->name);
+		return TXRX_DROP;
+	}
+	return TXRX_CONTINUE;
+}
+
+
+static ieee80211_txrx_result
+ieee80211_rx_h_mgmt(struct ieee80211_txrx_data *rx)
+{
+	struct ieee80211_sub_if_data *sdata;
+
+	if (!rx->u.rx.ra_match)
+		return TXRX_DROP;
+
+	sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev);
+	if ((sdata->type == IEEE80211_IF_TYPE_STA ||
+	     sdata->type == IEEE80211_IF_TYPE_IBSS) &&
+	    !rx->local->user_space_mlme) {
+		ieee80211_sta_rx_mgmt(rx->dev, rx->skb, rx->u.rx.status);
+	} else {
+		/* Management frames are sent to hostapd for processing */
+		if (!rx->local->apdev)
+			return TXRX_DROP;
+		ieee80211_rx_mgmt(rx->local, rx->skb, rx->u.rx.status,
+				  ieee80211_msg_normal);
+	}
+	return TXRX_QUEUED;
+}
+
+
+static ieee80211_txrx_result
+ieee80211_rx_h_passive_scan(struct ieee80211_txrx_data *rx)
+{
+	struct ieee80211_local *local = rx->local;
+	struct sk_buff *skb = rx->skb;
+
+	if (unlikely(local->sta_scanning != 0)) {
+		ieee80211_sta_rx_scan(rx->dev, skb, rx->u.rx.status);
+		return TXRX_QUEUED;
+	}
+
+	if (unlikely(rx->u.rx.in_scan)) {
+		/* scanning finished during invoking of handlers */
+		I802_DEBUG_INC(local->rx_handlers_drop_passive_scan);
+		return TXRX_DROP;
+	}
+
+	return TXRX_CONTINUE;
+}
+
+
+static void ieee80211_rx_michael_mic_report(struct net_device *dev,
+					    struct ieee80211_hdr *hdr,
+					    struct sta_info *sta,
+					    struct ieee80211_txrx_data *rx)
+{
+	int keyidx, hdrlen;
+
+	hdrlen = ieee80211_get_hdrlen_from_skb(rx->skb);
+	if (rx->skb->len >= hdrlen + 4)
+		keyidx = rx->skb->data[hdrlen + 3] >> 6;
+	else
+		keyidx = -1;
+
+	/* TODO: verify that this is not triggered by fragmented
+	 * frames (hw does not verify MIC for them). */
+	printk(KERN_DEBUG "%s: TKIP hwaccel reported Michael MIC "
+	       "failure from " MAC_FMT " to " MAC_FMT " keyidx=%d\n",
+	       dev->name, MAC_ARG(hdr->addr2), MAC_ARG(hdr->addr1), keyidx);
+
+	if (!sta) {
+		/* Some hardware versions seem to generate incorrect
+		 * Michael MIC reports; ignore them to avoid triggering
+		 * countermeasures. */
+		printk(KERN_DEBUG "%s: ignored spurious Michael MIC "
+		       "error for unknown address " MAC_FMT "\n",
+		       dev->name, MAC_ARG(hdr->addr2));
+		goto ignore;
+	}
+
+	if (!(rx->fc & IEEE80211_FCTL_PROTECTED)) {
+		printk(KERN_DEBUG "%s: ignored spurious Michael MIC "
+		       "error for a frame with no ISWEP flag (src "
+		       MAC_FMT ")\n", dev->name, MAC_ARG(hdr->addr2));
+		goto ignore;
+	}
+
+	if ((rx->local->hw.flags & IEEE80211_HW_WEP_INCLUDE_IV) &&
+	    rx->sdata->type == IEEE80211_IF_TYPE_AP) {
+		keyidx = ieee80211_wep_get_keyidx(rx->skb);
+		/* AP with Pairwise keys support should never receive Michael
+		 * MIC errors for non-zero keyidx because these are reserved
+		 * for group keys and only the AP is sending real multicast
+		 * frames in BSS. */
+		if (keyidx) {
+			printk(KERN_DEBUG "%s: ignored Michael MIC error for "
+			       "a frame with non-zero keyidx (%d) (src " MAC_FMT
+			       ")\n", dev->name, keyidx, MAC_ARG(hdr->addr2));
+			goto ignore;
+		}
+	}
+
+	if ((rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA &&
+	    ((rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_MGMT ||
+	     (rx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_AUTH)) {
+		printk(KERN_DEBUG "%s: ignored spurious Michael MIC "
+		       "error for a frame that cannot be encrypted "
+		       "(fc=0x%04x) (src " MAC_FMT ")\n",
+		       dev->name, rx->fc, MAC_ARG(hdr->addr2));
+		goto ignore;
+	}
+
+	do {
+		union iwreq_data wrqu;
+		char *buf = kmalloc(128, GFP_ATOMIC);
+		if (!buf)
+			break;
+
+		/* TODO: needed parameters: count, key type, TSC */
+		sprintf(buf, "MLME-MICHAELMICFAILURE.indication("
+			"keyid=%d %scast addr=" MAC_FMT ")",
+			keyidx, hdr->addr1[0] & 0x01 ? "broad" : "uni",
+			MAC_ARG(hdr->addr2));
+		memset(&wrqu, 0, sizeof(wrqu));
+		wrqu.data.length = strlen(buf);
+		wireless_send_event(rx->dev, IWEVCUSTOM, &wrqu, buf);
+		kfree(buf);
+	} while (0);
+
+	/* TODO: consider verifying the MIC error report with software
+	 * implementation if we get too many spurious reports from the
+	 * hardware. */
+	if (!rx->local->apdev)
+		goto ignore;
+	ieee80211_rx_mgmt(rx->local, rx->skb, rx->u.rx.status,
+			  ieee80211_msg_michael_mic_failure);
+	return;
+
+ ignore:
+	dev_kfree_skb(rx->skb);
+	rx->skb = NULL;
+}
+
+static inline ieee80211_txrx_result __ieee80211_invoke_rx_handlers(
+				struct ieee80211_local *local,
+				ieee80211_rx_handler *handlers,
+				struct ieee80211_txrx_data *rx,
+				struct sta_info *sta)
+{
+	ieee80211_rx_handler *handler;
+	ieee80211_txrx_result res = TXRX_DROP;
+
+	for (handler = handlers; *handler != NULL; handler++) {
+		res = (*handler)(rx);
+		if (res != TXRX_CONTINUE) {
+			if (res == TXRX_DROP) {
+				I802_DEBUG_INC(local->rx_handlers_drop);
+				if (sta)
+					sta->rx_dropped++;
+			}
+			if (res == TXRX_QUEUED)
+				I802_DEBUG_INC(local->rx_handlers_queued);
+			break;
+		}
+	}
+
+	if (res == TXRX_DROP) {
+		dev_kfree_skb(rx->skb);
+	}
+	return res;
+}
+
+static inline void ieee80211_invoke_rx_handlers(struct ieee80211_local *local,
+						ieee80211_rx_handler *handlers,
+						struct ieee80211_txrx_data *rx,
+						struct sta_info *sta)
+{
+	if (__ieee80211_invoke_rx_handlers(local, handlers, rx, sta) ==
+	    TXRX_CONTINUE)
+		dev_kfree_skb(rx->skb);
+}
+
+/*
+ * This is the receive path handler. It is called by a low level driver when an
+ * 802.11 MPDU is received from the hardware.
+ */
+void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb,
+		    struct ieee80211_rx_status *status)
+{
+	struct ieee80211_local *local = hw_to_local(hw);
+	struct ieee80211_sub_if_data *sdata;
+	struct sta_info *sta;
+	struct ieee80211_hdr *hdr;
+	struct ieee80211_txrx_data rx;
+	u16 type;
+	int multicast;
+	int radiotap_len = 0;
+
+	if (status->flag & RX_FLAG_RADIOTAP) {
+		radiotap_len = ieee80211_get_radiotap_len(skb);
+		skb_pull(skb, radiotap_len);
+	}
+
+	hdr = (struct ieee80211_hdr *) skb->data;
+	memset(&rx, 0, sizeof(rx));
+	rx.skb = skb;
+	rx.local = local;
+
+	rx.u.rx.status = status;
+	rx.fc = skb->len >= 2 ? le16_to_cpu(hdr->frame_control) : 0;
+	type = rx.fc & IEEE80211_FCTL_FTYPE;
+	if (type == IEEE80211_FTYPE_DATA || type == IEEE80211_FTYPE_MGMT)
+		local->dot11ReceivedFragmentCount++;
+	multicast = is_multicast_ether_addr(hdr->addr1);
+
+	if (skb->len >= 16)
+		sta = rx.sta = sta_info_get(local, hdr->addr2);
+	else
+		sta = rx.sta = NULL;
+
+	if (sta) {
+		rx.dev = sta->dev;
+		rx.sdata = IEEE80211_DEV_TO_SUB_IF(rx.dev);
+	}
+
+	if ((status->flag & RX_FLAG_MMIC_ERROR)) {
+		ieee80211_rx_michael_mic_report(local->mdev, hdr, sta, &rx);
+		goto end;
+	}
+
+	if (unlikely(local->sta_scanning))
+		rx.u.rx.in_scan = 1;
+
+	if (__ieee80211_invoke_rx_handlers(local, local->rx_pre_handlers, &rx,
+					   sta) != TXRX_CONTINUE)
+		goto end;
+	skb = rx.skb;
+
+	skb_push(skb, radiotap_len);
+	if (sta && !sta->assoc_ap && !(sta->flags & WLAN_STA_WDS) &&
+	    !local->iff_promiscs && !multicast) {
+		rx.u.rx.ra_match = 1;
+		ieee80211_invoke_rx_handlers(local, local->rx_handlers, &rx,
+					     sta);
+	} else {
+		struct ieee80211_sub_if_data *prev = NULL;
+		struct sk_buff *skb_new;
+		u8 *bssid = ieee80211_get_bssid(hdr, skb->len - radiotap_len);
+
+		read_lock(&local->sub_if_lock);
+		list_for_each_entry(sdata, &local->sub_if_list, list) {
+			rx.u.rx.ra_match = 1;
+			switch (sdata->type) {
+			case IEEE80211_IF_TYPE_STA:
+				if (!bssid)
+					continue;
+				if (!ieee80211_bssid_match(bssid,
+							sdata->u.sta.bssid)) {
+					if (!rx.u.rx.in_scan)
+						continue;
+					rx.u.rx.ra_match = 0;
+				} else if (!multicast &&
+					   compare_ether_addr(sdata->dev->dev_addr,
+							      hdr->addr1) != 0) {
+					if (!sdata->promisc)
+						continue;
+					rx.u.rx.ra_match = 0;
+				}
+				break;
+			case IEEE80211_IF_TYPE_IBSS:
+				if (!bssid)
+					continue;
+				if (!ieee80211_bssid_match(bssid,
+							sdata->u.sta.bssid)) {
+					if (!rx.u.rx.in_scan)
+						continue;
+					rx.u.rx.ra_match = 0;
+				} else if (!multicast &&
+					   compare_ether_addr(sdata->dev->dev_addr,
+							      hdr->addr1) != 0) {
+					if (!sdata->promisc)
+						continue;
+					rx.u.rx.ra_match = 0;
+				} else if (!sta)
+					sta = rx.sta =
+						ieee80211_ibss_add_sta(sdata->dev,
+								       skb, bssid,
+								       hdr->addr2);
+				break;
+			case IEEE80211_IF_TYPE_AP:
+				if (!bssid) {
+					if (compare_ether_addr(sdata->dev->dev_addr,
+							       hdr->addr1) != 0)
+						continue;
+				} else if (!ieee80211_bssid_match(bssid,
+							sdata->dev->dev_addr)) {
+					if (!rx.u.rx.in_scan)
+						continue;
+					rx.u.rx.ra_match = 0;
+				}
+				if (sdata->dev == local->mdev &&
+				    !rx.u.rx.in_scan)
+					/* do not receive anything via
+					 * master device when not scanning */
+					continue;
+				break;
+			case IEEE80211_IF_TYPE_WDS:
+				if (bssid ||
+				    (rx.fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA)
+					continue;
+				if (compare_ether_addr(sdata->u.wds.remote_addr,
+						       hdr->addr2) != 0)
+					continue;
+				break;
+			}
+
+			if (prev) {
+				skb_new = skb_copy(skb, GFP_ATOMIC);
+				if (!skb_new) {
+					if (net_ratelimit())
+						printk(KERN_DEBUG "%s: failed to copy "
+						       "multicast frame for %s",
+						       local->mdev->name, prev->dev->name);
+					continue;
+				}
+				rx.skb = skb_new;
+				rx.dev = prev->dev;
+				rx.sdata = prev;
+				ieee80211_invoke_rx_handlers(local,
+							     local->rx_handlers,
+							     &rx, sta);
+			}
+			prev = sdata;
+		}
+		if (prev) {
+			rx.skb = skb;
+			rx.dev = prev->dev;
+			rx.sdata = prev;
+			ieee80211_invoke_rx_handlers(local, local->rx_handlers,
+						     &rx, sta);
+		} else
+			dev_kfree_skb(skb);
+		read_unlock(&local->sub_if_lock);
+	}
+
+  end:
+	if (sta)
+		sta_info_put(sta);
+}
+EXPORT_SYMBOL(__ieee80211_rx);
+
+static ieee80211_txrx_result
+ieee80211_tx_h_load_stats(struct ieee80211_txrx_data *tx)
+{
+	struct ieee80211_local *local = tx->local;
+	struct ieee80211_hw_mode *mode = tx->u.tx.mode;
+	struct sk_buff *skb = tx->skb;
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+	u32 load = 0, hdrtime;
+
+	/* TODO: this could be part of tx_status handling, so that the number
+	 * of retries would be known; TX rate should in that case be stored
+	 * somewhere with the packet */
+
+	/* Estimate total channel use caused by this frame */
+
+	/* 1 bit at 1 Mbit/s takes 1 usec; in channel_use values,
+	 * 1 usec = 1/8 * (1080 / 10) = 13.5 */
+
+	if (mode->mode == MODE_IEEE80211A ||
+	    mode->mode == MODE_ATHEROS_TURBO ||
+	    mode->mode == MODE_ATHEROS_TURBOG ||
+	    (mode->mode == MODE_IEEE80211G &&
+	     tx->u.tx.rate->flags & IEEE80211_RATE_ERP))
+		hdrtime = CHAN_UTIL_HDR_SHORT;
+	else
+		hdrtime = CHAN_UTIL_HDR_LONG;
+
+	load = hdrtime;
+	if (!is_multicast_ether_addr(hdr->addr1))
+		load += hdrtime;
+
+	if (tx->u.tx.control->flags & IEEE80211_TXCTL_USE_RTS_CTS)
+		load += 2 * hdrtime;
+	else if (tx->u.tx.control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT)
+		load += hdrtime;
+
+	load += skb->len * tx->u.tx.rate->rate_inv;
+
+	if (tx->u.tx.extra_frag) {
+		int i;
+		for (i = 0; i < tx->u.tx.num_extra_frag; i++) {
+			load += 2 * hdrtime;
+			load += tx->u.tx.extra_frag[i]->len *
+				tx->u.tx.rate->rate;
+		}
+	}
+
+	/* Divide channel_use by 8 to avoid wrapping around the counter */
+	load >>= CHAN_UTIL_SHIFT;
+	local->channel_use_raw += load;
+	if (tx->sta)
+		tx->sta->channel_use_raw += load;
+	tx->sdata->channel_use_raw += load;
+
+	return TXRX_CONTINUE;
+}
+
+
+static ieee80211_txrx_result
+ieee80211_rx_h_load_stats(struct ieee80211_txrx_data *rx)
+{
+	struct ieee80211_local *local = rx->local;
+	struct sk_buff *skb = rx->skb;
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+	u32 load = 0, hdrtime;
+	struct ieee80211_rate *rate;
+	struct ieee80211_hw_mode *mode = local->hw.conf.mode;
+	int i;
+
+	/* Estimate total channel use caused by this frame */
+
+	if (unlikely(mode->num_rates < 0))
+		return TXRX_CONTINUE;
+
+	rate = &mode->rates[0];
+	for (i = 0; i < mode->num_rates; i++) {
+		if (mode->rates[i].val == rx->u.rx.status->rate) {
+			rate = &mode->rates[i];
+			break;
+		}
+	}
+
+	/* 1 bit at 1 Mbit/s takes 1 usec; in channel_use values,
+	 * 1 usec = 1/8 * (1080 / 10) = 13.5 */
+
+	if (mode->mode == MODE_IEEE80211A ||
+	    mode->mode == MODE_ATHEROS_TURBO ||
+	    mode->mode == MODE_ATHEROS_TURBOG ||
+	    (mode->mode == MODE_IEEE80211G &&
+	     rate->flags & IEEE80211_RATE_ERP))
+		hdrtime = CHAN_UTIL_HDR_SHORT;
+	else
+		hdrtime = CHAN_UTIL_HDR_LONG;
+
+	load = hdrtime;
+	if (!is_multicast_ether_addr(hdr->addr1))
+		load += hdrtime;
+
+	load += skb->len * rate->rate_inv;
+
+	/* Divide channel_use by 8 to avoid wrapping around the counter */
+	load >>= CHAN_UTIL_SHIFT;
+	local->channel_use_raw += load;
+	if (rx->sta)
+		rx->sta->channel_use_raw += load;
+	rx->u.rx.load = load;
+
+	return TXRX_CONTINUE;
+}
+
+static ieee80211_txrx_result
+ieee80211_rx_h_if_stats(struct ieee80211_txrx_data *rx)
+{
+	rx->sdata->channel_use_raw += rx->u.rx.load;
+	return TXRX_CONTINUE;
+}
+
+static void ieee80211_stat_refresh(unsigned long data)
+{
+	struct ieee80211_local *local = (struct ieee80211_local *) data;
+	struct sta_info *sta;
+	struct ieee80211_sub_if_data *sdata;
+
+	if (!local->stat_time)
+		return;
+
+	/* go through all stations */
+	spin_lock_bh(&local->sta_lock);
+	list_for_each_entry(sta, &local->sta_list, list) {
+		sta->channel_use = (sta->channel_use_raw / local->stat_time) /
+			CHAN_UTIL_PER_10MS;
+		sta->channel_use_raw = 0;
+	}
+	spin_unlock_bh(&local->sta_lock);
+
+	/* go through all subinterfaces */
+	read_lock(&local->sub_if_lock);
+	list_for_each_entry(sdata, &local->sub_if_list, list) {
+		sdata->channel_use = (sdata->channel_use_raw /
+				      local->stat_time) / CHAN_UTIL_PER_10MS;
+		sdata->channel_use_raw = 0;
+	}
+	read_unlock(&local->sub_if_lock);
+
+	/* hardware interface */
+	local->channel_use = (local->channel_use_raw /
+			      local->stat_time) / CHAN_UTIL_PER_10MS;
+	local->channel_use_raw = 0;
+
+	local->stat_timer.expires = jiffies + HZ * local->stat_time / 100;
+	add_timer(&local->stat_timer);
+}
+
+
+/* This is a version of the rx handler that can be called from hard irq
+ * context. Post the skb on the queue and schedule the tasklet */
+void ieee80211_rx_irqsafe(struct ieee80211_hw *hw, struct sk_buff *skb,
+			  struct ieee80211_rx_status *status)
+{
+	struct ieee80211_local *local = hw_to_local(hw);
+
+	BUILD_BUG_ON(sizeof(struct ieee80211_rx_status) > sizeof(skb->cb));
+
+	skb->dev = local->mdev;
+	/* copy status into skb->cb for use by tasklet */
+	memcpy(skb->cb, status, sizeof(*status));
+	skb->pkt_type = IEEE80211_RX_MSG;
+	skb_queue_tail(&local->skb_queue, skb);
+	tasklet_schedule(&local->tasklet);
+}
+EXPORT_SYMBOL(ieee80211_rx_irqsafe);
+
+void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw,
+				 struct sk_buff *skb,
+				 struct ieee80211_tx_status *status)
+{
+	struct ieee80211_local *local = hw_to_local(hw);
+	struct ieee80211_tx_status *saved;
+	int tmp;
+
+	skb->dev = local->mdev;
+	saved = kmalloc(sizeof(struct ieee80211_tx_status), GFP_ATOMIC);
+	if (unlikely(!saved)) {
+		if (net_ratelimit())
+			printk(KERN_WARNING "%s: Not enough memory, "
+			       "dropping tx status", skb->dev->name);
+		/* should be dev_kfree_skb_irq, but due to this function being
+		 * named _irqsafe instead of just _irq we can't be sure that
+		 * people won't call it from non-irq contexts */
+		dev_kfree_skb_any(skb);
+		return;
+	}
+	memcpy(saved, status, sizeof(struct ieee80211_tx_status));
+	/* copy pointer to saved status into skb->cb for use by tasklet */
+	memcpy(skb->cb, &saved, sizeof(saved));
+
+	skb->pkt_type = IEEE80211_TX_STATUS_MSG;
+	skb_queue_tail(status->control.flags & IEEE80211_TXCTL_REQ_TX_STATUS ?
+		       &local->skb_queue : &local->skb_queue_unreliable, skb);
+	tmp = skb_queue_len(&local->skb_queue) +
+		skb_queue_len(&local->skb_queue_unreliable);
+	while (tmp > IEEE80211_IRQSAFE_QUEUE_LIMIT &&
+	       (skb = skb_dequeue(&local->skb_queue_unreliable))) {
+		memcpy(&saved, skb->cb, sizeof(saved));
+		kfree(saved);
+		dev_kfree_skb_irq(skb);
+		tmp--;
+		I802_DEBUG_INC(local->tx_status_drop);
+	}
+	tasklet_schedule(&local->tasklet);
+}
+EXPORT_SYMBOL(ieee80211_tx_status_irqsafe);
+
+static void ieee80211_tasklet_handler(unsigned long data)
+{
+	struct ieee80211_local *local = (struct ieee80211_local *) data;
+	struct sk_buff *skb;
+	struct ieee80211_rx_status rx_status;
+	struct ieee80211_tx_status *tx_status;
+
+	while ((skb = skb_dequeue(&local->skb_queue)) ||
+	       (skb = skb_dequeue(&local->skb_queue_unreliable))) {
+		switch (skb->pkt_type) {
+		case IEEE80211_RX_MSG:
+			/* status is in skb->cb */
+			memcpy(&rx_status, skb->cb, sizeof(rx_status));
+			/* Clear skb->type in order to not confuse kernel
+			 * netstack. */
+			skb->pkt_type = 0;
+			__ieee80211_rx(local_to_hw(local), skb, &rx_status);
+			break;
+		case IEEE80211_TX_STATUS_MSG:
+			/* get pointer to saved status out of skb->cb */
+			memcpy(&tx_status, skb->cb, sizeof(tx_status));
+			skb->pkt_type = 0;
+			ieee80211_tx_status(local_to_hw(local),
+					    skb, tx_status);
+			kfree(tx_status);
+			break;
+		default: /* should never get here! */
+			printk(KERN_ERR "%s: Unknown message type (%d)\n",
+			       local->mdev->name, skb->pkt_type);
+			dev_kfree_skb(skb);
+			break;
+		}
+	}
+}
+
+
+/* Remove added headers (e.g., QoS control), encryption header/MIC, etc. to
+ * make a prepared TX frame (one that has been given to hw) to look like brand
+ * new IEEE 802.11 frame that is ready to go through TX processing again.
+ * Also, tx_packet_data in cb is restored from tx_control. */
+static void ieee80211_remove_tx_extra(struct ieee80211_local *local,
+				      struct ieee80211_key *key,
+				      struct sk_buff *skb,
+				      struct ieee80211_tx_control *control)
+{
+	int hdrlen, iv_len, mic_len;
+	struct ieee80211_tx_packet_data *pkt_data;
+
+	pkt_data = (struct ieee80211_tx_packet_data *)skb->cb;
+	pkt_data->ifindex = control->ifindex;
+	pkt_data->mgmt_iface = (control->type == IEEE80211_IF_TYPE_MGMT);
+	pkt_data->req_tx_status = !!(control->flags & IEEE80211_TXCTL_REQ_TX_STATUS);
+	pkt_data->do_not_encrypt = !!(control->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT);
+	pkt_data->requeue = !!(control->flags & IEEE80211_TXCTL_REQUEUE);
+	pkt_data->queue = control->queue;
+
+	hdrlen = ieee80211_get_hdrlen_from_skb(skb);
+
+	if (!key)
+		goto no_key;
+
+	switch (key->alg) {
+	case ALG_WEP:
+		iv_len = WEP_IV_LEN;
+		mic_len = WEP_ICV_LEN;
+		break;
+	case ALG_TKIP:
+		iv_len = TKIP_IV_LEN;
+		mic_len = TKIP_ICV_LEN;
+		break;
+	case ALG_CCMP:
+		iv_len = CCMP_HDR_LEN;
+		mic_len = CCMP_MIC_LEN;
+		break;
+	default:
+		goto no_key;
+	}
+
+	if (skb->len >= mic_len && key->force_sw_encrypt)
+		skb_trim(skb, skb->len - mic_len);
+	if (skb->len >= iv_len && skb->len > hdrlen) {
+		memmove(skb->data + iv_len, skb->data, hdrlen);
+		skb_pull(skb, iv_len);
+	}
+
+no_key:
+	{
+		struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+		u16 fc = le16_to_cpu(hdr->frame_control);
+		if ((fc & 0x8C) == 0x88) /* QoS Control Field */ {
+			fc &= ~IEEE80211_STYPE_QOS_DATA;
+			hdr->frame_control = cpu_to_le16(fc);
+			memmove(skb->data + 2, skb->data, hdrlen - 2);
+			skb_pull(skb, 2);
+		}
+	}
+}
+
+
+void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb,
+			 struct ieee80211_tx_status *status)
+{
+	struct sk_buff *skb2;
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+	struct ieee80211_local *local = hw_to_local(hw);
+	u16 frag, type;
+	u32 msg_type;
+
+	if (!status) {
+		printk(KERN_ERR
+		       "%s: ieee80211_tx_status called with NULL status\n",
+		       local->mdev->name);
+		dev_kfree_skb(skb);
+		return;
+	}
+
+	if (status->excessive_retries) {
+		struct sta_info *sta;
+		sta = sta_info_get(local, hdr->addr1);
+		if (sta) {
+			if (sta->flags & WLAN_STA_PS) {
+				/* The STA is in power save mode, so assume
+				 * that this TX packet failed because of that.
+				 */
+				status->excessive_retries = 0;
+				status->flags |= IEEE80211_TX_STATUS_TX_FILTERED;
+			}
+			sta_info_put(sta);
+		}
+	}
+
+	if (status->flags & IEEE80211_TX_STATUS_TX_FILTERED) {
+		struct sta_info *sta;
+		sta = sta_info_get(local, hdr->addr1);
+		if (sta) {
+			sta->tx_filtered_count++;
+
+			/* Clear the TX filter mask for this STA when sending
+			 * the next packet. If the STA went to power save mode,
+			 * this will happen when it is waking up for the next
+			 * time. */
+			sta->clear_dst_mask = 1;
+
+			/* TODO: Is the WLAN_STA_PS flag always set here or is
+			 * the race between RX and TX status causing some
+			 * packets to be filtered out before 80211.o gets an
+			 * update for PS status? This seems to be the case, so
+			 * no changes are likely to be needed. */
+			if (sta->flags & WLAN_STA_PS &&
+			    skb_queue_len(&sta->tx_filtered) <
+			    STA_MAX_TX_BUFFER) {
+				ieee80211_remove_tx_extra(local, sta->key,
+							  skb,
+							  &status->control);
+				skb_queue_tail(&sta->tx_filtered, skb);
+			} else if (!(sta->flags & WLAN_STA_PS) &&
+				   !(status->control.flags & IEEE80211_TXCTL_REQUEUE)) {
+				/* Software retry the packet once */
+				status->control.flags |= IEEE80211_TXCTL_REQUEUE;
+				ieee80211_remove_tx_extra(local, sta->key,
+							  skb,
+							  &status->control);
+				dev_queue_xmit(skb);
+			} else {
+				if (net_ratelimit()) {
+					printk(KERN_DEBUG "%s: dropped TX "
+					       "filtered frame queue_len=%d "
+					       "PS=%d @%lu\n",
+					       local->mdev->name,
+					       skb_queue_len(
+						       &sta->tx_filtered),
+					       !!(sta->flags & WLAN_STA_PS),
+					       jiffies);
+				}
+				dev_kfree_skb(skb);
+			}
+			sta_info_put(sta);
+			return;
+		}
+	} else {
+		/* FIXME: STUPID to call this with both local and local->mdev */
+		rate_control_tx_status(local, local->mdev, skb, status);
+	}
+
+	ieee80211_led_tx(local, 0);
+
+	/* SNMP counters
+	 * Fragments are passed to low-level drivers as separate skbs, so these
+	 * are actually fragments, not frames. Update frame counters only for
+	 * the first fragment of the frame. */
+
+	frag = le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG;
+	type = le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_FTYPE;
+
+	if (status->flags & IEEE80211_TX_STATUS_ACK) {
+		if (frag == 0) {
+			local->dot11TransmittedFrameCount++;
+			if (is_multicast_ether_addr(hdr->addr1))
+				local->dot11MulticastTransmittedFrameCount++;
+			if (status->retry_count > 0)
+				local->dot11RetryCount++;
+			if (status->retry_count > 1)
+				local->dot11MultipleRetryCount++;
+		}
+
+		/* This counter shall be incremented for an acknowledged MPDU
+		 * with an individual address in the address 1 field or an MPDU
+		 * with a multicast address in the address 1 field of type Data
+		 * or Management. */
+		if (!is_multicast_ether_addr(hdr->addr1) ||
+		    type == IEEE80211_FTYPE_DATA ||
+		    type == IEEE80211_FTYPE_MGMT)
+			local->dot11TransmittedFragmentCount++;
+	} else {
+		if (frag == 0)
+			local->dot11FailedCount++;
+	}
+
+	if (!(status->control.flags & IEEE80211_TXCTL_REQ_TX_STATUS)
+	    || unlikely(!local->apdev)) {
+		dev_kfree_skb(skb);
+		return;
+	}
+
+	msg_type = (status->flags & IEEE80211_TX_STATUS_ACK) ?
+		ieee80211_msg_tx_callback_ack : ieee80211_msg_tx_callback_fail;
+
+	/* skb was the original skb used for TX. Clone it and give the clone
+	 * to netif_rx(). Free original skb. */
+	skb2 = skb_copy(skb, GFP_ATOMIC);
+	if (!skb2) {
+		dev_kfree_skb(skb);
+		return;
+	}
+	dev_kfree_skb(skb);
+	skb = skb2;
+
+	/* Send frame to hostapd */
+	ieee80211_rx_mgmt(local, skb, NULL, msg_type);
+}
+EXPORT_SYMBOL(ieee80211_tx_status);
+
+/* TODO: implement register/unregister functions for adding TX/RX handlers
+ * into ordered list */
+
+/* rx_pre handlers don't have dev and sdata fields available in
+ * ieee80211_txrx_data */
+static ieee80211_rx_handler ieee80211_rx_pre_handlers[] =
+{
+	ieee80211_rx_h_parse_qos,
+	ieee80211_rx_h_load_stats,
+	NULL
+};
+
+static ieee80211_rx_handler ieee80211_rx_handlers[] =
+{
+	ieee80211_rx_h_if_stats,
+	ieee80211_rx_h_monitor,
+	ieee80211_rx_h_passive_scan,
+	ieee80211_rx_h_check,
+	ieee80211_rx_h_sta_process,
+	ieee80211_rx_h_ccmp_decrypt,
+	ieee80211_rx_h_tkip_decrypt,
+	ieee80211_rx_h_wep_weak_iv_detection,
+	ieee80211_rx_h_wep_decrypt,
+	ieee80211_rx_h_defragment,
+	ieee80211_rx_h_ps_poll,
+	ieee80211_rx_h_michael_mic_verify,
+	/* this must be after decryption - so header is counted in MPDU mic
+	 * must be before pae and data, so QOS_DATA format frames
+	 * are not passed to user space by these functions
+	 */
+	ieee80211_rx_h_remove_qos_control,
+	ieee80211_rx_h_802_1x_pae,
+	ieee80211_rx_h_drop_unencrypted,
+	ieee80211_rx_h_data,
+	ieee80211_rx_h_mgmt,
+	NULL
+};
+
+static ieee80211_tx_handler ieee80211_tx_handlers[] =
+{
+	ieee80211_tx_h_check_assoc,
+	ieee80211_tx_h_sequence,
+	ieee80211_tx_h_ps_buf,
+	ieee80211_tx_h_select_key,
+	ieee80211_tx_h_michael_mic_add,
+	ieee80211_tx_h_fragment,
+	ieee80211_tx_h_tkip_encrypt,
+	ieee80211_tx_h_ccmp_encrypt,
+	ieee80211_tx_h_wep_encrypt,
+	ieee80211_tx_h_rate_ctrl,
+	ieee80211_tx_h_misc,
+	ieee80211_tx_h_load_stats,
+	NULL
+};
+
+
+int ieee80211_if_update_wds(struct net_device *dev, u8 *remote_addr)
+{
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	struct sta_info *sta;
+
+	if (compare_ether_addr(remote_addr, sdata->u.wds.remote_addr) == 0)
+		return 0;
+
+	/* Create STA entry for the new peer */
+	sta = sta_info_add(local, dev, remote_addr, GFP_KERNEL);
+	if (!sta)
+		return -ENOMEM;
+	sta_info_put(sta);
+
+	/* Remove STA entry for the old peer */
+	sta = sta_info_get(local, sdata->u.wds.remote_addr);
+	if (sta) {
+		sta_info_put(sta);
+		sta_info_free(sta, 0);
+	} else {
+		printk(KERN_DEBUG "%s: could not find STA entry for WDS link "
+		       "peer " MAC_FMT "\n",
+		       dev->name, MAC_ARG(sdata->u.wds.remote_addr));
+	}
+
+	/* Update WDS link data */
+	memcpy(&sdata->u.wds.remote_addr, remote_addr, ETH_ALEN);
+
+	return 0;
+}
+
+/* Must not be called for mdev and apdev */
+void ieee80211_if_setup(struct net_device *dev)
+{
+	ether_setup(dev);
+	dev->hard_start_xmit = ieee80211_subif_start_xmit;
+	dev->wireless_handlers = &ieee80211_iw_handler_def;
+	dev->set_multicast_list = ieee80211_set_multicast_list;
+	dev->change_mtu = ieee80211_change_mtu;
+	dev->get_stats = ieee80211_get_stats;
+	dev->open = ieee80211_open;
+	dev->stop = ieee80211_stop;
+	dev->uninit = ieee80211_if_reinit;
+	dev->destructor = ieee80211_if_free;
+}
+
+void ieee80211_if_mgmt_setup(struct net_device *dev)
+{
+	ether_setup(dev);
+	dev->hard_start_xmit = ieee80211_mgmt_start_xmit;
+	dev->change_mtu = ieee80211_change_mtu_apdev;
+	dev->get_stats = ieee80211_get_stats;
+	dev->open = ieee80211_mgmt_open;
+	dev->stop = ieee80211_mgmt_stop;
+	dev->type = ARPHRD_IEEE80211_PRISM;
+	dev->hard_header_parse = header_parse_80211;
+	dev->uninit = ieee80211_if_reinit;
+	dev->destructor = ieee80211_if_free;
+}
+
+int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local,
+				 const char *name)
+{
+	struct rate_control_ref *ref, *old;
+
+	ASSERT_RTNL();
+	if (local->open_count || netif_running(local->mdev) ||
+	    (local->apdev && netif_running(local->apdev)))
+		return -EBUSY;
+
+	ref = rate_control_alloc(name, local);
+	if (!ref) {
+		printk(KERN_WARNING "%s: Failed to select rate control "
+		       "algorithm\n", local->mdev->name);
+		return -ENOENT;
+	}
+
+	old = local->rate_ctrl;
+	local->rate_ctrl = ref;
+	if (old) {
+		rate_control_put(old);
+		sta_info_flush(local, NULL);
+	}
+
+	printk(KERN_DEBUG "%s: Selected rate control "
+	       "algorithm '%s'\n", local->mdev->name,
+	       ref->ops->name);
+
+
+	return 0;
+}
+
+static void rate_control_deinitialize(struct ieee80211_local *local)
+{
+	struct rate_control_ref *ref;
+
+	ref = local->rate_ctrl;
+	local->rate_ctrl = NULL;
+	rate_control_put(ref);
+}
+
+struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
+					const struct ieee80211_ops *ops)
+{
+	struct net_device *mdev;
+	struct ieee80211_local *local;
+	struct ieee80211_sub_if_data *sdata;
+	int priv_size;
+	struct wiphy *wiphy;
+
+	/* Ensure 32-byte alignment of our private data and hw private data.
+	 * We use the wiphy priv data for both our ieee80211_local and for
+	 * the driver's private data
+	 *
+	 * In memory it'll be like this:
+	 *
+	 * +-------------------------+
+	 * | struct wiphy	    |
+	 * +-------------------------+
+	 * | struct ieee80211_local  |
+	 * +-------------------------+
+	 * | driver's private data   |
+	 * +-------------------------+
+	 *
+	 */
+	priv_size = ((sizeof(struct ieee80211_local) +
+		      NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST) +
+		    priv_data_len;
+
+	wiphy = wiphy_new(&mac80211_config_ops, priv_size);
+
+	if (!wiphy)
+		return NULL;
+
+	wiphy->privid = mac80211_wiphy_privid;
+
+	local = wiphy_priv(wiphy);
+	local->hw.wiphy = wiphy;
+
+	local->hw.priv = (char *)local +
+			 ((sizeof(struct ieee80211_local) +
+			   NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST);
+
+	local->ops = ops;
+
+	/* for now, mdev needs sub_if_data :/ */
+	mdev = alloc_netdev(sizeof(struct ieee80211_sub_if_data),
+			    "wmaster%d", ether_setup);
+	if (!mdev) {
+		wiphy_free(wiphy);
+		return NULL;
+	}
+
+	sdata = IEEE80211_DEV_TO_SUB_IF(mdev);
+	mdev->ieee80211_ptr = &sdata->wdev;
+	sdata->wdev.wiphy = wiphy;
+
+	local->hw.queues = 1; /* default */
+
+	local->mdev = mdev;
+	local->rx_pre_handlers = ieee80211_rx_pre_handlers;
+	local->rx_handlers = ieee80211_rx_handlers;
+	local->tx_handlers = ieee80211_tx_handlers;
+
+	local->bridge_packets = 1;
+
+	local->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD;
+	local->fragmentation_threshold = IEEE80211_MAX_FRAG_THRESHOLD;
+	local->short_retry_limit = 7;
+	local->long_retry_limit = 4;
+	local->hw.conf.radio_enabled = 1;
+	local->rate_ctrl_num_up = RATE_CONTROL_NUM_UP;
+	local->rate_ctrl_num_down = RATE_CONTROL_NUM_DOWN;
+
+	local->enabled_modes = (unsigned int) -1;
+
+	INIT_LIST_HEAD(&local->modes_list);
+
+	rwlock_init(&local->sub_if_lock);
+	INIT_LIST_HEAD(&local->sub_if_list);
+
+	INIT_DELAYED_WORK(&local->scan_work, ieee80211_sta_scan_work);
+	init_timer(&local->stat_timer);
+	local->stat_timer.function = ieee80211_stat_refresh;
+	local->stat_timer.data = (unsigned long) local;
+	ieee80211_rx_bss_list_init(mdev);
+
+	sta_info_init(local);
+
+	mdev->hard_start_xmit = ieee80211_master_start_xmit;
+	mdev->open = ieee80211_master_open;
+	mdev->stop = ieee80211_master_stop;
+	mdev->type = ARPHRD_IEEE80211;
+	mdev->hard_header_parse = header_parse_80211;
+
+	sdata->type = IEEE80211_IF_TYPE_AP;
+	sdata->dev = mdev;
+	sdata->local = local;
+	sdata->u.ap.force_unicast_rateidx = -1;
+	sdata->u.ap.max_ratectrl_rateidx = -1;
+	ieee80211_if_sdata_init(sdata);
+	list_add_tail(&sdata->list, &local->sub_if_list);
+
+	tasklet_init(&local->tx_pending_tasklet, ieee80211_tx_pending,
+		     (unsigned long)local);
+	tasklet_disable(&local->tx_pending_tasklet);
+
+	tasklet_init(&local->tasklet,
+		     ieee80211_tasklet_handler,
+		     (unsigned long) local);
+	tasklet_disable(&local->tasklet);
+
+	skb_queue_head_init(&local->skb_queue);
+	skb_queue_head_init(&local->skb_queue_unreliable);
+
+	return local_to_hw(local);
+}
+EXPORT_SYMBOL(ieee80211_alloc_hw);
+
+int ieee80211_register_hw(struct ieee80211_hw *hw)
+{
+	struct ieee80211_local *local = hw_to_local(hw);
+	const char *name;
+	int result;
+
+	result = wiphy_register(local->hw.wiphy);
+	if (result < 0)
+		return result;
+
+	name = wiphy_dev(local->hw.wiphy)->driver->name;
+	local->hw.workqueue = create_singlethread_workqueue(name);
+	if (!local->hw.workqueue) {
+		result = -ENOMEM;
+		goto fail_workqueue;
+	}
+
+	debugfs_hw_add(local);
+
+	local->hw.conf.beacon_int = 1000;
+
+	local->wstats_flags |= local->hw.max_rssi ?
+			       IW_QUAL_LEVEL_UPDATED : IW_QUAL_LEVEL_INVALID;
+	local->wstats_flags |= local->hw.max_signal ?
+			       IW_QUAL_QUAL_UPDATED : IW_QUAL_QUAL_INVALID;
+	local->wstats_flags |= local->hw.max_noise ?
+			       IW_QUAL_NOISE_UPDATED : IW_QUAL_NOISE_INVALID;
+	if (local->hw.max_rssi < 0 || local->hw.max_noise < 0)
+		local->wstats_flags |= IW_QUAL_DBM;
+
+	result = sta_info_start(local);
+	if (result < 0)
+		goto fail_sta_info;
+
+	rtnl_lock();
+	result = dev_alloc_name(local->mdev, local->mdev->name);
+	if (result < 0)
+		goto fail_dev;
+
+	memcpy(local->mdev->dev_addr, local->hw.wiphy->perm_addr, ETH_ALEN);
+	SET_NETDEV_DEV(local->mdev, wiphy_dev(local->hw.wiphy));
+
+	result = register_netdevice(local->mdev);
+	if (result < 0)
+		goto fail_dev;
+
+	ieee80211_debugfs_add_netdev(IEEE80211_DEV_TO_SUB_IF(local->mdev));
+
+	result = ieee80211_init_rate_ctrl_alg(local, NULL);
+	if (result < 0) {
+		printk(KERN_DEBUG "%s: Failed to initialize rate control "
+		       "algorithm\n", local->mdev->name);
+		goto fail_rate;
+	}
+
+	result = ieee80211_wep_init(local);
+
+	if (result < 0) {
+		printk(KERN_DEBUG "%s: Failed to initialize wep\n",
+		       local->mdev->name);
+		goto fail_wep;
+	}
+
+	ieee80211_install_qdisc(local->mdev);
+
+	/* add one default STA interface */
+	result = ieee80211_if_add(local->mdev, "wlan%d", NULL,
+				  IEEE80211_IF_TYPE_STA);
+	if (result)
+		printk(KERN_WARNING "%s: Failed to add default virtual iface\n",
+		       local->mdev->name);
+
+	local->reg_state = IEEE80211_DEV_REGISTERED;
+	rtnl_unlock();
+
+	ieee80211_led_init(local);
+
+	return 0;
+
+fail_wep:
+	rate_control_deinitialize(local);
+fail_rate:
+	ieee80211_debugfs_remove_netdev(IEEE80211_DEV_TO_SUB_IF(local->mdev));
+	unregister_netdevice(local->mdev);
+fail_dev:
+	rtnl_unlock();
+	sta_info_stop(local);
+fail_sta_info:
+	debugfs_hw_del(local);
+	destroy_workqueue(local->hw.workqueue);
+fail_workqueue:
+	wiphy_unregister(local->hw.wiphy);
+	return result;
+}
+EXPORT_SYMBOL(ieee80211_register_hw);
+
+int ieee80211_register_hwmode(struct ieee80211_hw *hw,
+			      struct ieee80211_hw_mode *mode)
+{
+	struct ieee80211_local *local = hw_to_local(hw);
+	struct ieee80211_rate *rate;
+	int i;
+
+	INIT_LIST_HEAD(&mode->list);
+	list_add_tail(&mode->list, &local->modes_list);
+
+	local->hw_modes |= (1 << mode->mode);
+	for (i = 0; i < mode->num_rates; i++) {
+		rate = &(mode->rates[i]);
+		rate->rate_inv = CHAN_UTIL_RATE_LCM / rate->rate;
+	}
+	ieee80211_prepare_rates(local, mode);
+
+	if (!local->oper_hw_mode) {
+		/* Default to this mode */
+		local->hw.conf.phymode = mode->mode;
+		local->oper_hw_mode = local->scan_hw_mode = mode;
+		local->oper_channel = local->scan_channel = &mode->channels[0];
+		local->hw.conf.mode = local->oper_hw_mode;
+		local->hw.conf.chan = local->oper_channel;
+	}
+
+	if (!(hw->flags & IEEE80211_HW_DEFAULT_REG_DOMAIN_CONFIGURED))
+		ieee80211_init_client(local->mdev);
+
+	return 0;
+}
+EXPORT_SYMBOL(ieee80211_register_hwmode);
+
+void ieee80211_unregister_hw(struct ieee80211_hw *hw)
+{
+	struct ieee80211_local *local = hw_to_local(hw);
+	struct ieee80211_sub_if_data *sdata, *tmp;
+	struct list_head tmp_list;
+	int i;
+
+	tasklet_kill(&local->tx_pending_tasklet);
+	tasklet_kill(&local->tasklet);
+
+	rtnl_lock();
+
+	BUG_ON(local->reg_state != IEEE80211_DEV_REGISTERED);
+
+	local->reg_state = IEEE80211_DEV_UNREGISTERED;
+	if (local->apdev)
+		ieee80211_if_del_mgmt(local);
+
+	write_lock_bh(&local->sub_if_lock);
+	list_replace_init(&local->sub_if_list, &tmp_list);
+	write_unlock_bh(&local->sub_if_lock);
+
+	list_for_each_entry_safe(sdata, tmp, &tmp_list, list)
+		__ieee80211_if_del(local, sdata);
+
+	rtnl_unlock();
+
+	if (local->stat_time)
+		del_timer_sync(&local->stat_timer);
+
+	ieee80211_rx_bss_list_deinit(local->mdev);
+	ieee80211_clear_tx_pending(local);
+	sta_info_stop(local);
+	rate_control_deinitialize(local);
+	debugfs_hw_del(local);
+
+	for (i = 0; i < NUM_IEEE80211_MODES; i++) {
+		kfree(local->supp_rates[i]);
+		kfree(local->basic_rates[i]);
+	}
+
+	if (skb_queue_len(&local->skb_queue)
+			|| skb_queue_len(&local->skb_queue_unreliable))
+		printk(KERN_WARNING "%s: skb_queue not empty\n",
+		       local->mdev->name);
+	skb_queue_purge(&local->skb_queue);
+	skb_queue_purge(&local->skb_queue_unreliable);
+
+	destroy_workqueue(local->hw.workqueue);
+	wiphy_unregister(local->hw.wiphy);
+	ieee80211_wep_free(local);
+	ieee80211_led_exit(local);
+}
+EXPORT_SYMBOL(ieee80211_unregister_hw);
+
+void ieee80211_free_hw(struct ieee80211_hw *hw)
+{
+	struct ieee80211_local *local = hw_to_local(hw);
+
+	ieee80211_if_free(local->mdev);
+	wiphy_free(local->hw.wiphy);
+}
+EXPORT_SYMBOL(ieee80211_free_hw);
+
+void ieee80211_wake_queue(struct ieee80211_hw *hw, int queue)
+{
+	struct ieee80211_local *local = hw_to_local(hw);
+
+	if (test_and_clear_bit(IEEE80211_LINK_STATE_XOFF,
+			       &local->state[queue])) {
+		if (test_bit(IEEE80211_LINK_STATE_PENDING,
+			     &local->state[queue]))
+			tasklet_schedule(&local->tx_pending_tasklet);
+		else
+			if (!ieee80211_qdisc_installed(local->mdev)) {
+				if (queue == 0)
+					netif_wake_queue(local->mdev);
+			} else
+				__netif_schedule(local->mdev);
+	}
+}
+EXPORT_SYMBOL(ieee80211_wake_queue);
+
+void ieee80211_stop_queue(struct ieee80211_hw *hw, int queue)
+{
+	struct ieee80211_local *local = hw_to_local(hw);
+
+	if (!ieee80211_qdisc_installed(local->mdev) && queue == 0)
+		netif_stop_queue(local->mdev);
+	set_bit(IEEE80211_LINK_STATE_XOFF, &local->state[queue]);
+}
+EXPORT_SYMBOL(ieee80211_stop_queue);
+
+void ieee80211_start_queues(struct ieee80211_hw *hw)
+{
+	struct ieee80211_local *local = hw_to_local(hw);
+	int i;
+
+	for (i = 0; i < local->hw.queues; i++)
+		clear_bit(IEEE80211_LINK_STATE_XOFF, &local->state[i]);
+	if (!ieee80211_qdisc_installed(local->mdev))
+		netif_start_queue(local->mdev);
+}
+EXPORT_SYMBOL(ieee80211_start_queues);
+
+void ieee80211_stop_queues(struct ieee80211_hw *hw)
+{
+	int i;
+
+	for (i = 0; i < hw->queues; i++)
+		ieee80211_stop_queue(hw, i);
+}
+EXPORT_SYMBOL(ieee80211_stop_queues);
+
+void ieee80211_wake_queues(struct ieee80211_hw *hw)
+{
+	int i;
+
+	for (i = 0; i < hw->queues; i++)
+		ieee80211_wake_queue(hw, i);
+}
+EXPORT_SYMBOL(ieee80211_wake_queues);
+
+struct net_device_stats *ieee80211_dev_stats(struct net_device *dev)
+{
+	struct ieee80211_sub_if_data *sdata;
+	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	return &sdata->stats;
+}
+
+static int __init ieee80211_init(void)
+{
+	struct sk_buff *skb;
+	int ret;
+
+	BUILD_BUG_ON(sizeof(struct ieee80211_tx_packet_data) > sizeof(skb->cb));
+
+	ret = ieee80211_wme_register();
+	if (ret) {
+		printk(KERN_DEBUG "ieee80211_init: failed to "
+		       "initialize WME (err=%d)\n", ret);
+		return ret;
+	}
+
+	ieee80211_debugfs_netdev_init();
+
+	return 0;
+}
+
+
+static void __exit ieee80211_exit(void)
+{
+	ieee80211_wme_unregister();
+	ieee80211_debugfs_netdev_exit();
+}
+
+
+module_init(ieee80211_init);
+module_exit(ieee80211_exit);
+
+MODULE_DESCRIPTION("IEEE 802.11 subsystem");
+MODULE_LICENSE("GPL");
diff --git a/net/mac80211/ieee80211_cfg.c b/net/mac80211/ieee80211_cfg.c
new file mode 100644
index 0000000..509096e
--- /dev/null
+++ b/net/mac80211/ieee80211_cfg.c
@@ -0,0 +1,66 @@
+/*
+ * mac80211 configuration hooks for cfg80211
+ *
+ * Copyright 2006	Johannes Berg <johannes@sipsolutions.net>
+ *
+ * This file is GPLv2 as found in COPYING.
+ */
+
+#include <linux/nl80211.h>
+#include <linux/rtnetlink.h>
+#include <net/cfg80211.h>
+#include "ieee80211_i.h"
+#include "ieee80211_cfg.h"
+
+static int ieee80211_add_iface(struct wiphy *wiphy, char *name,
+			       unsigned int type)
+{
+	struct ieee80211_local *local = wiphy_priv(wiphy);
+	int itype;
+
+	if (unlikely(local->reg_state != IEEE80211_DEV_REGISTERED))
+		return -ENODEV;
+
+	switch (type) {
+	case NL80211_IFTYPE_UNSPECIFIED:
+		itype = IEEE80211_IF_TYPE_STA;
+		break;
+	case NL80211_IFTYPE_ADHOC:
+		itype = IEEE80211_IF_TYPE_IBSS;
+		break;
+	case NL80211_IFTYPE_STATION:
+		itype = IEEE80211_IF_TYPE_STA;
+		break;
+	case NL80211_IFTYPE_MONITOR:
+		itype = IEEE80211_IF_TYPE_MNTR;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return ieee80211_if_add(local->mdev, name, NULL, itype);
+}
+
+static int ieee80211_del_iface(struct wiphy *wiphy, int ifindex)
+{
+	struct ieee80211_local *local = wiphy_priv(wiphy);
+	struct net_device *dev;
+	char *name;
+
+	if (unlikely(local->reg_state != IEEE80211_DEV_REGISTERED))
+		return -ENODEV;
+
+	dev = dev_get_by_index(ifindex);
+	if (!dev)
+		return 0;
+
+	name = dev->name;
+	dev_put(dev);
+
+	return ieee80211_if_remove(local->mdev, name, -1);
+}
+
+struct cfg80211_ops mac80211_config_ops = {
+	.add_virtual_intf = ieee80211_add_iface,
+	.del_virtual_intf = ieee80211_del_iface,
+};
diff --git a/net/mac80211/ieee80211_cfg.h b/net/mac80211/ieee80211_cfg.h
new file mode 100644
index 0000000..85ed2c9
--- /dev/null
+++ b/net/mac80211/ieee80211_cfg.h
@@ -0,0 +1,9 @@
+/*
+ * mac80211 configuration hooks for cfg80211
+ */
+#ifndef __IEEE80211_CFG_H
+#define __IEEE80211_CFG_H
+
+extern struct cfg80211_ops mac80211_config_ops;
+
+#endif /* __IEEE80211_CFG_H */
diff --git a/net/mac80211/ieee80211_common.h b/net/mac80211/ieee80211_common.h
new file mode 100644
index 0000000..b9a73e7
--- /dev/null
+++ b/net/mac80211/ieee80211_common.h
@@ -0,0 +1,98 @@
+/*
+ * IEEE 802.11 driver (80211.o) -- hostapd interface
+ * Copyright 2002-2004, Instant802 Networks, Inc.
+ *
+ * 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 IEEE80211_COMMON_H
+#define IEEE80211_COMMON_H
+
+#include <linux/types.h>
+
+/*
+ * This is common header information with user space. It is used on all
+ * frames sent to wlan#ap interface.
+ */
+
+#define IEEE80211_FI_VERSION 0x80211001
+
+struct ieee80211_frame_info {
+	__be32 version;
+	__be32 length;
+	__be64 mactime;
+	__be64 hosttime;
+	__be32 phytype;
+	__be32 channel;
+	__be32 datarate;
+	__be32 antenna;
+	__be32 priority;
+	__be32 ssi_type;
+	__be32 ssi_signal;
+	__be32 ssi_noise;
+	__be32 preamble;
+	__be32 encoding;
+
+	/* Note: this structure is otherwise identical to capture format used
+	 * in linux-wlan-ng, but this additional field is used to provide meta
+	 * data about the frame to hostapd. This was the easiest method for
+	 * providing this information, but this might change in the future. */
+	__be32 msg_type;
+} __attribute__ ((packed));
+
+
+enum ieee80211_msg_type {
+	ieee80211_msg_normal = 0,
+	ieee80211_msg_tx_callback_ack = 1,
+	ieee80211_msg_tx_callback_fail = 2,
+	ieee80211_msg_passive_scan = 3,
+	ieee80211_msg_wep_frame_unknown_key = 4,
+	ieee80211_msg_michael_mic_failure = 5,
+	/* hole at 6, was monitor but never sent to userspace */
+	ieee80211_msg_sta_not_assoc = 7,
+	ieee80211_msg_set_aid_for_sta = 8 /* used by Intersil MVC driver */,
+	ieee80211_msg_key_threshold_notification = 9,
+	ieee80211_msg_radar = 11,
+};
+
+struct ieee80211_msg_set_aid_for_sta {
+	char	sta_address[ETH_ALEN];
+	u16	aid;
+};
+
+struct ieee80211_msg_key_notification {
+	int tx_rx_count;
+	char ifname[IFNAMSIZ];
+	u8 addr[ETH_ALEN]; /* ff:ff:ff:ff:ff:ff for broadcast keys */
+};
+
+
+enum ieee80211_phytype {
+	ieee80211_phytype_fhss_dot11_97  = 1,
+	ieee80211_phytype_dsss_dot11_97  = 2,
+	ieee80211_phytype_irbaseband     = 3,
+	ieee80211_phytype_dsss_dot11_b   = 4,
+	ieee80211_phytype_pbcc_dot11_b   = 5,
+	ieee80211_phytype_ofdm_dot11_g   = 6,
+	ieee80211_phytype_pbcc_dot11_g   = 7,
+	ieee80211_phytype_ofdm_dot11_a   = 8,
+	ieee80211_phytype_dsss_dot11_turbog = 255,
+	ieee80211_phytype_dsss_dot11_turbo = 256,
+};
+
+enum ieee80211_ssi_type {
+	ieee80211_ssi_none = 0,
+	ieee80211_ssi_norm = 1, /* normalized, 0-1000 */
+	ieee80211_ssi_dbm = 2,
+	ieee80211_ssi_raw = 3, /* raw SSI */
+};
+
+struct ieee80211_radar_info {
+		int channel;
+		int radar;
+		int radar_type;
+};
+
+#endif /* IEEE80211_COMMON_H */
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
new file mode 100644
index 0000000..af4d14d
--- /dev/null
+++ b/net/mac80211/ieee80211_i.h
@@ -0,0 +1,798 @@
+/*
+ * Copyright 2002-2005, Instant802 Networks, Inc.
+ * Copyright 2005, Devicescape Software, Inc.
+ * Copyright 2006-2007	Jiri Benc <jbenc@suse.cz>
+ *
+ * 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 IEEE80211_I_H
+#define IEEE80211_I_H
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/if_ether.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/workqueue.h>
+#include <linux/types.h>
+#include <linux/spinlock.h>
+#include <net/wireless.h>
+#include "ieee80211_key.h"
+#include "sta_info.h"
+
+/* ieee80211.o internal definitions, etc. These are not included into
+ * low-level drivers. */
+
+#ifndef ETH_P_PAE
+#define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */
+#endif /* ETH_P_PAE */
+
+#define WLAN_FC_DATA_PRESENT(fc) (((fc) & 0x4c) == 0x08)
+
+struct ieee80211_local;
+
+#define BIT(x) (1 << (x))
+
+#define IEEE80211_ALIGN32_PAD(a) ((4 - ((a) & 3)) & 3)
+
+/* Maximum number of broadcast/multicast frames to buffer when some of the
+ * associated stations are using power saving. */
+#define AP_MAX_BC_BUFFER 128
+
+/* Maximum number of frames buffered to all STAs, including multicast frames.
+ * Note: increasing this limit increases the potential memory requirement. Each
+ * frame can be up to about 2 kB long. */
+#define TOTAL_MAX_TX_BUFFER 512
+
+/* Required encryption head and tailroom */
+#define IEEE80211_ENCRYPT_HEADROOM 8
+#define IEEE80211_ENCRYPT_TAILROOM 12
+
+/* IEEE 802.11 (Ch. 9.5 Defragmentation) requires support for concurrent
+ * reception of at least three fragmented frames. This limit can be increased
+ * by changing this define, at the cost of slower frame reassembly and
+ * increased memory use (about 2 kB of RAM per entry). */
+#define IEEE80211_FRAGMENT_MAX 4
+
+struct ieee80211_fragment_entry {
+	unsigned long first_frag_time;
+	unsigned int seq;
+	unsigned int rx_queue;
+	unsigned int last_frag;
+	unsigned int extra_len;
+	struct sk_buff_head skb_list;
+	int ccmp; /* Whether fragments were encrypted with CCMP */
+	u8 last_pn[6]; /* PN of the last fragment if CCMP was used */
+};
+
+
+struct ieee80211_sta_bss {
+	struct list_head list;
+	struct ieee80211_sta_bss *hnext;
+	atomic_t users;
+
+	u8 bssid[ETH_ALEN];
+	u8 ssid[IEEE80211_MAX_SSID_LEN];
+	size_t ssid_len;
+	u16 capability; /* host byte order */
+	int hw_mode;
+	int channel;
+	int freq;
+	int rssi, signal, noise;
+	u8 *wpa_ie;
+	size_t wpa_ie_len;
+	u8 *rsn_ie;
+	size_t rsn_ie_len;
+	u8 *wmm_ie;
+	size_t wmm_ie_len;
+#define IEEE80211_MAX_SUPP_RATES 32
+	u8 supp_rates[IEEE80211_MAX_SUPP_RATES];
+	size_t supp_rates_len;
+	int beacon_int;
+	u64 timestamp;
+
+	int probe_resp;
+	unsigned long last_update;
+
+};
+
+
+typedef enum {
+	TXRX_CONTINUE, TXRX_DROP, TXRX_QUEUED
+} ieee80211_txrx_result;
+
+struct ieee80211_txrx_data {
+	struct sk_buff *skb;
+	struct net_device *dev;
+	struct ieee80211_local *local;
+	struct ieee80211_sub_if_data *sdata;
+	struct sta_info *sta;
+	u16 fc, ethertype;
+	struct ieee80211_key *key;
+	unsigned int fragmented:1; /* whether the MSDU was fragmented */
+	union {
+		struct {
+			struct ieee80211_tx_control *control;
+			unsigned int unicast:1;
+			unsigned int ps_buffered:1;
+			unsigned int short_preamble:1;
+			unsigned int probe_last_frag:1;
+			struct ieee80211_hw_mode *mode;
+			struct ieee80211_rate *rate;
+			/* use this rate (if set) for last fragment; rate can
+			 * be set to lower rate for the first fragments, e.g.,
+			 * when using CTS protection with IEEE 802.11g. */
+			struct ieee80211_rate *last_frag_rate;
+			int last_frag_hwrate;
+			int mgmt_interface;
+
+			/* Extra fragments (in addition to the first fragment
+			 * in skb) */
+			int num_extra_frag;
+			struct sk_buff **extra_frag;
+		} tx;
+		struct {
+			struct ieee80211_rx_status *status;
+			int sent_ps_buffered;
+			int queue;
+			int load;
+			unsigned int in_scan:1;
+			/* frame is destined to interface currently processed
+			 * (including multicast frames) */
+			unsigned int ra_match:1;
+		} rx;
+	} u;
+};
+
+/* Stored in sk_buff->cb */
+struct ieee80211_tx_packet_data {
+	int ifindex;
+	unsigned long jiffies;
+	unsigned int req_tx_status:1;
+	unsigned int do_not_encrypt:1;
+	unsigned int requeue:1;
+	unsigned int mgmt_iface:1;
+	unsigned int queue:4;
+};
+
+struct ieee80211_tx_stored_packet {
+	struct ieee80211_tx_control control;
+	struct sk_buff *skb;
+	int num_extra_frag;
+	struct sk_buff **extra_frag;
+	int last_frag_rateidx;
+	int last_frag_hwrate;
+	struct ieee80211_rate *last_frag_rate;
+	unsigned int last_frag_rate_ctrl_probe:1;
+};
+
+typedef ieee80211_txrx_result (*ieee80211_tx_handler)
+(struct ieee80211_txrx_data *tx);
+
+typedef ieee80211_txrx_result (*ieee80211_rx_handler)
+(struct ieee80211_txrx_data *rx);
+
+struct ieee80211_if_ap {
+	u8 *beacon_head, *beacon_tail;
+	int beacon_head_len, beacon_tail_len;
+
+	u8 ssid[IEEE80211_MAX_SSID_LEN];
+	size_t ssid_len;
+	u8 *generic_elem;
+	size_t generic_elem_len;
+
+	/* yes, this looks ugly, but guarantees that we can later use
+	 * bitmap_empty :)
+	 * NB: don't ever use set_bit, use bss_tim_set/bss_tim_clear! */
+	u8 tim[sizeof(unsigned long) * BITS_TO_LONGS(IEEE80211_MAX_AID + 1)];
+	atomic_t num_sta_ps; /* number of stations in PS mode */
+	struct sk_buff_head ps_bc_buf;
+	int dtim_period, dtim_count;
+	int force_unicast_rateidx; /* forced TX rateidx for unicast frames */
+	int max_ratectrl_rateidx; /* max TX rateidx for rate control */
+	int num_beacons; /* number of TXed beacon frames for this BSS */
+};
+
+struct ieee80211_if_wds {
+	u8 remote_addr[ETH_ALEN];
+	struct sta_info *sta;
+};
+
+struct ieee80211_if_vlan {
+	u8 id;
+};
+
+struct ieee80211_if_sta {
+	enum {
+		IEEE80211_DISABLED, IEEE80211_AUTHENTICATE,
+		IEEE80211_ASSOCIATE, IEEE80211_ASSOCIATED,
+		IEEE80211_IBSS_SEARCH, IEEE80211_IBSS_JOINED
+	} state;
+	struct timer_list timer;
+	struct work_struct work;
+	u8 bssid[ETH_ALEN], prev_bssid[ETH_ALEN];
+	u8 ssid[IEEE80211_MAX_SSID_LEN];
+	size_t ssid_len;
+	u16 aid;
+	u16 ap_capab, capab;
+	u8 *extra_ie; /* to be added to the end of AssocReq */
+	size_t extra_ie_len;
+
+	/* The last AssocReq/Resp IEs */
+	u8 *assocreq_ies, *assocresp_ies;
+	size_t assocreq_ies_len, assocresp_ies_len;
+
+	int auth_tries, assoc_tries;
+
+	unsigned int ssid_set:1;
+	unsigned int bssid_set:1;
+	unsigned int prev_bssid_set:1;
+	unsigned int authenticated:1;
+	unsigned int associated:1;
+	unsigned int probereq_poll:1;
+	unsigned int use_protection:1;
+	unsigned int create_ibss:1;
+	unsigned int mixed_cell:1;
+	unsigned int wmm_enabled:1;
+	unsigned int auto_ssid_sel:1;
+	unsigned int auto_bssid_sel:1;
+	unsigned int auto_channel_sel:1;
+#define IEEE80211_STA_REQ_SCAN 0
+#define IEEE80211_STA_REQ_AUTH 1
+#define IEEE80211_STA_REQ_RUN  2
+	unsigned long request;
+	struct sk_buff_head skb_queue;
+
+	int key_mgmt;
+	unsigned long last_probe;
+
+#define IEEE80211_AUTH_ALG_OPEN BIT(0)
+#define IEEE80211_AUTH_ALG_SHARED_KEY BIT(1)
+#define IEEE80211_AUTH_ALG_LEAP BIT(2)
+	unsigned int auth_algs; /* bitfield of allowed auth algs */
+	int auth_alg; /* currently used IEEE 802.11 authentication algorithm */
+	int auth_transaction;
+
+	unsigned long ibss_join_req;
+	struct sk_buff *probe_resp; /* ProbeResp template for IBSS */
+	u32 supp_rates_bits;
+
+	int wmm_last_param_set;
+};
+
+
+struct ieee80211_sub_if_data {
+	struct list_head list;
+	unsigned int type;
+
+	struct wireless_dev wdev;
+
+	struct net_device *dev;
+	struct ieee80211_local *local;
+
+	int mc_count;
+	unsigned int allmulti:1;
+	unsigned int promisc:1;
+
+	struct net_device_stats stats;
+	int drop_unencrypted;
+	int eapol; /* 0 = process EAPOL frames as normal data frames,
+		    * 1 = send EAPOL frames through wlan#ap to hostapd
+		    *     (default) */
+	int ieee802_1x; /* IEEE 802.1X PAE - drop packet to/from unauthorized
+			 * port */
+
+	u16 sequence;
+
+	/* Fragment table for host-based reassembly */
+	struct ieee80211_fragment_entry	fragments[IEEE80211_FRAGMENT_MAX];
+	unsigned int fragment_next;
+
+#define NUM_DEFAULT_KEYS 4
+	struct ieee80211_key *keys[NUM_DEFAULT_KEYS];
+	struct ieee80211_key *default_key;
+
+	struct ieee80211_if_ap *bss; /* BSS that this device belongs to */
+
+	union {
+		struct ieee80211_if_ap ap;
+		struct ieee80211_if_wds wds;
+		struct ieee80211_if_vlan vlan;
+		struct ieee80211_if_sta sta;
+	} u;
+	int channel_use;
+	int channel_use_raw;
+
+#ifdef CONFIG_MAC80211_DEBUGFS
+	struct dentry *debugfsdir;
+	union {
+		struct {
+			struct dentry *channel_use;
+			struct dentry *drop_unencrypted;
+			struct dentry *eapol;
+			struct dentry *ieee8021_x;
+			struct dentry *state;
+			struct dentry *bssid;
+			struct dentry *prev_bssid;
+			struct dentry *ssid_len;
+			struct dentry *aid;
+			struct dentry *ap_capab;
+			struct dentry *capab;
+			struct dentry *extra_ie_len;
+			struct dentry *auth_tries;
+			struct dentry *assoc_tries;
+			struct dentry *auth_algs;
+			struct dentry *auth_alg;
+			struct dentry *auth_transaction;
+			struct dentry *flags;
+		} sta;
+		struct {
+			struct dentry *channel_use;
+			struct dentry *drop_unencrypted;
+			struct dentry *eapol;
+			struct dentry *ieee8021_x;
+			struct dentry *num_sta_ps;
+			struct dentry *dtim_period;
+			struct dentry *dtim_count;
+			struct dentry *num_beacons;
+			struct dentry *force_unicast_rateidx;
+			struct dentry *max_ratectrl_rateidx;
+			struct dentry *num_buffered_multicast;
+			struct dentry *beacon_head_len;
+			struct dentry *beacon_tail_len;
+		} ap;
+		struct {
+			struct dentry *channel_use;
+			struct dentry *drop_unencrypted;
+			struct dentry *eapol;
+			struct dentry *ieee8021_x;
+			struct dentry *peer;
+		} wds;
+		struct {
+			struct dentry *channel_use;
+			struct dentry *drop_unencrypted;
+			struct dentry *eapol;
+			struct dentry *ieee8021_x;
+			struct dentry *vlan_id;
+		} vlan;
+		struct {
+			struct dentry *mode;
+		} monitor;
+		struct dentry *default_key;
+	} debugfs;
+#endif
+};
+
+#define IEEE80211_DEV_TO_SUB_IF(dev) netdev_priv(dev)
+
+enum {
+	IEEE80211_RX_MSG	= 1,
+	IEEE80211_TX_STATUS_MSG	= 2,
+};
+
+struct ieee80211_local {
+	/* embed the driver visible part.
+	 * don't cast (use the static inlines below), but we keep
+	 * it first anyway so they become a no-op */
+	struct ieee80211_hw hw;
+
+	const struct ieee80211_ops *ops;
+
+	/* List of registered struct ieee80211_hw_mode */
+	struct list_head modes_list;
+
+	struct net_device *mdev; /* wmaster# - "master" 802.11 device */
+	struct net_device *apdev; /* wlan#ap - management frames (hostapd) */
+	int open_count;
+	int monitors;
+	struct iw_statistics wstats;
+	u8 wstats_flags;
+
+	enum {
+		IEEE80211_DEV_UNINITIALIZED = 0,
+		IEEE80211_DEV_REGISTERED,
+		IEEE80211_DEV_UNREGISTERED,
+	} reg_state;
+
+	/* Tasklet and skb queue to process calls from IRQ mode. All frames
+	 * added to skb_queue will be processed, but frames in
+	 * skb_queue_unreliable may be dropped if the total length of these
+	 * queues increases over the limit. */
+#define IEEE80211_IRQSAFE_QUEUE_LIMIT 128
+	struct tasklet_struct tasklet;
+	struct sk_buff_head skb_queue;
+	struct sk_buff_head skb_queue_unreliable;
+
+	/* Station data structures */
+	spinlock_t sta_lock; /* mutex for STA data structures */
+	int num_sta; /* number of stations in sta_list */
+	struct list_head sta_list;
+	struct list_head deleted_sta_list;
+	struct sta_info *sta_hash[STA_HASH_SIZE];
+	struct timer_list sta_cleanup;
+
+	unsigned long state[NUM_TX_DATA_QUEUES];
+	struct ieee80211_tx_stored_packet pending_packet[NUM_TX_DATA_QUEUES];
+	struct tasklet_struct tx_pending_tasklet;
+
+	int mc_count;	/* total count of multicast entries in all interfaces */
+	int iff_allmultis, iff_promiscs;
+			/* number of interfaces with corresponding IFF_ flags */
+
+	struct rate_control_ref *rate_ctrl;
+
+	int next_mode; /* MODE_IEEE80211*
+			* The mode preference for next channel change. This is
+			* used to select .11g vs. .11b channels (or 4.9 GHz vs.
+			* .11a) when the channel number is not unique. */
+
+	/* Supported and basic rate filters for different modes. These are
+	 * pointers to -1 terminated lists and rates in 100 kbps units. */
+	int *supp_rates[NUM_IEEE80211_MODES];
+	int *basic_rates[NUM_IEEE80211_MODES];
+
+	int rts_threshold;
+	int cts_protect_erp_frames;
+	int fragmentation_threshold;
+	int short_retry_limit; /* dot11ShortRetryLimit */
+	int long_retry_limit; /* dot11LongRetryLimit */
+	int short_preamble; /* use short preamble with IEEE 802.11b */
+
+	struct crypto_blkcipher *wep_tx_tfm;
+	struct crypto_blkcipher *wep_rx_tfm;
+	u32 wep_iv;
+	int key_tx_rx_threshold; /* number of times any key can be used in TX
+				  * or RX before generating a rekey
+				  * notification; 0 = notification disabled. */
+
+	int bridge_packets; /* bridge packets between associated stations and
+			     * deliver multicast frames both back to wireless
+			     * media and to the local net stack */
+
+	ieee80211_rx_handler *rx_pre_handlers;
+	ieee80211_rx_handler *rx_handlers;
+	ieee80211_tx_handler *tx_handlers;
+
+	rwlock_t sub_if_lock; /* Protects sub_if_list. Cannot be taken under
+			       * sta_bss_lock or sta_lock. */
+	struct list_head sub_if_list;
+	int sta_scanning;
+	int scan_channel_idx;
+	enum { SCAN_SET_CHANNEL, SCAN_SEND_PROBE } scan_state;
+	unsigned long last_scan_completed;
+	struct delayed_work scan_work;
+	struct net_device *scan_dev;
+	struct ieee80211_channel *oper_channel, *scan_channel;
+	struct ieee80211_hw_mode *oper_hw_mode, *scan_hw_mode;
+	u8 scan_ssid[IEEE80211_MAX_SSID_LEN];
+	size_t scan_ssid_len;
+	struct list_head sta_bss_list;
+	struct ieee80211_sta_bss *sta_bss_hash[STA_HASH_SIZE];
+	spinlock_t sta_bss_lock;
+#define IEEE80211_SCAN_MATCH_SSID BIT(0)
+#define IEEE80211_SCAN_WPA_ONLY BIT(1)
+#define IEEE80211_SCAN_EXTRA_INFO BIT(2)
+	int scan_flags;
+
+	/* SNMP counters */
+	/* dot11CountersTable */
+	u32 dot11TransmittedFragmentCount;
+	u32 dot11MulticastTransmittedFrameCount;
+	u32 dot11FailedCount;
+	u32 dot11RetryCount;
+	u32 dot11MultipleRetryCount;
+	u32 dot11FrameDuplicateCount;
+	u32 dot11ReceivedFragmentCount;
+	u32 dot11MulticastReceivedFrameCount;
+	u32 dot11TransmittedFrameCount;
+	u32 dot11WEPUndecryptableCount;
+
+#ifdef CONFIG_MAC80211_LEDS
+	int tx_led_counter, rx_led_counter;
+	struct led_trigger *tx_led, *rx_led;
+	char tx_led_name[32], rx_led_name[32];
+#endif
+
+	u32 channel_use;
+	u32 channel_use_raw;
+	u32 stat_time;
+	struct timer_list stat_timer;
+
+#ifdef CONFIG_MAC80211_DEBUGFS
+	struct work_struct sta_debugfs_add;
+#endif
+
+	enum {
+		STA_ANTENNA_SEL_AUTO = 0,
+		STA_ANTENNA_SEL_SW_CTRL = 1,
+		STA_ANTENNA_SEL_SW_CTRL_DEBUG = 2
+	} sta_antenna_sel;
+
+	int rate_ctrl_num_up, rate_ctrl_num_down;
+
+#ifdef CONFIG_MAC80211_DEBUG_COUNTERS
+	/* TX/RX handler statistics */
+	unsigned int tx_handlers_drop;
+	unsigned int tx_handlers_queued;
+	unsigned int tx_handlers_drop_unencrypted;
+	unsigned int tx_handlers_drop_fragment;
+	unsigned int tx_handlers_drop_wep;
+	unsigned int tx_handlers_drop_not_assoc;
+	unsigned int tx_handlers_drop_unauth_port;
+	unsigned int rx_handlers_drop;
+	unsigned int rx_handlers_queued;
+	unsigned int rx_handlers_drop_nullfunc;
+	unsigned int rx_handlers_drop_defrag;
+	unsigned int rx_handlers_drop_short;
+	unsigned int rx_handlers_drop_passive_scan;
+	unsigned int tx_expand_skb_head;
+	unsigned int tx_expand_skb_head_cloned;
+	unsigned int rx_expand_skb_head;
+	unsigned int rx_expand_skb_head2;
+	unsigned int rx_handlers_fragments;
+	unsigned int tx_status_drop;
+	unsigned int wme_rx_queue[NUM_RX_DATA_QUEUES];
+	unsigned int wme_tx_queue[NUM_RX_DATA_QUEUES];
+#define I802_DEBUG_INC(c) (c)++
+#else /* CONFIG_MAC80211_DEBUG_COUNTERS */
+#define I802_DEBUG_INC(c) do { } while (0)
+#endif /* CONFIG_MAC80211_DEBUG_COUNTERS */
+
+
+	int default_wep_only; /* only default WEP keys are used with this
+			       * interface; this is used to decide when hwaccel
+			       * can be used with default keys */
+	int total_ps_buffered; /* total number of all buffered unicast and
+				* multicast packets for power saving stations
+				*/
+	int allow_broadcast_always; /* whether to allow TX of broadcast frames
+				     * even when there are no associated STAs
+				     */
+
+	int wifi_wme_noack_test;
+	unsigned int wmm_acm; /* bit field of ACM bits (BIT(802.1D tag)) */
+
+	unsigned int enabled_modes; /* bitfield of allowed modes;
+				      * (1 << MODE_*) */
+	unsigned int hw_modes; /* bitfield of supported hardware modes;
+				* (1 << MODE_*) */
+
+	int user_space_mlme;
+
+#ifdef CONFIG_MAC80211_DEBUGFS
+	struct local_debugfsdentries {
+		struct dentry *channel;
+		struct dentry *frequency;
+		struct dentry *radar_detect;
+		struct dentry *antenna_sel_tx;
+		struct dentry *antenna_sel_rx;
+		struct dentry *bridge_packets;
+		struct dentry *key_tx_rx_threshold;
+		struct dentry *rts_threshold;
+		struct dentry *fragmentation_threshold;
+		struct dentry *short_retry_limit;
+		struct dentry *long_retry_limit;
+		struct dentry *total_ps_buffered;
+		struct dentry *mode;
+		struct dentry *wep_iv;
+		struct dentry *tx_power_reduction;
+		struct dentry *modes;
+		struct dentry *statistics;
+		struct local_debugfsdentries_statsdentries {
+			struct dentry *transmitted_fragment_count;
+			struct dentry *multicast_transmitted_frame_count;
+			struct dentry *failed_count;
+			struct dentry *retry_count;
+			struct dentry *multiple_retry_count;
+			struct dentry *frame_duplicate_count;
+			struct dentry *received_fragment_count;
+			struct dentry *multicast_received_frame_count;
+			struct dentry *transmitted_frame_count;
+			struct dentry *wep_undecryptable_count;
+			struct dentry *num_scans;
+#ifdef CONFIG_MAC80211_DEBUG_COUNTERS
+			struct dentry *tx_handlers_drop;
+			struct dentry *tx_handlers_queued;
+			struct dentry *tx_handlers_drop_unencrypted;
+			struct dentry *tx_handlers_drop_fragment;
+			struct dentry *tx_handlers_drop_wep;
+			struct dentry *tx_handlers_drop_not_assoc;
+			struct dentry *tx_handlers_drop_unauth_port;
+			struct dentry *rx_handlers_drop;
+			struct dentry *rx_handlers_queued;
+			struct dentry *rx_handlers_drop_nullfunc;
+			struct dentry *rx_handlers_drop_defrag;
+			struct dentry *rx_handlers_drop_short;
+			struct dentry *rx_handlers_drop_passive_scan;
+			struct dentry *tx_expand_skb_head;
+			struct dentry *tx_expand_skb_head_cloned;
+			struct dentry *rx_expand_skb_head;
+			struct dentry *rx_expand_skb_head2;
+			struct dentry *rx_handlers_fragments;
+			struct dentry *tx_status_drop;
+			struct dentry *wme_tx_queue;
+			struct dentry *wme_rx_queue;
+#endif
+			struct dentry *dot11ACKFailureCount;
+			struct dentry *dot11RTSFailureCount;
+			struct dentry *dot11FCSErrorCount;
+			struct dentry *dot11RTSSuccessCount;
+		} stats;
+		struct dentry *stations;
+		struct dentry *keys;
+	} debugfs;
+#endif
+};
+
+static inline struct ieee80211_local *hw_to_local(
+	struct ieee80211_hw *hw)
+{
+	return container_of(hw, struct ieee80211_local, hw);
+}
+
+static inline struct ieee80211_hw *local_to_hw(
+	struct ieee80211_local *local)
+{
+	return &local->hw;
+}
+
+enum ieee80211_link_state_t {
+	IEEE80211_LINK_STATE_XOFF = 0,
+	IEEE80211_LINK_STATE_PENDING,
+};
+
+struct sta_attribute {
+	struct attribute attr;
+	ssize_t (*show)(const struct sta_info *, char *buf);
+	ssize_t (*store)(struct sta_info *, const char *buf, size_t count);
+};
+
+static inline void __bss_tim_set(struct ieee80211_if_ap *bss, int aid)
+{
+	/*
+	 * This format has ben mandated by the IEEE specifications,
+	 * so this line may not be changed to use the __set_bit() format.
+	 */
+	bss->tim[(aid)/8] |= 1<<((aid) % 8);
+}
+
+static inline void bss_tim_set(struct ieee80211_local *local,
+			       struct ieee80211_if_ap *bss, int aid)
+{
+	spin_lock_bh(&local->sta_lock);
+	__bss_tim_set(bss, aid);
+	spin_unlock_bh(&local->sta_lock);
+}
+
+static inline void __bss_tim_clear(struct ieee80211_if_ap *bss, int aid)
+{
+	/*
+	 * This format has ben mandated by the IEEE specifications,
+	 * so this line may not be changed to use the __clear_bit() format.
+	 */
+	bss->tim[(aid)/8] &= !(1<<((aid) % 8));
+}
+
+static inline void bss_tim_clear(struct ieee80211_local *local,
+				 struct ieee80211_if_ap *bss, int aid)
+{
+	spin_lock_bh(&local->sta_lock);
+	__bss_tim_clear(bss, aid);
+	spin_unlock_bh(&local->sta_lock);
+}
+
+/**
+ * ieee80211_is_erp_rate - Check if a rate is an ERP rate
+ * @phymode: The PHY-mode for this rate (MODE_IEEE80211...)
+ * @rate: Transmission rate to check, in 100 kbps
+ *
+ * Check if a given rate is an Extended Rate PHY (ERP) rate.
+ */
+static inline int ieee80211_is_erp_rate(int phymode, int rate)
+{
+	if (phymode == MODE_IEEE80211G) {
+		if (rate != 10 && rate != 20 &&
+		    rate != 55 && rate != 110)
+			return 1;
+	}
+	return 0;
+}
+
+/* ieee80211.c */
+int ieee80211_hw_config(struct ieee80211_local *local);
+int ieee80211_if_config(struct net_device *dev);
+int ieee80211_if_config_beacon(struct net_device *dev);
+struct ieee80211_key_conf *
+ieee80211_key_data2conf(struct ieee80211_local *local,
+			const struct ieee80211_key *data);
+struct ieee80211_key *ieee80211_key_alloc(struct ieee80211_sub_if_data *sdata,
+					  int idx, size_t key_len, gfp_t flags);
+void ieee80211_key_free(struct ieee80211_key *key);
+void ieee80211_rx_mgmt(struct ieee80211_local *local, struct sk_buff *skb,
+		       struct ieee80211_rx_status *status, u32 msg_type);
+void ieee80211_prepare_rates(struct ieee80211_local *local,
+			     struct ieee80211_hw_mode *mode);
+void ieee80211_tx_set_iswep(struct ieee80211_txrx_data *tx);
+int ieee80211_if_update_wds(struct net_device *dev, u8 *remote_addr);
+void ieee80211_if_setup(struct net_device *dev);
+void ieee80211_if_mgmt_setup(struct net_device *dev);
+int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local,
+				 const char *name);
+struct net_device_stats *ieee80211_dev_stats(struct net_device *dev);
+
+/* ieee80211_ioctl.c */
+extern const struct iw_handler_def ieee80211_iw_handler_def;
+
+void ieee80211_update_default_wep_only(struct ieee80211_local *local);
+
+
+/* Least common multiple of the used rates (in 100 kbps). This is used to
+ * calculate rate_inv values for each rate so that only integers are needed. */
+#define CHAN_UTIL_RATE_LCM 95040
+/* 1 usec is 1/8 * (95040/10) = 1188 */
+#define CHAN_UTIL_PER_USEC 1188
+/* Amount of bits to shift the result right to scale the total utilization
+ * to values that will not wrap around 32-bit integers. */
+#define CHAN_UTIL_SHIFT 9
+/* Theoretical maximum of channel utilization counter in 10 ms (stat_time=1):
+ * (CHAN_UTIL_PER_USEC * 10000) >> CHAN_UTIL_SHIFT = 23203. So dividing the
+ * raw value with about 23 should give utilization in 10th of a percentage
+ * (1/1000). However, utilization is only estimated and not all intervals
+ * between frames etc. are calculated. 18 seems to give numbers that are closer
+ * to the real maximum. */
+#define CHAN_UTIL_PER_10MS 18
+#define CHAN_UTIL_HDR_LONG (202 * CHAN_UTIL_PER_USEC)
+#define CHAN_UTIL_HDR_SHORT (40 * CHAN_UTIL_PER_USEC)
+
+
+/* ieee80211_ioctl.c */
+int ieee80211_set_compression(struct ieee80211_local *local,
+			      struct net_device *dev, struct sta_info *sta);
+int ieee80211_init_client(struct net_device *dev);
+int ieee80211_set_channel(struct ieee80211_local *local, int channel, int freq);
+/* ieee80211_sta.c */
+void ieee80211_sta_timer(unsigned long data);
+void ieee80211_sta_work(struct work_struct *work);
+void ieee80211_sta_scan_work(struct work_struct *work);
+void ieee80211_sta_rx_mgmt(struct net_device *dev, struct sk_buff *skb,
+			   struct ieee80211_rx_status *rx_status);
+int ieee80211_sta_set_ssid(struct net_device *dev, char *ssid, size_t len);
+int ieee80211_sta_get_ssid(struct net_device *dev, char *ssid, size_t *len);
+int ieee80211_sta_set_bssid(struct net_device *dev, u8 *bssid);
+int ieee80211_sta_req_scan(struct net_device *dev, u8 *ssid, size_t ssid_len);
+void ieee80211_sta_req_auth(struct net_device *dev,
+			    struct ieee80211_if_sta *ifsta);
+int ieee80211_sta_scan_results(struct net_device *dev, char *buf, size_t len);
+void ieee80211_sta_rx_scan(struct net_device *dev, struct sk_buff *skb,
+			   struct ieee80211_rx_status *rx_status);
+void ieee80211_rx_bss_list_init(struct net_device *dev);
+void ieee80211_rx_bss_list_deinit(struct net_device *dev);
+int ieee80211_sta_set_extra_ie(struct net_device *dev, char *ie, size_t len);
+struct sta_info * ieee80211_ibss_add_sta(struct net_device *dev,
+					 struct sk_buff *skb, u8 *bssid,
+					 u8 *addr);
+int ieee80211_sta_deauthenticate(struct net_device *dev, u16 reason);
+int ieee80211_sta_disassociate(struct net_device *dev, u16 reason);
+
+/* ieee80211_iface.c */
+int ieee80211_if_add(struct net_device *dev, const char *name,
+		     struct net_device **new_dev, int type);
+void ieee80211_if_set_type(struct net_device *dev, int type);
+void ieee80211_if_reinit(struct net_device *dev);
+void __ieee80211_if_del(struct ieee80211_local *local,
+			struct ieee80211_sub_if_data *sdata);
+int ieee80211_if_remove(struct net_device *dev, const char *name, int id);
+void ieee80211_if_free(struct net_device *dev);
+void ieee80211_if_sdata_init(struct ieee80211_sub_if_data *sdata);
+int ieee80211_if_add_mgmt(struct ieee80211_local *local);
+void ieee80211_if_del_mgmt(struct ieee80211_local *local);
+
+/* for wiphy privid */
+extern void *mac80211_wiphy_privid;
+
+#endif /* IEEE80211_I_H */
diff --git a/net/mac80211/ieee80211_iface.c b/net/mac80211/ieee80211_iface.c
new file mode 100644
index 0000000..cf0f32e
--- /dev/null
+++ b/net/mac80211/ieee80211_iface.c
@@ -0,0 +1,352 @@
+/*
+ * Copyright 2002-2005, Instant802 Networks, Inc.
+ * Copyright 2005-2006, Devicescape Software, Inc.
+ * Copyright (c) 2006 Jiri Benc <jbenc@suse.cz>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/kernel.h>
+#include <linux/if_arp.h>
+#include <linux/netdevice.h>
+#include <linux/rtnetlink.h>
+#include <net/mac80211.h>
+#include "ieee80211_i.h"
+#include "sta_info.h"
+#include "debugfs_netdev.h"
+
+void ieee80211_if_sdata_init(struct ieee80211_sub_if_data *sdata)
+{
+	int i;
+
+	/* Default values for sub-interface parameters */
+	sdata->drop_unencrypted = 0;
+	sdata->eapol = 1;
+	for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++)
+		skb_queue_head_init(&sdata->fragments[i].skb_list);
+}
+
+static void ieee80211_if_sdata_deinit(struct ieee80211_sub_if_data *sdata)
+{
+	int i;
+
+	for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++) {
+		__skb_queue_purge(&sdata->fragments[i].skb_list);
+	}
+}
+
+/* Must be called with rtnl lock held. */
+int ieee80211_if_add(struct net_device *dev, const char *name,
+		     struct net_device **new_dev, int type)
+{
+	struct net_device *ndev;
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+	struct ieee80211_sub_if_data *sdata = NULL;
+	int ret;
+
+	ASSERT_RTNL();
+	ndev = alloc_netdev(sizeof(struct ieee80211_sub_if_data),
+			    name, ieee80211_if_setup);
+	if (!ndev)
+		return -ENOMEM;
+
+	ret = dev_alloc_name(ndev, ndev->name);
+	if (ret < 0)
+		goto fail;
+
+	memcpy(ndev->dev_addr, local->hw.wiphy->perm_addr, ETH_ALEN);
+	ndev->base_addr = dev->base_addr;
+	ndev->irq = dev->irq;
+	ndev->mem_start = dev->mem_start;
+	ndev->mem_end = dev->mem_end;
+	SET_NETDEV_DEV(ndev, wiphy_dev(local->hw.wiphy));
+
+	sdata = IEEE80211_DEV_TO_SUB_IF(ndev);
+	ndev->ieee80211_ptr = &sdata->wdev;
+	sdata->wdev.wiphy = local->hw.wiphy;
+	sdata->type = IEEE80211_IF_TYPE_AP;
+	sdata->dev = ndev;
+	sdata->local = local;
+	ieee80211_if_sdata_init(sdata);
+
+	ret = register_netdevice(ndev);
+	if (ret)
+		goto fail;
+
+	ieee80211_debugfs_add_netdev(sdata);
+	ieee80211_if_set_type(ndev, type);
+
+	write_lock_bh(&local->sub_if_lock);
+	if (unlikely(local->reg_state == IEEE80211_DEV_UNREGISTERED)) {
+		write_unlock_bh(&local->sub_if_lock);
+		__ieee80211_if_del(local, sdata);
+		return -ENODEV;
+	}
+	list_add(&sdata->list, &local->sub_if_list);
+	if (new_dev)
+		*new_dev = ndev;
+	write_unlock_bh(&local->sub_if_lock);
+
+	ieee80211_update_default_wep_only(local);
+
+	return 0;
+
+fail:
+	free_netdev(ndev);
+	return ret;
+}
+
+int ieee80211_if_add_mgmt(struct ieee80211_local *local)
+{
+	struct net_device *ndev;
+	struct ieee80211_sub_if_data *nsdata;
+	int ret;
+
+	ASSERT_RTNL();
+
+	ndev = alloc_netdev(sizeof(struct ieee80211_sub_if_data), "wmgmt%d",
+			    ieee80211_if_mgmt_setup);
+	if (!ndev)
+		return -ENOMEM;
+	ret = dev_alloc_name(ndev, ndev->name);
+	if (ret < 0)
+		goto fail;
+
+	memcpy(ndev->dev_addr, local->hw.wiphy->perm_addr, ETH_ALEN);
+	SET_NETDEV_DEV(ndev, wiphy_dev(local->hw.wiphy));
+
+	nsdata = IEEE80211_DEV_TO_SUB_IF(ndev);
+	ndev->ieee80211_ptr = &nsdata->wdev;
+	nsdata->wdev.wiphy = local->hw.wiphy;
+	nsdata->type = IEEE80211_IF_TYPE_MGMT;
+	nsdata->dev = ndev;
+	nsdata->local = local;
+	ieee80211_if_sdata_init(nsdata);
+
+	ret = register_netdevice(ndev);
+	if (ret)
+		goto fail;
+
+	ieee80211_debugfs_add_netdev(nsdata);
+
+	if (local->open_count > 0)
+		dev_open(ndev);
+	local->apdev = ndev;
+	return 0;
+
+fail:
+	free_netdev(ndev);
+	return ret;
+}
+
+void ieee80211_if_del_mgmt(struct ieee80211_local *local)
+{
+	struct net_device *apdev;
+
+	ASSERT_RTNL();
+	apdev = local->apdev;
+	ieee80211_debugfs_remove_netdev(IEEE80211_DEV_TO_SUB_IF(apdev));
+	local->apdev = NULL;
+	unregister_netdevice(apdev);
+}
+
+void ieee80211_if_set_type(struct net_device *dev, int type)
+{
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+	int oldtype = sdata->type;
+
+	sdata->type = type;
+	switch (type) {
+	case IEEE80211_IF_TYPE_WDS:
+		sdata->bss = NULL;
+		break;
+	case IEEE80211_IF_TYPE_VLAN:
+		break;
+	case IEEE80211_IF_TYPE_AP:
+		sdata->u.ap.dtim_period = 2;
+		sdata->u.ap.force_unicast_rateidx = -1;
+		sdata->u.ap.max_ratectrl_rateidx = -1;
+		skb_queue_head_init(&sdata->u.ap.ps_bc_buf);
+		sdata->bss = &sdata->u.ap;
+		break;
+	case IEEE80211_IF_TYPE_STA:
+	case IEEE80211_IF_TYPE_IBSS: {
+		struct ieee80211_sub_if_data *msdata;
+		struct ieee80211_if_sta *ifsta;
+
+		ifsta = &sdata->u.sta;
+		INIT_WORK(&ifsta->work, ieee80211_sta_work);
+		setup_timer(&ifsta->timer, ieee80211_sta_timer,
+			    (unsigned long) sdata);
+		skb_queue_head_init(&ifsta->skb_queue);
+
+		ifsta->capab = WLAN_CAPABILITY_ESS;
+		ifsta->auth_algs = IEEE80211_AUTH_ALG_OPEN |
+			IEEE80211_AUTH_ALG_SHARED_KEY;
+		ifsta->create_ibss = 1;
+		ifsta->wmm_enabled = 1;
+		ifsta->auto_channel_sel = 1;
+		ifsta->auto_bssid_sel = 1;
+
+		msdata = IEEE80211_DEV_TO_SUB_IF(sdata->local->mdev);
+		sdata->bss = &msdata->u.ap;
+		break;
+	}
+	case IEEE80211_IF_TYPE_MNTR:
+		dev->type = ARPHRD_IEEE80211_RADIOTAP;
+		break;
+	default:
+		printk(KERN_WARNING "%s: %s: Unknown interface type 0x%x",
+		       dev->name, __FUNCTION__, type);
+	}
+	ieee80211_debugfs_change_if_type(sdata, oldtype);
+	ieee80211_update_default_wep_only(local);
+}
+
+/* Must be called with rtnl lock held. */
+void ieee80211_if_reinit(struct net_device *dev)
+{
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	struct sta_info *sta;
+	int i;
+
+	ASSERT_RTNL();
+	ieee80211_if_sdata_deinit(sdata);
+	for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
+		if (!sdata->keys[i])
+			continue;
+#if 0
+		/* The interface is down at the moment, so there is not
+		 * really much point in disabling the keys at this point. */
+		memset(addr, 0xff, ETH_ALEN);
+		if (local->ops->set_key)
+			local->ops->set_key(local_to_hw(local), DISABLE_KEY, addr,
+					    local->keys[i], 0);
+#endif
+		ieee80211_key_free(sdata->keys[i]);
+		sdata->keys[i] = NULL;
+	}
+
+	switch (sdata->type) {
+	case IEEE80211_IF_TYPE_AP: {
+		/* Remove all virtual interfaces that use this BSS
+		 * as their sdata->bss */
+		struct ieee80211_sub_if_data *tsdata, *n;
+		LIST_HEAD(tmp_list);
+
+		write_lock_bh(&local->sub_if_lock);
+		list_for_each_entry_safe(tsdata, n, &local->sub_if_list, list) {
+			if (tsdata != sdata && tsdata->bss == &sdata->u.ap) {
+				printk(KERN_DEBUG "%s: removing virtual "
+				       "interface %s because its BSS interface"
+				       " is being removed\n",
+				       sdata->dev->name, tsdata->dev->name);
+				list_move_tail(&tsdata->list, &tmp_list);
+			}
+		}
+		write_unlock_bh(&local->sub_if_lock);
+
+		list_for_each_entry_safe(tsdata, n, &tmp_list, list)
+			__ieee80211_if_del(local, tsdata);
+
+		kfree(sdata->u.ap.beacon_head);
+		kfree(sdata->u.ap.beacon_tail);
+		kfree(sdata->u.ap.generic_elem);
+
+		if (dev != local->mdev) {
+			struct sk_buff *skb;
+			while ((skb = skb_dequeue(&sdata->u.ap.ps_bc_buf))) {
+				local->total_ps_buffered--;
+				dev_kfree_skb(skb);
+			}
+		}
+
+		break;
+	}
+	case IEEE80211_IF_TYPE_WDS:
+		sta = sta_info_get(local, sdata->u.wds.remote_addr);
+		if (sta) {
+			sta_info_put(sta);
+			sta_info_free(sta, 0);
+		} else {
+#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
+			printk(KERN_DEBUG "%s: Someone had deleted my STA "
+			       "entry for the WDS link\n", dev->name);
+#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
+		}
+		break;
+	case IEEE80211_IF_TYPE_STA:
+	case IEEE80211_IF_TYPE_IBSS:
+		kfree(sdata->u.sta.extra_ie);
+		sdata->u.sta.extra_ie = NULL;
+		kfree(sdata->u.sta.assocreq_ies);
+		sdata->u.sta.assocreq_ies = NULL;
+		kfree(sdata->u.sta.assocresp_ies);
+		sdata->u.sta.assocresp_ies = NULL;
+		if (sdata->u.sta.probe_resp) {
+			dev_kfree_skb(sdata->u.sta.probe_resp);
+			sdata->u.sta.probe_resp = NULL;
+		}
+
+		break;
+	case IEEE80211_IF_TYPE_MNTR:
+		dev->type = ARPHRD_ETHER;
+		break;
+	}
+
+	/* remove all STAs that are bound to this virtual interface */
+	sta_info_flush(local, dev);
+
+	memset(&sdata->u, 0, sizeof(sdata->u));
+	ieee80211_if_sdata_init(sdata);
+}
+
+/* Must be called with rtnl lock held. */
+void __ieee80211_if_del(struct ieee80211_local *local,
+			struct ieee80211_sub_if_data *sdata)
+{
+	struct net_device *dev = sdata->dev;
+
+	ieee80211_debugfs_remove_netdev(sdata);
+	unregister_netdevice(dev);
+	/* Except master interface, the net_device will be freed by
+	 * net_device->destructor (i. e. ieee80211_if_free). */
+}
+
+/* Must be called with rtnl lock held. */
+int ieee80211_if_remove(struct net_device *dev, const char *name, int id)
+{
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+	struct ieee80211_sub_if_data *sdata, *n;
+
+	ASSERT_RTNL();
+
+	write_lock_bh(&local->sub_if_lock);
+	list_for_each_entry_safe(sdata, n, &local->sub_if_list, list) {
+		if ((sdata->type == id || id == -1) &&
+		    strcmp(name, sdata->dev->name) == 0 &&
+		    sdata->dev != local->mdev) {
+			list_del(&sdata->list);
+			write_unlock_bh(&local->sub_if_lock);
+			__ieee80211_if_del(local, sdata);
+			ieee80211_update_default_wep_only(local);
+			return 0;
+		}
+	}
+	write_unlock_bh(&local->sub_if_lock);
+	return -ENODEV;
+}
+
+void ieee80211_if_free(struct net_device *dev)
+{
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+
+	/* local->apdev must be NULL when freeing management interface */
+	BUG_ON(dev == local->apdev);
+	ieee80211_if_sdata_deinit(sdata);
+	free_netdev(dev);
+}
diff --git a/net/mac80211/ieee80211_ioctl.c b/net/mac80211/ieee80211_ioctl.c
new file mode 100644
index 0000000..352f03b
--- /dev/null
+++ b/net/mac80211/ieee80211_ioctl.c
@@ -0,0 +1,1822 @@
+/*
+ * Copyright 2002-2005, Instant802 Networks, Inc.
+ * Copyright 2005-2006, Devicescape Software, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/skbuff.h>
+#include <linux/etherdevice.h>
+#include <linux/if_arp.h>
+#include <linux/wireless.h>
+#include <net/iw_handler.h>
+#include <asm/uaccess.h>
+
+#include <net/mac80211.h>
+#include "ieee80211_i.h"
+#include "hostapd_ioctl.h"
+#include "ieee80211_rate.h"
+#include "wpa.h"
+#include "aes_ccm.h"
+#include "debugfs_key.h"
+
+static int ieee80211_regdom = 0x10; /* FCC */
+module_param(ieee80211_regdom, int, 0444);
+MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain; 64=MKK");
+
+/*
+ * If firmware is upgraded by the vendor, additional channels can be used based
+ * on the new Japanese regulatory rules. This is indicated by setting
+ * ieee80211_japan_5ghz module parameter to one when loading the 80211 kernel
+ * module.
+ */
+static int ieee80211_japan_5ghz /* = 0 */;
+module_param(ieee80211_japan_5ghz, int, 0444);
+MODULE_PARM_DESC(ieee80211_japan_5ghz, "Vendor-updated firmware for 5 GHz");
+
+static void ieee80211_set_hw_encryption(struct net_device *dev,
+					struct sta_info *sta, u8 addr[ETH_ALEN],
+					struct ieee80211_key *key)
+{
+	struct ieee80211_key_conf *keyconf = NULL;
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+
+	/* default to sw encryption; this will be cleared by low-level
+	 * driver if the hw supports requested encryption */
+	if (key)
+		key->force_sw_encrypt = 1;
+
+	if (key && local->ops->set_key &&
+	    (keyconf = ieee80211_key_data2conf(local, key))) {
+		if (local->ops->set_key(local_to_hw(local), SET_KEY, addr,
+				       keyconf, sta ? sta->aid : 0)) {
+			key->force_sw_encrypt = 1;
+			key->hw_key_idx = HW_KEY_IDX_INVALID;
+		} else {
+			key->force_sw_encrypt =
+				!!(keyconf->flags & IEEE80211_KEY_FORCE_SW_ENCRYPT);
+			key->hw_key_idx =
+				keyconf->hw_key_idx;
+
+		}
+	}
+	kfree(keyconf);
+}
+
+
+static int ieee80211_set_encryption(struct net_device *dev, u8 *sta_addr,
+				    int idx, int alg, int set_tx_key,
+				    const u8 *_key, size_t key_len)
+{
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+	int ret = 0;
+	struct sta_info *sta;
+	struct ieee80211_key *key, *old_key;
+	int try_hwaccel = 1;
+	struct ieee80211_key_conf *keyconf;
+	struct ieee80211_sub_if_data *sdata;
+
+	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+
+	if (is_broadcast_ether_addr(sta_addr)) {
+		sta = NULL;
+		if (idx >= NUM_DEFAULT_KEYS) {
+			printk(KERN_DEBUG "%s: set_encrypt - invalid idx=%d\n",
+			       dev->name, idx);
+			return -EINVAL;
+		}
+		key = sdata->keys[idx];
+
+		/* TODO: consider adding hwaccel support for these; at least
+		 * Atheros key cache should be able to handle this since AP is
+		 * only transmitting frames with default keys. */
+		/* FIX: hw key cache can be used when only one virtual
+		 * STA is associated with each AP. If more than one STA
+		 * is associated to the same AP, software encryption
+		 * must be used. This should be done automatically
+		 * based on configured station devices. For the time
+		 * being, this can be only set at compile time. */
+	} else {
+		set_tx_key = 0;
+		if (idx != 0) {
+			printk(KERN_DEBUG "%s: set_encrypt - non-zero idx for "
+			       "individual key\n", dev->name);
+			return -EINVAL;
+		}
+
+		sta = sta_info_get(local, sta_addr);
+		if (!sta) {
+#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
+			printk(KERN_DEBUG "%s: set_encrypt - unknown addr "
+			       MAC_FMT "\n",
+			       dev->name, MAC_ARG(sta_addr));
+#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
+
+			return -ENOENT;
+		}
+
+		key = sta->key;
+	}
+
+	/* FIX:
+	 * Cannot configure default hwaccel keys with WEP algorithm, if
+	 * any of the virtual interfaces is using static WEP
+	 * configuration because hwaccel would otherwise try to decrypt
+	 * these frames.
+	 *
+	 * For now, just disable WEP hwaccel for broadcast when there is
+	 * possibility of conflict with default keys. This can maybe later be
+	 * optimized by using non-default keys (at least with Atheros ar521x).
+	 */
+	if (!sta && alg == ALG_WEP && !local->default_wep_only &&
+	    sdata->type != IEEE80211_IF_TYPE_IBSS &&
+	    sdata->type != IEEE80211_IF_TYPE_AP) {
+		try_hwaccel = 0;
+	}
+
+	if (local->hw.flags & IEEE80211_HW_DEVICE_HIDES_WEP) {
+		/* Software encryption cannot be used with devices that hide
+		 * encryption from the host system, so always try to use
+		 * hardware acceleration with such devices. */
+		try_hwaccel = 1;
+	}
+
+	if ((local->hw.flags & IEEE80211_HW_NO_TKIP_WMM_HWACCEL) &&
+	    alg == ALG_TKIP) {
+		if (sta && (sta->flags & WLAN_STA_WME)) {
+		/* Hardware does not support hwaccel with TKIP when using WMM.
+		 */
+			try_hwaccel = 0;
+		}
+		else if (sdata->type == IEEE80211_IF_TYPE_STA) {
+			sta = sta_info_get(local, sdata->u.sta.bssid);
+			if (sta) {
+				if (sta->flags & WLAN_STA_WME) {
+					try_hwaccel = 0;
+				}
+				sta_info_put(sta);
+				sta = NULL;
+			}
+		}
+	}
+
+	if (alg == ALG_NONE) {
+		keyconf = NULL;
+		if (try_hwaccel && key &&
+		    key->hw_key_idx != HW_KEY_IDX_INVALID &&
+		    local->ops->set_key &&
+		    (keyconf = ieee80211_key_data2conf(local, key)) != NULL &&
+		    local->ops->set_key(local_to_hw(local), DISABLE_KEY,
+				       sta_addr, keyconf, sta ? sta->aid : 0)) {
+			printk(KERN_DEBUG "%s: set_encrypt - low-level disable"
+			       " failed\n", dev->name);
+			ret = -EINVAL;
+		}
+		kfree(keyconf);
+
+		if (set_tx_key || sdata->default_key == key) {
+			ieee80211_debugfs_key_remove_default(sdata);
+			sdata->default_key = NULL;
+		}
+		ieee80211_debugfs_key_remove(key);
+		if (sta)
+			sta->key = NULL;
+		else
+			sdata->keys[idx] = NULL;
+		ieee80211_key_free(key);
+		key = NULL;
+	} else {
+		old_key = key;
+		key = ieee80211_key_alloc(sta ? NULL : sdata, idx, key_len,
+					  GFP_KERNEL);
+		if (!key) {
+			ret = -ENOMEM;
+			goto err_out;
+		}
+
+		/* default to sw encryption; low-level driver sets these if the
+		 * requested encryption is supported */
+		key->hw_key_idx = HW_KEY_IDX_INVALID;
+		key->force_sw_encrypt = 1;
+
+		key->alg = alg;
+		key->keyidx = idx;
+		key->keylen = key_len;
+		memcpy(key->key, _key, key_len);
+		if (set_tx_key)
+			key->default_tx_key = 1;
+
+		if (alg == ALG_CCMP) {
+			/* Initialize AES key state here as an optimization
+			 * so that it does not need to be initialized for every
+			 * packet. */
+			key->u.ccmp.tfm = ieee80211_aes_key_setup_encrypt(
+				key->key);
+			if (!key->u.ccmp.tfm) {
+				ret = -ENOMEM;
+				goto err_free;
+			}
+		}
+
+		if (set_tx_key || sdata->default_key == old_key) {
+			ieee80211_debugfs_key_remove_default(sdata);
+			sdata->default_key = NULL;
+		}
+		ieee80211_debugfs_key_remove(old_key);
+		if (sta)
+			sta->key = key;
+		else
+			sdata->keys[idx] = key;
+		ieee80211_key_free(old_key);
+		ieee80211_debugfs_key_add(local, key);
+		if (sta)
+			ieee80211_debugfs_key_sta_link(key, sta);
+
+		if (try_hwaccel &&
+		    (alg == ALG_WEP || alg == ALG_TKIP || alg == ALG_CCMP))
+			ieee80211_set_hw_encryption(dev, sta, sta_addr, key);
+	}
+
+	if (set_tx_key || (!sta && !sdata->default_key && key)) {
+		sdata->default_key = key;
+		if (key)
+			ieee80211_debugfs_key_add_default(sdata);
+
+		if (local->ops->set_key_idx &&
+		    local->ops->set_key_idx(local_to_hw(local), idx))
+			printk(KERN_DEBUG "%s: failed to set TX key idx for "
+			       "low-level driver\n", dev->name);
+	}
+
+	if (sta)
+		sta_info_put(sta);
+
+	return 0;
+
+err_free:
+	ieee80211_key_free(key);
+err_out:
+	if (sta)
+		sta_info_put(sta);
+	return ret;
+}
+
+static int ieee80211_ioctl_siwgenie(struct net_device *dev,
+				    struct iw_request_info *info,
+				    struct iw_point *data, char *extra)
+{
+	struct ieee80211_sub_if_data *sdata;
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+
+	if (local->user_space_mlme)
+		return -EOPNOTSUPP;
+
+	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	if (sdata->type == IEEE80211_IF_TYPE_STA ||
+	    sdata->type == IEEE80211_IF_TYPE_IBSS) {
+		int ret = ieee80211_sta_set_extra_ie(dev, extra, data->length);
+		if (ret)
+			return ret;
+		sdata->u.sta.auto_bssid_sel = 0;
+		ieee80211_sta_req_auth(dev, &sdata->u.sta);
+		return 0;
+	}
+
+	if (sdata->type == IEEE80211_IF_TYPE_AP) {
+		kfree(sdata->u.ap.generic_elem);
+		sdata->u.ap.generic_elem = kmalloc(data->length, GFP_KERNEL);
+		if (!sdata->u.ap.generic_elem)
+			return -ENOMEM;
+		memcpy(sdata->u.ap.generic_elem, extra, data->length);
+		sdata->u.ap.generic_elem_len = data->length;
+		return ieee80211_if_config(dev);
+	}
+	return -EOPNOTSUPP;
+}
+
+static int ieee80211_ioctl_set_radio_enabled(struct net_device *dev,
+					     int val)
+{
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+	struct ieee80211_conf *conf = &local->hw.conf;
+
+	conf->radio_enabled = val;
+	return ieee80211_hw_config(wdev_priv(dev->ieee80211_ptr));
+}
+
+static int ieee80211_ioctl_giwname(struct net_device *dev,
+				   struct iw_request_info *info,
+				   char *name, char *extra)
+{
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+
+	switch (local->hw.conf.phymode) {
+	case MODE_IEEE80211A:
+		strcpy(name, "IEEE 802.11a");
+		break;
+	case MODE_IEEE80211B:
+		strcpy(name, "IEEE 802.11b");
+		break;
+	case MODE_IEEE80211G:
+		strcpy(name, "IEEE 802.11g");
+		break;
+	case MODE_ATHEROS_TURBO:
+		strcpy(name, "5GHz Turbo");
+		break;
+	default:
+		strcpy(name, "IEEE 802.11");
+		break;
+	}
+
+	return 0;
+}
+
+
+static int ieee80211_ioctl_giwrange(struct net_device *dev,
+				 struct iw_request_info *info,
+				 struct iw_point *data, char *extra)
+{
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+	struct iw_range *range = (struct iw_range *) extra;
+
+	data->length = sizeof(struct iw_range);
+	memset(range, 0, sizeof(struct iw_range));
+
+	range->we_version_compiled = WIRELESS_EXT;
+	range->we_version_source = 21;
+	range->retry_capa = IW_RETRY_LIMIT;
+	range->retry_flags = IW_RETRY_LIMIT;
+	range->min_retry = 0;
+	range->max_retry = 255;
+	range->min_rts = 0;
+	range->max_rts = 2347;
+	range->min_frag = 256;
+	range->max_frag = 2346;
+
+	range->encoding_size[0] = 5;
+	range->encoding_size[1] = 13;
+	range->num_encoding_sizes = 2;
+	range->max_encoding_tokens = NUM_DEFAULT_KEYS;
+
+	range->max_qual.qual = local->hw.max_signal;
+	range->max_qual.level = local->hw.max_rssi;
+	range->max_qual.noise = local->hw.max_noise;
+	range->max_qual.updated = local->wstats_flags;
+
+	range->avg_qual.qual = local->hw.max_signal/2;
+	range->avg_qual.level = 0;
+	range->avg_qual.noise = 0;
+	range->avg_qual.updated = local->wstats_flags;
+
+	range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
+			  IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP;
+
+	IW_EVENT_CAPA_SET_KERNEL(range->event_capa);
+	IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWTHRSPY);
+	IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWAP);
+	IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWSCAN);
+
+	return 0;
+}
+
+
+struct ieee80211_channel_range {
+	short start_freq;
+	short end_freq;
+	unsigned char power_level;
+	unsigned char antenna_max;
+};
+
+static const struct ieee80211_channel_range ieee80211_fcc_channels[] = {
+	{ 2412, 2462, 27, 6 } /* IEEE 802.11b/g, channels 1..11 */,
+	{ 5180, 5240, 17, 6 } /* IEEE 802.11a, channels 36..48 */,
+	{ 5260, 5320, 23, 6 } /* IEEE 802.11a, channels 52..64 */,
+	{ 5745, 5825, 30, 6 } /* IEEE 802.11a, channels 149..165, outdoor */,
+	{ 0 }
+};
+
+static const struct ieee80211_channel_range ieee80211_mkk_channels[] = {
+	{ 2412, 2472, 20, 6 } /* IEEE 802.11b/g, channels 1..13 */,
+	{ 5170, 5240, 20, 6 } /* IEEE 802.11a, channels 34..48 */,
+	{ 5260, 5320, 20, 6 } /* IEEE 802.11a, channels 52..64 */,
+	{ 0 }
+};
+
+
+static const struct ieee80211_channel_range *channel_range =
+	ieee80211_fcc_channels;
+
+
+static void ieee80211_unmask_channel(struct net_device *dev, int mode,
+				     struct ieee80211_channel *chan)
+{
+	int i;
+
+	chan->flag = 0;
+
+	if (ieee80211_regdom == 64 &&
+	    (mode == MODE_ATHEROS_TURBO || mode == MODE_ATHEROS_TURBOG)) {
+		/* Do not allow Turbo modes in Japan. */
+		return;
+	}
+
+	for (i = 0; channel_range[i].start_freq; i++) {
+		const struct ieee80211_channel_range *r = &channel_range[i];
+		if (r->start_freq <= chan->freq && r->end_freq >= chan->freq) {
+			if (ieee80211_regdom == 64 && !ieee80211_japan_5ghz &&
+			    chan->freq >= 5260 && chan->freq <= 5320) {
+				/*
+				 * Skip new channels in Japan since the
+				 * firmware was not marked having been upgraded
+				 * by the vendor.
+				 */
+				continue;
+			}
+
+			if (ieee80211_regdom == 0x10 &&
+			    (chan->freq == 5190 || chan->freq == 5210 ||
+			     chan->freq == 5230)) {
+				    /* Skip MKK channels when in FCC domain. */
+				    continue;
+			}
+
+			chan->flag |= IEEE80211_CHAN_W_SCAN |
+				IEEE80211_CHAN_W_ACTIVE_SCAN |
+				IEEE80211_CHAN_W_IBSS;
+			chan->power_level = r->power_level;
+			chan->antenna_max = r->antenna_max;
+
+			if (ieee80211_regdom == 64 &&
+			    (chan->freq == 5170 || chan->freq == 5190 ||
+			     chan->freq == 5210 || chan->freq == 5230)) {
+				/*
+				 * New regulatory rules in Japan have backwards
+				 * compatibility with old channels in 5.15-5.25
+				 * GHz band, but the station is not allowed to
+				 * use active scan on these old channels.
+				 */
+				chan->flag &= ~IEEE80211_CHAN_W_ACTIVE_SCAN;
+			}
+
+			if (ieee80211_regdom == 64 &&
+			    (chan->freq == 5260 || chan->freq == 5280 ||
+			     chan->freq == 5300 || chan->freq == 5320)) {
+				/*
+				 * IBSS is not allowed on 5.25-5.35 GHz band
+				 * due to radar detection requirements.
+				 */
+				chan->flag &= ~IEEE80211_CHAN_W_IBSS;
+			}
+
+			break;
+		}
+	}
+}
+
+
+static int ieee80211_unmask_channels(struct net_device *dev)
+{
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+	struct ieee80211_hw_mode *mode;
+	int c;
+
+	list_for_each_entry(mode, &local->modes_list, list) {
+		for (c = 0; c < mode->num_channels; c++) {
+			ieee80211_unmask_channel(dev, mode->mode,
+						 &mode->channels[c]);
+		}
+	}
+	return 0;
+}
+
+
+int ieee80211_init_client(struct net_device *dev)
+{
+	if (ieee80211_regdom == 0x40)
+		channel_range = ieee80211_mkk_channels;
+	ieee80211_unmask_channels(dev);
+	return 0;
+}
+
+
+static int ieee80211_ioctl_siwmode(struct net_device *dev,
+				   struct iw_request_info *info,
+				   __u32 *mode, char *extra)
+{
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	int type;
+
+	if (sdata->type == IEEE80211_IF_TYPE_VLAN)
+		return -EOPNOTSUPP;
+
+	switch (*mode) {
+	case IW_MODE_INFRA:
+		type = IEEE80211_IF_TYPE_STA;
+		break;
+	case IW_MODE_ADHOC:
+		type = IEEE80211_IF_TYPE_IBSS;
+		break;
+	case IW_MODE_MONITOR:
+		type = IEEE80211_IF_TYPE_MNTR;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (type == sdata->type)
+		return 0;
+	if (netif_running(dev))
+		return -EBUSY;
+
+	ieee80211_if_reinit(dev);
+	ieee80211_if_set_type(dev, type);
+
+	return 0;
+}
+
+
+static int ieee80211_ioctl_giwmode(struct net_device *dev,
+				   struct iw_request_info *info,
+				   __u32 *mode, char *extra)
+{
+	struct ieee80211_sub_if_data *sdata;
+
+	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	switch (sdata->type) {
+	case IEEE80211_IF_TYPE_AP:
+		*mode = IW_MODE_MASTER;
+		break;
+	case IEEE80211_IF_TYPE_STA:
+		*mode = IW_MODE_INFRA;
+		break;
+	case IEEE80211_IF_TYPE_IBSS:
+		*mode = IW_MODE_ADHOC;
+		break;
+	case IEEE80211_IF_TYPE_MNTR:
+		*mode = IW_MODE_MONITOR;
+		break;
+	case IEEE80211_IF_TYPE_WDS:
+		*mode = IW_MODE_REPEAT;
+		break;
+	case IEEE80211_IF_TYPE_VLAN:
+		*mode = IW_MODE_SECOND;		/* FIXME */
+		break;
+	default:
+		*mode = IW_MODE_AUTO;
+		break;
+	}
+	return 0;
+}
+
+int ieee80211_set_channel(struct ieee80211_local *local, int channel, int freq)
+{
+	struct ieee80211_hw_mode *mode;
+	int c, set = 0;
+	int ret = -EINVAL;
+
+	list_for_each_entry(mode, &local->modes_list, list) {
+		if (!(local->enabled_modes & (1 << mode->mode)))
+			continue;
+		for (c = 0; c < mode->num_channels; c++) {
+			struct ieee80211_channel *chan = &mode->channels[c];
+			if (chan->flag & IEEE80211_CHAN_W_SCAN &&
+			    ((chan->chan == channel) || (chan->freq == freq))) {
+				/* Use next_mode as the mode preference to
+				 * resolve non-unique channel numbers. */
+				if (set && mode->mode != local->next_mode)
+					continue;
+
+				local->oper_channel = chan;
+				local->oper_hw_mode = mode;
+				set++;
+			}
+		}
+	}
+
+	if (set) {
+		if (local->sta_scanning)
+			ret = 0;
+		else
+			ret = ieee80211_hw_config(local);
+
+		rate_control_clear(local);
+	}
+
+	return ret;
+}
+
+static int ieee80211_ioctl_siwfreq(struct net_device *dev,
+				   struct iw_request_info *info,
+				   struct iw_freq *freq, char *extra)
+{
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+
+	if (sdata->type == IEEE80211_IF_TYPE_STA)
+		sdata->u.sta.auto_channel_sel = 0;
+
+	/* freq->e == 0: freq->m = channel; otherwise freq = m * 10^e */
+	if (freq->e == 0) {
+		if (freq->m < 0) {
+			if (sdata->type == IEEE80211_IF_TYPE_STA)
+				sdata->u.sta.auto_channel_sel = 1;
+			return 0;
+		} else
+			return ieee80211_set_channel(local, freq->m, -1);
+	} else {
+		int i, div = 1000000;
+		for (i = 0; i < freq->e; i++)
+			div /= 10;
+		if (div > 0)
+			return ieee80211_set_channel(local, -1, freq->m / div);
+		else
+			return -EINVAL;
+	}
+}
+
+
+static int ieee80211_ioctl_giwfreq(struct net_device *dev,
+				   struct iw_request_info *info,
+				   struct iw_freq *freq, char *extra)
+{
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+
+	/* TODO: in station mode (Managed/Ad-hoc) might need to poll low-level
+	 * driver for the current channel with firmware-based management */
+
+	freq->m = local->hw.conf.freq;
+	freq->e = 6;
+
+	return 0;
+}
+
+
+static int ieee80211_ioctl_siwessid(struct net_device *dev,
+				    struct iw_request_info *info,
+				    struct iw_point *data, char *ssid)
+{
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+	struct ieee80211_sub_if_data *sdata;
+	size_t len = data->length;
+
+	/* iwconfig uses nul termination in SSID.. */
+	if (len > 0 && ssid[len - 1] == '\0')
+		len--;
+
+	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	if (sdata->type == IEEE80211_IF_TYPE_STA ||
+	    sdata->type == IEEE80211_IF_TYPE_IBSS) {
+		int ret;
+		if (local->user_space_mlme) {
+			if (len > IEEE80211_MAX_SSID_LEN)
+				return -EINVAL;
+			memcpy(sdata->u.sta.ssid, ssid, len);
+			sdata->u.sta.ssid_len = len;
+			return 0;
+		}
+		sdata->u.sta.auto_ssid_sel = !data->flags;
+		ret = ieee80211_sta_set_ssid(dev, ssid, len);
+		if (ret)
+			return ret;
+		ieee80211_sta_req_auth(dev, &sdata->u.sta);
+		return 0;
+	}
+
+	if (sdata->type == IEEE80211_IF_TYPE_AP) {
+		memcpy(sdata->u.ap.ssid, ssid, len);
+		memset(sdata->u.ap.ssid + len, 0,
+		       IEEE80211_MAX_SSID_LEN - len);
+		sdata->u.ap.ssid_len = len;
+		return ieee80211_if_config(dev);
+	}
+	return -EOPNOTSUPP;
+}
+
+
+static int ieee80211_ioctl_giwessid(struct net_device *dev,
+				    struct iw_request_info *info,
+				    struct iw_point *data, char *ssid)
+{
+	size_t len;
+
+	struct ieee80211_sub_if_data *sdata;
+	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	if (sdata->type == IEEE80211_IF_TYPE_STA ||
+	    sdata->type == IEEE80211_IF_TYPE_IBSS) {
+		int res = ieee80211_sta_get_ssid(dev, ssid, &len);
+		if (res == 0) {
+			data->length = len;
+			data->flags = 1;
+		} else
+			data->flags = 0;
+		return res;
+	}
+
+	if (sdata->type == IEEE80211_IF_TYPE_AP) {
+		len = sdata->u.ap.ssid_len;
+		if (len > IW_ESSID_MAX_SIZE)
+			len = IW_ESSID_MAX_SIZE;
+		memcpy(ssid, sdata->u.ap.ssid, len);
+		data->length = len;
+		data->flags = 1;
+		return 0;
+	}
+	return -EOPNOTSUPP;
+}
+
+
+static int ieee80211_ioctl_siwap(struct net_device *dev,
+				 struct iw_request_info *info,
+				 struct sockaddr *ap_addr, char *extra)
+{
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+	struct ieee80211_sub_if_data *sdata;
+
+	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	if (sdata->type == IEEE80211_IF_TYPE_STA ||
+	    sdata->type == IEEE80211_IF_TYPE_IBSS) {
+		int ret;
+		if (local->user_space_mlme) {
+			memcpy(sdata->u.sta.bssid, (u8 *) &ap_addr->sa_data,
+			       ETH_ALEN);
+			return 0;
+		}
+		if (is_zero_ether_addr((u8 *) &ap_addr->sa_data)) {
+			sdata->u.sta.auto_bssid_sel = 1;
+			sdata->u.sta.auto_channel_sel = 1;
+		} else if (is_broadcast_ether_addr((u8 *) &ap_addr->sa_data))
+			sdata->u.sta.auto_bssid_sel = 1;
+		else
+			sdata->u.sta.auto_bssid_sel = 0;
+		ret = ieee80211_sta_set_bssid(dev, (u8 *) &ap_addr->sa_data);
+		if (ret)
+			return ret;
+		ieee80211_sta_req_auth(dev, &sdata->u.sta);
+		return 0;
+	} else if (sdata->type == IEEE80211_IF_TYPE_WDS) {
+		if (memcmp(sdata->u.wds.remote_addr, (u8 *) &ap_addr->sa_data,
+			   ETH_ALEN) == 0)
+			return 0;
+		return ieee80211_if_update_wds(dev, (u8 *) &ap_addr->sa_data);
+	}
+
+	return -EOPNOTSUPP;
+}
+
+
+static int ieee80211_ioctl_giwap(struct net_device *dev,
+				 struct iw_request_info *info,
+				 struct sockaddr *ap_addr, char *extra)
+{
+	struct ieee80211_sub_if_data *sdata;
+
+	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	if (sdata->type == IEEE80211_IF_TYPE_STA ||
+	    sdata->type == IEEE80211_IF_TYPE_IBSS) {
+		ap_addr->sa_family = ARPHRD_ETHER;
+		memcpy(&ap_addr->sa_data, sdata->u.sta.bssid, ETH_ALEN);
+		return 0;
+	} else if (sdata->type == IEEE80211_IF_TYPE_WDS) {
+		ap_addr->sa_family = ARPHRD_ETHER;
+		memcpy(&ap_addr->sa_data, sdata->u.wds.remote_addr, ETH_ALEN);
+		return 0;
+	}
+
+	return -EOPNOTSUPP;
+}
+
+
+static int ieee80211_ioctl_siwscan(struct net_device *dev,
+				   struct iw_request_info *info,
+				   struct iw_point *data, char *extra)
+{
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	u8 *ssid = NULL;
+	size_t ssid_len = 0;
+
+	if (!netif_running(dev))
+		return -ENETDOWN;
+
+	if (local->scan_flags & IEEE80211_SCAN_MATCH_SSID) {
+		if (sdata->type == IEEE80211_IF_TYPE_STA ||
+		    sdata->type == IEEE80211_IF_TYPE_IBSS) {
+			ssid = sdata->u.sta.ssid;
+			ssid_len = sdata->u.sta.ssid_len;
+		} else if (sdata->type == IEEE80211_IF_TYPE_AP) {
+			ssid = sdata->u.ap.ssid;
+			ssid_len = sdata->u.ap.ssid_len;
+		} else
+			return -EINVAL;
+	}
+	return ieee80211_sta_req_scan(dev, ssid, ssid_len);
+}
+
+
+static int ieee80211_ioctl_giwscan(struct net_device *dev,
+				   struct iw_request_info *info,
+				   struct iw_point *data, char *extra)
+{
+	int res;
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+	if (local->sta_scanning)
+		return -EAGAIN;
+	res = ieee80211_sta_scan_results(dev, extra, data->length);
+	if (res >= 0) {
+		data->length = res;
+		return 0;
+	}
+	data->length = 0;
+	return res;
+}
+
+
+static int ieee80211_ioctl_siwrts(struct net_device *dev,
+				  struct iw_request_info *info,
+				  struct iw_param *rts, char *extra)
+{
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+
+	if (rts->disabled)
+		local->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD;
+	else if (rts->value < 0 || rts->value > IEEE80211_MAX_RTS_THRESHOLD)
+		return -EINVAL;
+	else
+		local->rts_threshold = rts->value;
+
+	/* If the wlan card performs RTS/CTS in hardware/firmware,
+	 * configure it here */
+
+	if (local->ops->set_rts_threshold)
+		local->ops->set_rts_threshold(local_to_hw(local),
+					     local->rts_threshold);
+
+	return 0;
+}
+
+static int ieee80211_ioctl_giwrts(struct net_device *dev,
+				  struct iw_request_info *info,
+				  struct iw_param *rts, char *extra)
+{
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+
+	rts->value = local->rts_threshold;
+	rts->disabled = (rts->value >= IEEE80211_MAX_RTS_THRESHOLD);
+	rts->fixed = 1;
+
+	return 0;
+}
+
+
+static int ieee80211_ioctl_siwfrag(struct net_device *dev,
+				   struct iw_request_info *info,
+				   struct iw_param *frag, char *extra)
+{
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+
+	if (frag->disabled)
+		local->fragmentation_threshold = IEEE80211_MAX_FRAG_THRESHOLD;
+	else if (frag->value < 256 ||
+		 frag->value > IEEE80211_MAX_FRAG_THRESHOLD)
+		return -EINVAL;
+	else {
+		/* Fragment length must be even, so strip LSB. */
+		local->fragmentation_threshold = frag->value & ~0x1;
+	}
+
+	/* If the wlan card performs fragmentation in hardware/firmware,
+	 * configure it here */
+
+	if (local->ops->set_frag_threshold)
+		local->ops->set_frag_threshold(
+			local_to_hw(local),
+			local->fragmentation_threshold);
+
+	return 0;
+}
+
+static int ieee80211_ioctl_giwfrag(struct net_device *dev,
+				   struct iw_request_info *info,
+				   struct iw_param *frag, char *extra)
+{
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+
+	frag->value = local->fragmentation_threshold;
+	frag->disabled = (frag->value >= IEEE80211_MAX_RTS_THRESHOLD);
+	frag->fixed = 1;
+
+	return 0;
+}
+
+
+static int ieee80211_ioctl_siwretry(struct net_device *dev,
+				    struct iw_request_info *info,
+				    struct iw_param *retry, char *extra)
+{
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+
+	if (retry->disabled ||
+	    (retry->flags & IW_RETRY_TYPE) != IW_RETRY_LIMIT)
+		return -EINVAL;
+
+	if (retry->flags & IW_RETRY_MAX)
+		local->long_retry_limit = retry->value;
+	else if (retry->flags & IW_RETRY_MIN)
+		local->short_retry_limit = retry->value;
+	else {
+		local->long_retry_limit = retry->value;
+		local->short_retry_limit = retry->value;
+	}
+
+	if (local->ops->set_retry_limit) {
+		return local->ops->set_retry_limit(
+			local_to_hw(local),
+			local->short_retry_limit,
+			local->long_retry_limit);
+	}
+
+	return 0;
+}
+
+
+static int ieee80211_ioctl_giwretry(struct net_device *dev,
+				    struct iw_request_info *info,
+				    struct iw_param *retry, char *extra)
+{
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+
+	retry->disabled = 0;
+	if (retry->flags == 0 || retry->flags & IW_RETRY_MIN) {
+		/* first return min value, iwconfig will ask max value
+		 * later if needed */
+		retry->flags |= IW_RETRY_LIMIT;
+		retry->value = local->short_retry_limit;
+		if (local->long_retry_limit != local->short_retry_limit)
+			retry->flags |= IW_RETRY_MIN;
+		return 0;
+	}
+	if (retry->flags & IW_RETRY_MAX) {
+		retry->flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
+		retry->value = local->long_retry_limit;
+	}
+
+	return 0;
+}
+
+static int ieee80211_ioctl_clear_keys(struct net_device *dev)
+{
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+	struct ieee80211_key_conf key;
+	int i;
+	u8 addr[ETH_ALEN];
+	struct ieee80211_key_conf *keyconf;
+	struct ieee80211_sub_if_data *sdata;
+	struct sta_info *sta;
+
+	memset(addr, 0xff, ETH_ALEN);
+	read_lock(&local->sub_if_lock);
+	list_for_each_entry(sdata, &local->sub_if_list, list) {
+		for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
+			keyconf = NULL;
+			if (sdata->keys[i] &&
+			    !sdata->keys[i]->force_sw_encrypt &&
+			    local->ops->set_key &&
+			    (keyconf = ieee80211_key_data2conf(local,
+							       sdata->keys[i])))
+				local->ops->set_key(local_to_hw(local),
+						   DISABLE_KEY, addr,
+						   keyconf, 0);
+			kfree(keyconf);
+			ieee80211_key_free(sdata->keys[i]);
+			sdata->keys[i] = NULL;
+		}
+		sdata->default_key = NULL;
+	}
+	read_unlock(&local->sub_if_lock);
+
+	spin_lock_bh(&local->sta_lock);
+	list_for_each_entry(sta, &local->sta_list, list) {
+		keyconf = NULL;
+		if (sta->key && !sta->key->force_sw_encrypt &&
+		    local->ops->set_key &&
+		    (keyconf = ieee80211_key_data2conf(local, sta->key)))
+			local->ops->set_key(local_to_hw(local), DISABLE_KEY,
+					   sta->addr, keyconf, sta->aid);
+		kfree(keyconf);
+		ieee80211_key_free(sta->key);
+		sta->key = NULL;
+	}
+	spin_unlock_bh(&local->sta_lock);
+
+	memset(&key, 0, sizeof(key));
+	if (local->ops->set_key &&
+		    local->ops->set_key(local_to_hw(local), REMOVE_ALL_KEYS,
+				       NULL, &key, 0))
+		printk(KERN_DEBUG "%s: failed to remove hwaccel keys\n",
+		       dev->name);
+
+	return 0;
+}
+
+
+static int
+ieee80211_ioctl_force_unicast_rate(struct net_device *dev,
+				   struct ieee80211_sub_if_data *sdata,
+				   int rate)
+{
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+	struct ieee80211_hw_mode *mode;
+	int i;
+
+	if (sdata->type != IEEE80211_IF_TYPE_AP)
+		return -ENOENT;
+
+	if (rate == 0) {
+		sdata->u.ap.force_unicast_rateidx = -1;
+		return 0;
+	}
+
+	mode = local->oper_hw_mode;
+	for (i = 0; i < mode->num_rates; i++) {
+		if (mode->rates[i].rate == rate) {
+			sdata->u.ap.force_unicast_rateidx = i;
+			return 0;
+		}
+	}
+	return -EINVAL;
+}
+
+
+static int
+ieee80211_ioctl_max_ratectrl_rate(struct net_device *dev,
+				  struct ieee80211_sub_if_data *sdata,
+				  int rate)
+{
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+	struct ieee80211_hw_mode *mode;
+	int i;
+
+	if (sdata->type != IEEE80211_IF_TYPE_AP)
+		return -ENOENT;
+
+	if (rate == 0) {
+		sdata->u.ap.max_ratectrl_rateidx = -1;
+		return 0;
+	}
+
+	mode = local->oper_hw_mode;
+	for (i = 0; i < mode->num_rates; i++) {
+		if (mode->rates[i].rate == rate) {
+			sdata->u.ap.max_ratectrl_rateidx = i;
+			return 0;
+		}
+	}
+	return -EINVAL;
+}
+
+
+static void ieee80211_key_enable_hwaccel(struct ieee80211_local *local,
+					 struct ieee80211_key *key)
+{
+	struct ieee80211_key_conf *keyconf;
+	u8 addr[ETH_ALEN];
+
+	if (!key || key->alg != ALG_WEP || !key->force_sw_encrypt ||
+	    (local->hw.flags & IEEE80211_HW_DEVICE_HIDES_WEP))
+		return;
+
+	memset(addr, 0xff, ETH_ALEN);
+	keyconf = ieee80211_key_data2conf(local, key);
+	if (keyconf && local->ops->set_key &&
+	    local->ops->set_key(local_to_hw(local),
+			       SET_KEY, addr, keyconf, 0) == 0) {
+		key->force_sw_encrypt =
+			!!(keyconf->flags & IEEE80211_KEY_FORCE_SW_ENCRYPT);
+		key->hw_key_idx = keyconf->hw_key_idx;
+	}
+	kfree(keyconf);
+}
+
+
+static void ieee80211_key_disable_hwaccel(struct ieee80211_local *local,
+					  struct ieee80211_key *key)
+{
+	struct ieee80211_key_conf *keyconf;
+	u8 addr[ETH_ALEN];
+
+	if (!key || key->alg != ALG_WEP || key->force_sw_encrypt ||
+	    (local->hw.flags & IEEE80211_HW_DEVICE_HIDES_WEP))
+		return;
+
+	memset(addr, 0xff, ETH_ALEN);
+	keyconf = ieee80211_key_data2conf(local, key);
+	if (keyconf && local->ops->set_key)
+		local->ops->set_key(local_to_hw(local), DISABLE_KEY,
+				   addr, keyconf, 0);
+	kfree(keyconf);
+	key->force_sw_encrypt = 1;
+}
+
+
+static int ieee80211_ioctl_default_wep_only(struct ieee80211_local *local,
+					    int value)
+{
+	int i;
+	struct ieee80211_sub_if_data *sdata;
+
+	local->default_wep_only = value;
+	read_lock(&local->sub_if_lock);
+	list_for_each_entry(sdata, &local->sub_if_list, list)
+		for (i = 0; i < NUM_DEFAULT_KEYS; i++)
+			if (value)
+				ieee80211_key_enable_hwaccel(local,
+							     sdata->keys[i]);
+			else
+				ieee80211_key_disable_hwaccel(local,
+							      sdata->keys[i]);
+	read_unlock(&local->sub_if_lock);
+
+	return 0;
+}
+
+
+void ieee80211_update_default_wep_only(struct ieee80211_local *local)
+{
+	int i = 0;
+	struct ieee80211_sub_if_data *sdata;
+
+	read_lock(&local->sub_if_lock);
+	list_for_each_entry(sdata, &local->sub_if_list, list) {
+
+		if (sdata->dev == local->mdev)
+			continue;
+
+		/* If there is an AP interface then depend on userspace to
+		   set default_wep_only correctly. */
+		if (sdata->type == IEEE80211_IF_TYPE_AP) {
+			read_unlock(&local->sub_if_lock);
+			return;
+		}
+
+		i++;
+	}
+
+	read_unlock(&local->sub_if_lock);
+
+	if (i <= 1)
+		ieee80211_ioctl_default_wep_only(local, 1);
+	else
+		ieee80211_ioctl_default_wep_only(local, 0);
+}
+
+
+static int ieee80211_ioctl_prism2_param(struct net_device *dev,
+					struct iw_request_info *info,
+					void *wrqu, char *extra)
+{
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+	struct ieee80211_sub_if_data *sdata;
+	int *i = (int *) extra;
+	int param = *i;
+	int value = *(i + 1);
+	int ret = 0;
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
+	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+
+	switch (param) {
+	case PRISM2_PARAM_IEEE_802_1X:
+		if (local->ops->set_ieee8021x)
+			ret = local->ops->set_ieee8021x(local_to_hw(local),
+							value);
+		if (ret)
+			printk(KERN_DEBUG "%s: failed to set IEEE 802.1X (%d) "
+			       "for low-level driver\n", dev->name, value);
+		else
+			sdata->ieee802_1x = value;
+		break;
+
+	case PRISM2_PARAM_ANTSEL_TX:
+		local->hw.conf.antenna_sel_tx = value;
+		if (ieee80211_hw_config(local))
+			ret = -EINVAL;
+		break;
+
+	case PRISM2_PARAM_ANTSEL_RX:
+		local->hw.conf.antenna_sel_rx = value;
+		if (ieee80211_hw_config(local))
+			ret = -EINVAL;
+		break;
+
+	case PRISM2_PARAM_CTS_PROTECT_ERP_FRAMES:
+		local->cts_protect_erp_frames = value;
+		break;
+
+	case PRISM2_PARAM_DROP_UNENCRYPTED:
+		sdata->drop_unencrypted = value;
+		break;
+
+	case PRISM2_PARAM_PREAMBLE:
+		local->short_preamble = value;
+		break;
+
+	case PRISM2_PARAM_STAT_TIME:
+		if (!local->stat_time && value) {
+			local->stat_timer.expires = jiffies + HZ * value / 100;
+			add_timer(&local->stat_timer);
+		} else if (local->stat_time && !value) {
+			del_timer_sync(&local->stat_timer);
+		}
+		local->stat_time = value;
+		break;
+	case PRISM2_PARAM_SHORT_SLOT_TIME:
+		if (value)
+			local->hw.conf.flags |= IEEE80211_CONF_SHORT_SLOT_TIME;
+		else
+			local->hw.conf.flags &= ~IEEE80211_CONF_SHORT_SLOT_TIME;
+		if (ieee80211_hw_config(local))
+			ret = -EINVAL;
+		break;
+
+	case PRISM2_PARAM_NEXT_MODE:
+		local->next_mode = value;
+		break;
+
+	case PRISM2_PARAM_CLEAR_KEYS:
+		ret = ieee80211_ioctl_clear_keys(dev);
+		break;
+
+	case PRISM2_PARAM_RADIO_ENABLED:
+		ret = ieee80211_ioctl_set_radio_enabled(dev, value);
+		break;
+
+	case PRISM2_PARAM_ANTENNA_MODE:
+		local->hw.conf.antenna_mode = value;
+		if (ieee80211_hw_config(local))
+			ret = -EINVAL;
+		break;
+
+	case PRISM2_PARAM_STA_ANTENNA_SEL:
+		local->sta_antenna_sel = value;
+		break;
+
+	case PRISM2_PARAM_FORCE_UNICAST_RATE:
+		ret = ieee80211_ioctl_force_unicast_rate(dev, sdata, value);
+		break;
+
+	case PRISM2_PARAM_MAX_RATECTRL_RATE:
+		ret = ieee80211_ioctl_max_ratectrl_rate(dev, sdata, value);
+		break;
+
+	case PRISM2_PARAM_RATE_CTRL_NUM_UP:
+		local->rate_ctrl_num_up = value;
+		break;
+
+	case PRISM2_PARAM_RATE_CTRL_NUM_DOWN:
+		local->rate_ctrl_num_down = value;
+		break;
+
+	case PRISM2_PARAM_TX_POWER_REDUCTION:
+		if (value < 0)
+			ret = -EINVAL;
+		else
+			local->hw.conf.tx_power_reduction = value;
+		break;
+
+	case PRISM2_PARAM_KEY_TX_RX_THRESHOLD:
+		local->key_tx_rx_threshold = value;
+		break;
+
+	case PRISM2_PARAM_DEFAULT_WEP_ONLY:
+		ret = ieee80211_ioctl_default_wep_only(local, value);
+		break;
+
+	case PRISM2_PARAM_WIFI_WME_NOACK_TEST:
+		local->wifi_wme_noack_test = value;
+		break;
+
+	case PRISM2_PARAM_SCAN_FLAGS:
+		local->scan_flags = value;
+		break;
+
+	case PRISM2_PARAM_MIXED_CELL:
+		if (sdata->type != IEEE80211_IF_TYPE_STA &&
+		    sdata->type != IEEE80211_IF_TYPE_IBSS)
+			ret = -EINVAL;
+		else
+			sdata->u.sta.mixed_cell = !!value;
+		break;
+
+	case PRISM2_PARAM_HW_MODES:
+		local->enabled_modes = value;
+		break;
+
+	case PRISM2_PARAM_CREATE_IBSS:
+		if (sdata->type != IEEE80211_IF_TYPE_IBSS)
+			ret = -EINVAL;
+		else
+			sdata->u.sta.create_ibss = !!value;
+		break;
+	case PRISM2_PARAM_WMM_ENABLED:
+		if (sdata->type != IEEE80211_IF_TYPE_STA &&
+		    sdata->type != IEEE80211_IF_TYPE_IBSS)
+			ret = -EINVAL;
+		else
+			sdata->u.sta.wmm_enabled = !!value;
+		break;
+	case PRISM2_PARAM_RADAR_DETECT:
+		local->hw.conf.radar_detect = value;
+		break;
+	case PRISM2_PARAM_SPECTRUM_MGMT:
+		local->hw.conf.spect_mgmt = value;
+		break;
+	default:
+		ret = -EOPNOTSUPP;
+		break;
+	}
+
+	return ret;
+}
+
+
+static int ieee80211_ioctl_get_prism2_param(struct net_device *dev,
+					    struct iw_request_info *info,
+					    void *wrqu, char *extra)
+{
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+	struct ieee80211_sub_if_data *sdata;
+	int *param = (int *) extra;
+	int ret = 0;
+
+	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+
+	switch (*param) {
+	case PRISM2_PARAM_IEEE_802_1X:
+		*param = sdata->ieee802_1x;
+		break;
+
+	case PRISM2_PARAM_ANTSEL_TX:
+		*param = local->hw.conf.antenna_sel_tx;
+		break;
+
+	case PRISM2_PARAM_ANTSEL_RX:
+		*param = local->hw.conf.antenna_sel_rx;
+		break;
+
+	case PRISM2_PARAM_CTS_PROTECT_ERP_FRAMES:
+		*param = local->cts_protect_erp_frames;
+		break;
+
+	case PRISM2_PARAM_DROP_UNENCRYPTED:
+		*param = sdata->drop_unencrypted;
+		break;
+
+	case PRISM2_PARAM_PREAMBLE:
+		*param = local->short_preamble;
+		break;
+
+	case PRISM2_PARAM_STAT_TIME:
+		*param = local->stat_time;
+		break;
+	case PRISM2_PARAM_SHORT_SLOT_TIME:
+		*param = !!(local->hw.conf.flags & IEEE80211_CONF_SHORT_SLOT_TIME);
+		break;
+
+	case PRISM2_PARAM_NEXT_MODE:
+		*param = local->next_mode;
+		break;
+
+	case PRISM2_PARAM_ANTENNA_MODE:
+		*param = local->hw.conf.antenna_mode;
+		break;
+
+	case PRISM2_PARAM_STA_ANTENNA_SEL:
+		*param = local->sta_antenna_sel;
+		break;
+
+	case PRISM2_PARAM_RATE_CTRL_NUM_UP:
+		*param = local->rate_ctrl_num_up;
+		break;
+
+	case PRISM2_PARAM_RATE_CTRL_NUM_DOWN:
+		*param = local->rate_ctrl_num_down;
+		break;
+
+	case PRISM2_PARAM_TX_POWER_REDUCTION:
+		*param = local->hw.conf.tx_power_reduction;
+		break;
+
+	case PRISM2_PARAM_KEY_TX_RX_THRESHOLD:
+		*param = local->key_tx_rx_threshold;
+		break;
+
+	case PRISM2_PARAM_DEFAULT_WEP_ONLY:
+		*param = local->default_wep_only;
+		break;
+
+	case PRISM2_PARAM_WIFI_WME_NOACK_TEST:
+		*param = local->wifi_wme_noack_test;
+		break;
+
+	case PRISM2_PARAM_SCAN_FLAGS:
+		*param = local->scan_flags;
+		break;
+
+	case PRISM2_PARAM_HW_MODES:
+		*param = local->enabled_modes;
+		break;
+
+	case PRISM2_PARAM_CREATE_IBSS:
+		if (sdata->type != IEEE80211_IF_TYPE_IBSS)
+			ret = -EINVAL;
+		else
+			*param = !!sdata->u.sta.create_ibss;
+		break;
+
+	case PRISM2_PARAM_MIXED_CELL:
+		if (sdata->type != IEEE80211_IF_TYPE_STA &&
+		    sdata->type != IEEE80211_IF_TYPE_IBSS)
+			ret = -EINVAL;
+		else
+			*param = !!sdata->u.sta.mixed_cell;
+		break;
+	case PRISM2_PARAM_WMM_ENABLED:
+		if (sdata->type != IEEE80211_IF_TYPE_STA &&
+		    sdata->type != IEEE80211_IF_TYPE_IBSS)
+			ret = -EINVAL;
+		else
+			*param = !!sdata->u.sta.wmm_enabled;
+		break;
+	default:
+		ret = -EOPNOTSUPP;
+		break;
+	}
+
+	return ret;
+}
+
+static int ieee80211_ioctl_siwmlme(struct net_device *dev,
+				   struct iw_request_info *info,
+				   struct iw_point *data, char *extra)
+{
+	struct ieee80211_sub_if_data *sdata;
+	struct iw_mlme *mlme = (struct iw_mlme *) extra;
+
+	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	if (sdata->type != IEEE80211_IF_TYPE_STA &&
+	    sdata->type != IEEE80211_IF_TYPE_IBSS)
+		return -EINVAL;
+
+	switch (mlme->cmd) {
+	case IW_MLME_DEAUTH:
+		/* TODO: mlme->addr.sa_data */
+		return ieee80211_sta_deauthenticate(dev, mlme->reason_code);
+	case IW_MLME_DISASSOC:
+		/* TODO: mlme->addr.sa_data */
+		return ieee80211_sta_disassociate(dev, mlme->reason_code);
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+
+static int ieee80211_ioctl_siwencode(struct net_device *dev,
+				     struct iw_request_info *info,
+				     struct iw_point *erq, char *keybuf)
+{
+	struct ieee80211_sub_if_data *sdata;
+	int idx, i, alg = ALG_WEP;
+	u8 bcaddr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+
+	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+
+	idx = erq->flags & IW_ENCODE_INDEX;
+	if (idx == 0) {
+		if (sdata->default_key)
+			for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
+				if (sdata->default_key == sdata->keys[i]) {
+					idx = i;
+					break;
+				}
+			}
+	} else if (idx < 1 || idx > 4)
+		return -EINVAL;
+	else
+		idx--;
+
+	if (erq->flags & IW_ENCODE_DISABLED)
+		alg = ALG_NONE;
+	else if (erq->length == 0) {
+		/* No key data - just set the default TX key index */
+		if (sdata->default_key != sdata->keys[idx]) {
+			ieee80211_debugfs_key_remove_default(sdata);
+			sdata->default_key = sdata->keys[idx];
+			if (sdata->default_key)
+				ieee80211_debugfs_key_add_default(sdata);
+		}
+		return 0;
+	}
+
+	return ieee80211_set_encryption(
+		dev, bcaddr,
+		idx, alg,
+		!sdata->default_key,
+		keybuf, erq->length);
+}
+
+
+static int ieee80211_ioctl_giwencode(struct net_device *dev,
+				     struct iw_request_info *info,
+				     struct iw_point *erq, char *key)
+{
+	struct ieee80211_sub_if_data *sdata;
+	int idx, i;
+
+	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+
+	idx = erq->flags & IW_ENCODE_INDEX;
+	if (idx < 1 || idx > 4) {
+		idx = -1;
+		if (!sdata->default_key)
+			idx = 0;
+		else for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
+			if (sdata->default_key == sdata->keys[i]) {
+				idx = i;
+				break;
+			}
+		}
+		if (idx < 0)
+			return -EINVAL;
+	} else
+		idx--;
+
+	erq->flags = idx + 1;
+
+	if (!sdata->keys[idx]) {
+		erq->length = 0;
+		erq->flags |= IW_ENCODE_DISABLED;
+		return 0;
+	}
+
+	memcpy(key, sdata->keys[idx]->key,
+	       min((int)erq->length, sdata->keys[idx]->keylen));
+	erq->length = sdata->keys[idx]->keylen;
+	erq->flags |= IW_ENCODE_ENABLED;
+
+	return 0;
+}
+
+static int ieee80211_ioctl_siwauth(struct net_device *dev,
+				   struct iw_request_info *info,
+				   struct iw_param *data, char *extra)
+{
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	int ret = 0;
+
+	switch (data->flags & IW_AUTH_INDEX) {
+	case IW_AUTH_WPA_VERSION:
+	case IW_AUTH_CIPHER_PAIRWISE:
+	case IW_AUTH_CIPHER_GROUP:
+	case IW_AUTH_WPA_ENABLED:
+	case IW_AUTH_RX_UNENCRYPTED_EAPOL:
+		break;
+	case IW_AUTH_KEY_MGMT:
+		if (sdata->type != IEEE80211_IF_TYPE_STA)
+			ret = -EINVAL;
+		else {
+			/*
+			 * TODO: sdata->u.sta.key_mgmt does not match with WE18
+			 * value completely; could consider modifying this to
+			 * be closer to WE18. For now, this value is not really
+			 * used for anything else than Privacy matching, so the
+			 * current code here should be more or less OK.
+			 */
+			if (data->value & IW_AUTH_KEY_MGMT_802_1X) {
+				sdata->u.sta.key_mgmt =
+					IEEE80211_KEY_MGMT_WPA_EAP;
+			} else if (data->value & IW_AUTH_KEY_MGMT_PSK) {
+				sdata->u.sta.key_mgmt =
+					IEEE80211_KEY_MGMT_WPA_PSK;
+			} else {
+				sdata->u.sta.key_mgmt =
+					IEEE80211_KEY_MGMT_NONE;
+			}
+		}
+		break;
+	case IW_AUTH_80211_AUTH_ALG:
+		if (sdata->type == IEEE80211_IF_TYPE_STA ||
+		    sdata->type == IEEE80211_IF_TYPE_IBSS)
+			sdata->u.sta.auth_algs = data->value;
+		else
+			ret = -EOPNOTSUPP;
+		break;
+	case IW_AUTH_PRIVACY_INVOKED:
+		if (local->ops->set_privacy_invoked)
+			ret = local->ops->set_privacy_invoked(
+					local_to_hw(local), data->value);
+		break;
+	default:
+		ret = -EOPNOTSUPP;
+		break;
+	}
+	return ret;
+}
+
+/* Get wireless statistics.  Called by /proc/net/wireless and by SIOCGIWSTATS */
+static struct iw_statistics *ieee80211_get_wireless_stats(struct net_device *dev)
+{
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+	struct iw_statistics *wstats = &local->wstats;
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	struct sta_info *sta = NULL;
+
+	if (sdata->type == IEEE80211_IF_TYPE_STA ||
+	    sdata->type == IEEE80211_IF_TYPE_IBSS)
+		sta = sta_info_get(local, sdata->u.sta.bssid);
+	if (!sta) {
+		wstats->discard.fragment = 0;
+		wstats->discard.misc = 0;
+		wstats->qual.qual = 0;
+		wstats->qual.level = 0;
+		wstats->qual.noise = 0;
+		wstats->qual.updated = IW_QUAL_ALL_INVALID;
+	} else {
+		wstats->qual.level = sta->last_rssi;
+		wstats->qual.qual = sta->last_signal;
+		wstats->qual.noise = sta->last_noise;
+		wstats->qual.updated = local->wstats_flags;
+		sta_info_put(sta);
+	}
+	return wstats;
+}
+
+static int ieee80211_ioctl_giwauth(struct net_device *dev,
+				   struct iw_request_info *info,
+				   struct iw_param *data, char *extra)
+{
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	int ret = 0;
+
+	switch (data->flags & IW_AUTH_INDEX) {
+	case IW_AUTH_80211_AUTH_ALG:
+		if (sdata->type == IEEE80211_IF_TYPE_STA ||
+		    sdata->type == IEEE80211_IF_TYPE_IBSS)
+			data->value = sdata->u.sta.auth_algs;
+		else
+			ret = -EOPNOTSUPP;
+		break;
+	default:
+		ret = -EOPNOTSUPP;
+		break;
+	}
+	return ret;
+}
+
+
+static int ieee80211_ioctl_siwencodeext(struct net_device *dev,
+					struct iw_request_info *info,
+					struct iw_point *erq, char *extra)
+{
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	struct iw_encode_ext *ext = (struct iw_encode_ext *) extra;
+	int alg, idx, i;
+
+	switch (ext->alg) {
+	case IW_ENCODE_ALG_NONE:
+		alg = ALG_NONE;
+		break;
+	case IW_ENCODE_ALG_WEP:
+		alg = ALG_WEP;
+		break;
+	case IW_ENCODE_ALG_TKIP:
+		alg = ALG_TKIP;
+		break;
+	case IW_ENCODE_ALG_CCMP:
+		alg = ALG_CCMP;
+		break;
+	default:
+		return -EOPNOTSUPP;
+	}
+
+	if (erq->flags & IW_ENCODE_DISABLED)
+		alg = ALG_NONE;
+
+	idx = erq->flags & IW_ENCODE_INDEX;
+	if (idx < 1 || idx > 4) {
+		idx = -1;
+		if (!sdata->default_key)
+			idx = 0;
+		else for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
+			if (sdata->default_key == sdata->keys[i]) {
+				idx = i;
+				break;
+			}
+		}
+		if (idx < 0)
+			return -EINVAL;
+	} else
+		idx--;
+
+	return ieee80211_set_encryption(dev, ext->addr.sa_data, idx, alg,
+					ext->ext_flags &
+					IW_ENCODE_EXT_SET_TX_KEY,
+					ext->key, ext->key_len);
+}
+
+
+static const struct iw_priv_args ieee80211_ioctl_priv[] = {
+	{ PRISM2_IOCTL_PRISM2_PARAM,
+	  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "param" },
+	{ PRISM2_IOCTL_GET_PRISM2_PARAM,
+	  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+	  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_param" },
+};
+
+/* Structures to export the Wireless Handlers */
+
+static const iw_handler ieee80211_handler[] =
+{
+	(iw_handler) NULL,				/* SIOCSIWCOMMIT */
+	(iw_handler) ieee80211_ioctl_giwname,		/* SIOCGIWNAME */
+	(iw_handler) NULL,				/* SIOCSIWNWID */
+	(iw_handler) NULL,				/* SIOCGIWNWID */
+	(iw_handler) ieee80211_ioctl_siwfreq,		/* SIOCSIWFREQ */
+	(iw_handler) ieee80211_ioctl_giwfreq,		/* SIOCGIWFREQ */
+	(iw_handler) ieee80211_ioctl_siwmode,		/* SIOCSIWMODE */
+	(iw_handler) ieee80211_ioctl_giwmode,		/* SIOCGIWMODE */
+	(iw_handler) NULL,				/* SIOCSIWSENS */
+	(iw_handler) NULL,				/* SIOCGIWSENS */
+	(iw_handler) NULL /* not used */,		/* SIOCSIWRANGE */
+	(iw_handler) ieee80211_ioctl_giwrange,		/* SIOCGIWRANGE */
+	(iw_handler) NULL /* not used */,		/* SIOCSIWPRIV */
+	(iw_handler) NULL /* kernel code */,		/* SIOCGIWPRIV */
+	(iw_handler) NULL /* not used */,		/* SIOCSIWSTATS */
+	(iw_handler) NULL /* kernel code */,		/* SIOCGIWSTATS */
+	iw_handler_set_spy,				/* SIOCSIWSPY */
+	iw_handler_get_spy,				/* SIOCGIWSPY */
+	iw_handler_set_thrspy,				/* SIOCSIWTHRSPY */
+	iw_handler_get_thrspy,				/* SIOCGIWTHRSPY */
+	(iw_handler) ieee80211_ioctl_siwap,		/* SIOCSIWAP */
+	(iw_handler) ieee80211_ioctl_giwap,		/* SIOCGIWAP */
+	(iw_handler) ieee80211_ioctl_siwmlme,		/* SIOCSIWMLME */
+	(iw_handler) NULL,				/* SIOCGIWAPLIST */
+	(iw_handler) ieee80211_ioctl_siwscan,		/* SIOCSIWSCAN */
+	(iw_handler) ieee80211_ioctl_giwscan,		/* SIOCGIWSCAN */
+	(iw_handler) ieee80211_ioctl_siwessid,		/* SIOCSIWESSID */
+	(iw_handler) ieee80211_ioctl_giwessid,		/* SIOCGIWESSID */
+	(iw_handler) NULL,				/* SIOCSIWNICKN */
+	(iw_handler) NULL,				/* SIOCGIWNICKN */
+	(iw_handler) NULL,				/* -- hole -- */
+	(iw_handler) NULL,				/* -- hole -- */
+	(iw_handler) NULL,				/* SIOCSIWRATE */
+	(iw_handler) NULL,				/* SIOCGIWRATE */
+	(iw_handler) ieee80211_ioctl_siwrts,		/* SIOCSIWRTS */
+	(iw_handler) ieee80211_ioctl_giwrts,		/* SIOCGIWRTS */
+	(iw_handler) ieee80211_ioctl_siwfrag,		/* SIOCSIWFRAG */
+	(iw_handler) ieee80211_ioctl_giwfrag,		/* SIOCGIWFRAG */
+	(iw_handler) NULL,				/* SIOCSIWTXPOW */
+	(iw_handler) NULL,				/* SIOCGIWTXPOW */
+	(iw_handler) ieee80211_ioctl_siwretry,		/* SIOCSIWRETRY */
+	(iw_handler) ieee80211_ioctl_giwretry,		/* SIOCGIWRETRY */
+	(iw_handler) ieee80211_ioctl_siwencode,		/* SIOCSIWENCODE */
+	(iw_handler) ieee80211_ioctl_giwencode,		/* SIOCGIWENCODE */
+	(iw_handler) NULL,				/* SIOCSIWPOWER */
+	(iw_handler) NULL,				/* SIOCGIWPOWER */
+	(iw_handler) NULL,				/* -- hole -- */
+	(iw_handler) NULL,				/* -- hole -- */
+	(iw_handler) ieee80211_ioctl_siwgenie,		/* SIOCSIWGENIE */
+	(iw_handler) NULL,				/* SIOCGIWGENIE */
+	(iw_handler) ieee80211_ioctl_siwauth,		/* SIOCSIWAUTH */
+	(iw_handler) ieee80211_ioctl_giwauth,		/* SIOCGIWAUTH */
+	(iw_handler) ieee80211_ioctl_siwencodeext,	/* SIOCSIWENCODEEXT */
+	(iw_handler) NULL,				/* SIOCGIWENCODEEXT */
+	(iw_handler) NULL,				/* SIOCSIWPMKSA */
+	(iw_handler) NULL,				/* -- hole -- */
+};
+
+static const iw_handler ieee80211_private_handler[] =
+{							/* SIOCIWFIRSTPRIV + */
+	(iw_handler) ieee80211_ioctl_prism2_param,	/* 0 */
+	(iw_handler) ieee80211_ioctl_get_prism2_param,	/* 1 */
+};
+
+const struct iw_handler_def ieee80211_iw_handler_def =
+{
+	.num_standard	= ARRAY_SIZE(ieee80211_handler),
+	.num_private	= ARRAY_SIZE(ieee80211_private_handler),
+	.num_private_args = ARRAY_SIZE(ieee80211_ioctl_priv),
+	.standard	= (iw_handler *) ieee80211_handler,
+	.private	= (iw_handler *) ieee80211_private_handler,
+	.private_args	= (struct iw_priv_args *) ieee80211_ioctl_priv,
+	.get_wireless_stats = ieee80211_get_wireless_stats,
+};
diff --git a/net/mac80211/ieee80211_key.h b/net/mac80211/ieee80211_key.h
new file mode 100644
index 0000000..c333849
--- /dev/null
+++ b/net/mac80211/ieee80211_key.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2002-2004, Instant802 Networks, Inc.
+ * Copyright 2005, Devicescape Software, Inc.
+ *
+ * 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 IEEE80211_KEY_H
+#define IEEE80211_KEY_H
+
+#include <linux/types.h>
+#include <linux/kref.h>
+#include <linux/crypto.h>
+#include <net/mac80211.h>
+
+/* ALG_TKIP
+ * struct ieee80211_key::key is encoded as a 256-bit (32 byte) data block:
+ * Temporal Encryption Key (128 bits)
+ * Temporal Authenticator Tx MIC Key (64 bits)
+ * Temporal Authenticator Rx MIC Key (64 bits)
+ */
+
+#define WEP_IV_LEN 4
+#define WEP_ICV_LEN 4
+
+#define ALG_TKIP_KEY_LEN 32
+/* Starting offsets for each key */
+#define ALG_TKIP_TEMP_ENCR_KEY 0
+#define ALG_TKIP_TEMP_AUTH_TX_MIC_KEY 16
+#define ALG_TKIP_TEMP_AUTH_RX_MIC_KEY 24
+#define TKIP_IV_LEN 8
+#define TKIP_ICV_LEN 4
+
+#define ALG_CCMP_KEY_LEN 16
+#define CCMP_HDR_LEN 8
+#define CCMP_MIC_LEN 8
+#define CCMP_TK_LEN 16
+#define CCMP_PN_LEN 6
+
+#define NUM_RX_DATA_QUEUES 17
+
+struct ieee80211_key {
+	struct kref kref;
+
+	int hw_key_idx; /* filled and used by low-level driver */
+	ieee80211_key_alg alg;
+	union {
+		struct {
+			/* last used TSC */
+			u32 iv32;
+			u16 iv16;
+			u16 p1k[5];
+			int tx_initialized;
+
+			/* last received RSC */
+			u32 iv32_rx[NUM_RX_DATA_QUEUES];
+			u16 iv16_rx[NUM_RX_DATA_QUEUES];
+			u16 p1k_rx[NUM_RX_DATA_QUEUES][5];
+			int rx_initialized[NUM_RX_DATA_QUEUES];
+		} tkip;
+		struct {
+			u8 tx_pn[6];
+			u8 rx_pn[NUM_RX_DATA_QUEUES][6];
+			struct crypto_cipher *tfm;
+			u32 replays; /* dot11RSNAStatsCCMPReplays */
+			/* scratch buffers for virt_to_page() (crypto API) */
+#ifndef AES_BLOCK_LEN
+#define AES_BLOCK_LEN 16
+#endif
+			u8 tx_crypto_buf[6 * AES_BLOCK_LEN];
+			u8 rx_crypto_buf[6 * AES_BLOCK_LEN];
+		} ccmp;
+	} u;
+	int tx_rx_count; /* number of times this key has been used */
+	int keylen;
+
+	/* if the low level driver can provide hardware acceleration it should
+	 * clear this flag */
+	unsigned int force_sw_encrypt:1;
+	unsigned int default_tx_key:1; /* This key is the new default TX key
+					* (used only for broadcast keys). */
+	s8 keyidx; /* WEP key index */
+
+#ifdef CONFIG_MAC80211_DEBUGFS
+	struct {
+		struct dentry *stalink;
+		struct dentry *dir;
+		struct dentry *keylen;
+		struct dentry *force_sw_encrypt;
+		struct dentry *keyidx;
+		struct dentry *hw_key_idx;
+		struct dentry *tx_rx_count;
+		struct dentry *algorithm;
+		struct dentry *tx_spec;
+		struct dentry *rx_spec;
+		struct dentry *replays;
+		struct dentry *key;
+	} debugfs;
+#endif
+
+	u8 key[0];
+};
+
+#endif /* IEEE80211_KEY_H */
diff --git a/net/mac80211/ieee80211_led.c b/net/mac80211/ieee80211_led.c
new file mode 100644
index 0000000..719d75b
--- /dev/null
+++ b/net/mac80211/ieee80211_led.c
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2006, Johannes Berg <johannes@sipsolutions.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/* just for IFNAMSIZ */
+#include <linux/if.h>
+#include "ieee80211_led.h"
+
+void ieee80211_led_rx(struct ieee80211_local *local)
+{
+	if (unlikely(!local->rx_led))
+		return;
+	if (local->rx_led_counter++ % 2 == 0)
+		led_trigger_event(local->rx_led, LED_OFF);
+	else
+		led_trigger_event(local->rx_led, LED_FULL);
+}
+
+/* q is 1 if a packet was enqueued, 0 if it has been transmitted */
+void ieee80211_led_tx(struct ieee80211_local *local, int q)
+{
+	if (unlikely(!local->tx_led))
+		return;
+	/* not sure how this is supposed to work ... */
+	local->tx_led_counter += 2*q-1;
+	if (local->tx_led_counter % 2 == 0)
+		led_trigger_event(local->tx_led, LED_OFF);
+	else
+		led_trigger_event(local->tx_led, LED_FULL);
+}
+
+void ieee80211_led_init(struct ieee80211_local *local)
+{
+	local->rx_led = kzalloc(sizeof(struct led_trigger), GFP_KERNEL);
+	if (!local->rx_led)
+		return;
+	snprintf(local->rx_led_name, sizeof(local->rx_led_name),
+		 "%srx", wiphy_name(local->hw.wiphy));
+	local->rx_led->name = local->rx_led_name;
+	if (led_trigger_register(local->rx_led)) {
+		kfree(local->rx_led);
+		local->rx_led = NULL;
+	}
+
+	local->tx_led = kzalloc(sizeof(struct led_trigger), GFP_KERNEL);
+	if (!local->tx_led)
+		return;
+	snprintf(local->tx_led_name, sizeof(local->tx_led_name),
+		 "%stx", wiphy_name(local->hw.wiphy));
+	local->tx_led->name = local->tx_led_name;
+	if (led_trigger_register(local->tx_led)) {
+		kfree(local->tx_led);
+		local->tx_led = NULL;
+	}
+}
+
+void ieee80211_led_exit(struct ieee80211_local *local)
+{
+	if (local->tx_led) {
+		led_trigger_unregister(local->tx_led);
+		kfree(local->tx_led);
+	}
+	if (local->rx_led) {
+		led_trigger_unregister(local->rx_led);
+		kfree(local->rx_led);
+	}
+}
+
+char *__ieee80211_get_tx_led_name(struct ieee80211_hw *hw)
+{
+	struct ieee80211_local *local = hw_to_local(hw);
+
+	if (local->tx_led)
+		return local->tx_led_name;
+	return NULL;
+}
+EXPORT_SYMBOL(__ieee80211_get_tx_led_name);
+
+char *__ieee80211_get_rx_led_name(struct ieee80211_hw *hw)
+{
+	struct ieee80211_local *local = hw_to_local(hw);
+
+	if (local->rx_led)
+		return local->rx_led_name;
+	return NULL;
+}
+EXPORT_SYMBOL(__ieee80211_get_rx_led_name);
diff --git a/net/mac80211/ieee80211_led.h b/net/mac80211/ieee80211_led.h
new file mode 100644
index 0000000..5c8ab82
--- /dev/null
+++ b/net/mac80211/ieee80211_led.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2006, Johannes Berg <johannes@sipsolutions.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/leds.h>
+#include "ieee80211_i.h"
+
+#ifdef CONFIG_MAC80211_LEDS
+extern void ieee80211_led_rx(struct ieee80211_local *local);
+extern void ieee80211_led_tx(struct ieee80211_local *local, int q);
+extern void ieee80211_led_init(struct ieee80211_local *local);
+extern void ieee80211_led_exit(struct ieee80211_local *local);
+#else
+static inline void ieee80211_led_rx(struct ieee80211_local *local)
+{
+}
+static inline void ieee80211_led_tx(struct ieee80211_local *local, int q)
+{
+}
+static inline void ieee80211_led_init(struct ieee80211_local *local)
+{
+}
+static inline void ieee80211_led_exit(struct ieee80211_local *local)
+{
+}
+#endif
diff --git a/net/mac80211/ieee80211_rate.c b/net/mac80211/ieee80211_rate.c
new file mode 100644
index 0000000..16e8508
--- /dev/null
+++ b/net/mac80211/ieee80211_rate.c
@@ -0,0 +1,140 @@
+/*
+ * Copyright 2002-2005, Instant802 Networks, Inc.
+ * Copyright 2005-2006, Devicescape Software, Inc.
+ * Copyright (c) 2006 Jiri Benc <jbenc@suse.cz>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include "ieee80211_rate.h"
+#include "ieee80211_i.h"
+
+struct rate_control_alg {
+	struct list_head list;
+	struct rate_control_ops *ops;
+};
+
+static LIST_HEAD(rate_ctrl_algs);
+static DEFINE_MUTEX(rate_ctrl_mutex);
+
+int ieee80211_rate_control_register(struct rate_control_ops *ops)
+{
+	struct rate_control_alg *alg;
+
+	alg = kmalloc(sizeof(*alg), GFP_KERNEL);
+	if (alg == NULL) {
+		return -ENOMEM;
+	}
+	memset(alg, 0, sizeof(*alg));
+	alg->ops = ops;
+
+	mutex_lock(&rate_ctrl_mutex);
+	list_add_tail(&alg->list, &rate_ctrl_algs);
+	mutex_unlock(&rate_ctrl_mutex);
+
+	return 0;
+}
+EXPORT_SYMBOL(ieee80211_rate_control_register);
+
+void ieee80211_rate_control_unregister(struct rate_control_ops *ops)
+{
+	struct rate_control_alg *alg;
+
+	mutex_lock(&rate_ctrl_mutex);
+	list_for_each_entry(alg, &rate_ctrl_algs, list) {
+		if (alg->ops == ops) {
+			list_del(&alg->list);
+			break;
+		}
+	}
+	mutex_unlock(&rate_ctrl_mutex);
+	kfree(alg);
+}
+EXPORT_SYMBOL(ieee80211_rate_control_unregister);
+
+static struct rate_control_ops *
+ieee80211_try_rate_control_ops_get(const char *name)
+{
+	struct rate_control_alg *alg;
+	struct rate_control_ops *ops = NULL;
+
+	mutex_lock(&rate_ctrl_mutex);
+	list_for_each_entry(alg, &rate_ctrl_algs, list) {
+		if (!name || !strcmp(alg->ops->name, name))
+			if (try_module_get(alg->ops->module)) {
+				ops = alg->ops;
+				break;
+			}
+	}
+	mutex_unlock(&rate_ctrl_mutex);
+	return ops;
+}
+
+/* Get the rate control algorithm. If `name' is NULL, get the first
+ * available algorithm. */
+static struct rate_control_ops *
+ieee80211_rate_control_ops_get(const char *name)
+{
+	struct rate_control_ops *ops;
+
+	ops = ieee80211_try_rate_control_ops_get(name);
+	if (!ops) {
+		request_module("rc80211_%s", name ? name : "default");
+		ops = ieee80211_try_rate_control_ops_get(name);
+	}
+	return ops;
+}
+
+static void ieee80211_rate_control_ops_put(struct rate_control_ops *ops)
+{
+	module_put(ops->module);
+}
+
+struct rate_control_ref *rate_control_alloc(const char *name,
+					    struct ieee80211_local *local)
+{
+	struct rate_control_ref *ref;
+
+	ref = kmalloc(sizeof(struct rate_control_ref), GFP_KERNEL);
+	if (!ref)
+		goto fail_ref;
+	kref_init(&ref->kref);
+	ref->ops = ieee80211_rate_control_ops_get(name);
+	if (!ref->ops)
+		goto fail_ops;
+	ref->priv = ref->ops->alloc(local);
+	if (!ref->priv)
+		goto fail_priv;
+	return ref;
+
+fail_priv:
+	ieee80211_rate_control_ops_put(ref->ops);
+fail_ops:
+	kfree(ref);
+fail_ref:
+	return NULL;
+}
+
+static void rate_control_release(struct kref *kref)
+{
+	struct rate_control_ref *ctrl_ref;
+
+	ctrl_ref = container_of(kref, struct rate_control_ref, kref);
+	ctrl_ref->ops->free(ctrl_ref->priv);
+	ieee80211_rate_control_ops_put(ctrl_ref->ops);
+	kfree(ctrl_ref);
+}
+
+struct rate_control_ref *rate_control_get(struct rate_control_ref *ref)
+{
+	kref_get(&ref->kref);
+	return ref;
+}
+
+void rate_control_put(struct rate_control_ref *ref)
+{
+	kref_put(&ref->kref, rate_control_release);
+}
diff --git a/net/mac80211/ieee80211_rate.h b/net/mac80211/ieee80211_rate.h
new file mode 100644
index 0000000..f021a02
--- /dev/null
+++ b/net/mac80211/ieee80211_rate.h
@@ -0,0 +1,144 @@
+/*
+ * Copyright 2002-2005, Instant802 Networks, Inc.
+ * Copyright 2005, Devicescape Software, Inc.
+ * Copyright (c) 2006 Jiri Benc <jbenc@suse.cz>
+ *
+ * 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 IEEE80211_RATE_H
+#define IEEE80211_RATE_H
+
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/types.h>
+#include <net/mac80211.h>
+#include "ieee80211_i.h"
+#include "sta_info.h"
+
+#define RATE_CONTROL_NUM_DOWN 20
+#define RATE_CONTROL_NUM_UP   15
+
+
+struct rate_control_extra {
+	/* values from rate_control_get_rate() to the caller: */
+	struct ieee80211_rate *probe; /* probe with this rate, or NULL for no
+				       * probing */
+	struct ieee80211_rate *nonerp;
+
+	/* parameters from the caller to rate_control_get_rate(): */
+	struct ieee80211_hw_mode *mode;
+	int mgmt_data; /* this is data frame that is used for management
+			* (e.g., IEEE 802.1X EAPOL) */
+	u16 ethertype;
+};
+
+
+struct rate_control_ops {
+	struct module *module;
+	const char *name;
+	void (*tx_status)(void *priv, struct net_device *dev,
+			  struct sk_buff *skb,
+			  struct ieee80211_tx_status *status);
+	struct ieee80211_rate *(*get_rate)(void *priv, struct net_device *dev,
+					   struct sk_buff *skb,
+					   struct rate_control_extra *extra);
+	void (*rate_init)(void *priv, void *priv_sta,
+			  struct ieee80211_local *local, struct sta_info *sta);
+	void (*clear)(void *priv);
+
+	void *(*alloc)(struct ieee80211_local *local);
+	void (*free)(void *priv);
+	void *(*alloc_sta)(void *priv, gfp_t gfp);
+	void (*free_sta)(void *priv, void *priv_sta);
+
+	int (*add_attrs)(void *priv, struct kobject *kobj);
+	void (*remove_attrs)(void *priv, struct kobject *kobj);
+	void (*add_sta_debugfs)(void *priv, void *priv_sta,
+				struct dentry *dir);
+	void (*remove_sta_debugfs)(void *priv, void *priv_sta);
+};
+
+struct rate_control_ref {
+	struct rate_control_ops *ops;
+	void *priv;
+	struct kref kref;
+};
+
+int ieee80211_rate_control_register(struct rate_control_ops *ops);
+void ieee80211_rate_control_unregister(struct rate_control_ops *ops);
+
+/* Get a reference to the rate control algorithm. If `name' is NULL, get the
+ * first available algorithm. */
+struct rate_control_ref *rate_control_alloc(const char *name,
+					    struct ieee80211_local *local);
+struct rate_control_ref *rate_control_get(struct rate_control_ref *ref);
+void rate_control_put(struct rate_control_ref *ref);
+
+static inline void rate_control_tx_status(struct ieee80211_local *local,
+					  struct net_device *dev,
+					  struct sk_buff *skb,
+					  struct ieee80211_tx_status *status)
+{
+	struct rate_control_ref *ref = local->rate_ctrl;
+	ref->ops->tx_status(ref->priv, dev, skb, status);
+}
+
+
+static inline struct ieee80211_rate *
+rate_control_get_rate(struct ieee80211_local *local, struct net_device *dev,
+		      struct sk_buff *skb, struct rate_control_extra *extra)
+{
+	struct rate_control_ref *ref = local->rate_ctrl;
+	return ref->ops->get_rate(ref->priv, dev, skb, extra);
+}
+
+
+static inline void rate_control_rate_init(struct sta_info *sta,
+					  struct ieee80211_local *local)
+{
+	struct rate_control_ref *ref = sta->rate_ctrl;
+	ref->ops->rate_init(ref->priv, sta->rate_ctrl_priv, local, sta);
+}
+
+
+static inline void rate_control_clear(struct ieee80211_local *local)
+{
+	struct rate_control_ref *ref = local->rate_ctrl;
+	ref->ops->clear(ref->priv);
+}
+
+static inline void *rate_control_alloc_sta(struct rate_control_ref *ref,
+					   gfp_t gfp)
+{
+	return ref->ops->alloc_sta(ref->priv, gfp);
+}
+
+static inline void rate_control_free_sta(struct rate_control_ref *ref,
+					 void *priv)
+{
+	ref->ops->free_sta(ref->priv, priv);
+}
+
+static inline void rate_control_add_sta_debugfs(struct sta_info *sta)
+{
+#ifdef CONFIG_MAC80211_DEBUGFS
+	struct rate_control_ref *ref = sta->rate_ctrl;
+	if (sta->debugfs.dir && ref->ops->add_sta_debugfs)
+		ref->ops->add_sta_debugfs(ref->priv, sta->rate_ctrl_priv,
+					  sta->debugfs.dir);
+#endif
+}
+
+static inline void rate_control_remove_sta_debugfs(struct sta_info *sta)
+{
+#ifdef CONFIG_MAC80211_DEBUGFS
+	struct rate_control_ref *ref = sta->rate_ctrl;
+	if (ref->ops->remove_sta_debugfs)
+		ref->ops->remove_sta_debugfs(ref->priv, sta->rate_ctrl_priv);
+#endif
+}
+
+#endif /* IEEE80211_RATE_H */
diff --git a/net/mac80211/ieee80211_sta.c b/net/mac80211/ieee80211_sta.c
new file mode 100644
index 0000000..822917d
--- /dev/null
+++ b/net/mac80211/ieee80211_sta.c
@@ -0,0 +1,3060 @@
+/*
+ * BSS client mode implementation
+ * Copyright 2003, Jouni Malinen <jkmaline@cc.hut.fi>
+ * Copyright 2004, Instant802 Networks, Inc.
+ * Copyright 2005, Devicescape Software, Inc.
+ * Copyright 2006-2007	Jiri Benc <jbenc@suse.cz>
+ * Copyright 2007, Michael Wu <flamingice@sourmilk.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/* TODO:
+ * BSS table: use <BSSID,SSID> as the key to support multi-SSID APs
+ * order BSS list by RSSI(?) ("quality of AP")
+ * scan result table filtering (by capability (privacy, IBSS/BSS, WPA/RSN IE,
+ *    SSID)
+ */
+#include <linux/if_ether.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/if_arp.h>
+#include <linux/wireless.h>
+#include <linux/random.h>
+#include <linux/etherdevice.h>
+#include <linux/rtnetlink.h>
+#include <net/iw_handler.h>
+#include <asm/types.h>
+#include <asm/delay.h>
+
+#include <net/mac80211.h>
+#include "ieee80211_i.h"
+#include "ieee80211_rate.h"
+#include "hostapd_ioctl.h"
+
+#define IEEE80211_AUTH_TIMEOUT (HZ / 5)
+#define IEEE80211_AUTH_MAX_TRIES 3
+#define IEEE80211_ASSOC_TIMEOUT (HZ / 5)
+#define IEEE80211_ASSOC_MAX_TRIES 3
+#define IEEE80211_MONITORING_INTERVAL (2 * HZ)
+#define IEEE80211_PROBE_INTERVAL (60 * HZ)
+#define IEEE80211_RETRY_AUTH_INTERVAL (1 * HZ)
+#define IEEE80211_SCAN_INTERVAL (2 * HZ)
+#define IEEE80211_SCAN_INTERVAL_SLOW (15 * HZ)
+#define IEEE80211_IBSS_JOIN_TIMEOUT (20 * HZ)
+
+#define IEEE80211_PROBE_DELAY (HZ / 33)
+#define IEEE80211_CHANNEL_TIME (HZ / 33)
+#define IEEE80211_PASSIVE_CHANNEL_TIME (HZ / 5)
+#define IEEE80211_SCAN_RESULT_EXPIRE (10 * HZ)
+#define IEEE80211_IBSS_MERGE_INTERVAL (30 * HZ)
+#define IEEE80211_IBSS_INACTIVITY_LIMIT (60 * HZ)
+
+#define IEEE80211_IBSS_MAX_STA_ENTRIES 128
+
+
+#define IEEE80211_FC(type, stype) cpu_to_le16(type | stype)
+
+#define ERP_INFO_USE_PROTECTION BIT(1)
+
+static void ieee80211_send_probe_req(struct net_device *dev, u8 *dst,
+				     u8 *ssid, size_t ssid_len);
+static struct ieee80211_sta_bss *
+ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid);
+static void ieee80211_rx_bss_put(struct net_device *dev,
+				 struct ieee80211_sta_bss *bss);
+static int ieee80211_sta_find_ibss(struct net_device *dev,
+				   struct ieee80211_if_sta *ifsta);
+static int ieee80211_sta_wep_configured(struct net_device *dev);
+static int ieee80211_sta_start_scan(struct net_device *dev,
+				    u8 *ssid, size_t ssid_len);
+static int ieee80211_sta_config_auth(struct net_device *dev,
+				     struct ieee80211_if_sta *ifsta);
+
+
+/* Parsed Information Elements */
+struct ieee802_11_elems {
+	u8 *ssid;
+	u8 ssid_len;
+	u8 *supp_rates;
+	u8 supp_rates_len;
+	u8 *fh_params;
+	u8 fh_params_len;
+	u8 *ds_params;
+	u8 ds_params_len;
+	u8 *cf_params;
+	u8 cf_params_len;
+	u8 *tim;
+	u8 tim_len;
+	u8 *ibss_params;
+	u8 ibss_params_len;
+	u8 *challenge;
+	u8 challenge_len;
+	u8 *wpa;
+	u8 wpa_len;
+	u8 *rsn;
+	u8 rsn_len;
+	u8 *erp_info;
+	u8 erp_info_len;
+	u8 *ext_supp_rates;
+	u8 ext_supp_rates_len;
+	u8 *wmm_info;
+	u8 wmm_info_len;
+	u8 *wmm_param;
+	u8 wmm_param_len;
+};
+
+typedef enum { ParseOK = 0, ParseUnknown = 1, ParseFailed = -1 } ParseRes;
+
+
+static ParseRes ieee802_11_parse_elems(u8 *start, size_t len,
+				       struct ieee802_11_elems *elems)
+{
+	size_t left = len;
+	u8 *pos = start;
+	int unknown = 0;
+
+	memset(elems, 0, sizeof(*elems));
+
+	while (left >= 2) {
+		u8 id, elen;
+
+		id = *pos++;
+		elen = *pos++;
+		left -= 2;
+
+		if (elen > left) {
+#if 0
+			if (net_ratelimit())
+				printk(KERN_DEBUG "IEEE 802.11 element parse "
+				       "failed (id=%d elen=%d left=%d)\n",
+				       id, elen, left);
+#endif
+			return ParseFailed;
+		}
+
+		switch (id) {
+		case WLAN_EID_SSID:
+			elems->ssid = pos;
+			elems->ssid_len = elen;
+			break;
+		case WLAN_EID_SUPP_RATES:
+			elems->supp_rates = pos;
+			elems->supp_rates_len = elen;
+			break;
+		case WLAN_EID_FH_PARAMS:
+			elems->fh_params = pos;
+			elems->fh_params_len = elen;
+			break;
+		case WLAN_EID_DS_PARAMS:
+			elems->ds_params = pos;
+			elems->ds_params_len = elen;
+			break;
+		case WLAN_EID_CF_PARAMS:
+			elems->cf_params = pos;
+			elems->cf_params_len = elen;
+			break;
+		case WLAN_EID_TIM:
+			elems->tim = pos;
+			elems->tim_len = elen;
+			break;
+		case WLAN_EID_IBSS_PARAMS:
+			elems->ibss_params = pos;
+			elems->ibss_params_len = elen;
+			break;
+		case WLAN_EID_CHALLENGE:
+			elems->challenge = pos;
+			elems->challenge_len = elen;
+			break;
+		case WLAN_EID_WPA:
+			if (elen >= 4 && pos[0] == 0x00 && pos[1] == 0x50 &&
+			    pos[2] == 0xf2) {
+				/* Microsoft OUI (00:50:F2) */
+				if (pos[3] == 1) {
+					/* OUI Type 1 - WPA IE */
+					elems->wpa = pos;
+					elems->wpa_len = elen;
+				} else if (elen >= 5 && pos[3] == 2) {
+					if (pos[4] == 0) {
+						elems->wmm_info = pos;
+						elems->wmm_info_len = elen;
+					} else if (pos[4] == 1) {
+						elems->wmm_param = pos;
+						elems->wmm_param_len = elen;
+					}
+				}
+			}
+			break;
+		case WLAN_EID_RSN:
+			elems->rsn = pos;
+			elems->rsn_len = elen;
+			break;
+		case WLAN_EID_ERP_INFO:
+			elems->erp_info = pos;
+			elems->erp_info_len = elen;
+			break;
+		case WLAN_EID_EXT_SUPP_RATES:
+			elems->ext_supp_rates = pos;
+			elems->ext_supp_rates_len = elen;
+			break;
+		default:
+#if 0
+			printk(KERN_DEBUG "IEEE 802.11 element parse ignored "
+				      "unknown element (id=%d elen=%d)\n",
+				      id, elen);
+#endif
+			unknown++;
+			break;
+		}
+
+		left -= elen;
+		pos += elen;
+	}
+
+	/* Do not trigger error if left == 1 as Apple Airport base stations
+	 * send AssocResps that are one spurious byte too long. */
+
+	return unknown ? ParseUnknown : ParseOK;
+}
+
+
+
+
+static int ecw2cw(int ecw)
+{
+	int cw = 1;
+	while (ecw > 0) {
+		cw <<= 1;
+		ecw--;
+	}
+	return cw - 1;
+}
+
+
+static void ieee80211_sta_wmm_params(struct net_device *dev,
+				     struct ieee80211_if_sta *ifsta,
+				     u8 *wmm_param, size_t wmm_param_len)
+{
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+	struct ieee80211_tx_queue_params params;
+	size_t left;
+	int count;
+	u8 *pos;
+
+	if (wmm_param_len < 8 || wmm_param[5] /* version */ != 1)
+		return;
+	count = wmm_param[6] & 0x0f;
+	if (count == ifsta->wmm_last_param_set)
+		return;
+	ifsta->wmm_last_param_set = count;
+
+	pos = wmm_param + 8;
+	left = wmm_param_len - 8;
+
+	memset(&params, 0, sizeof(params));
+
+	if (!local->ops->conf_tx)
+		return;
+
+	local->wmm_acm = 0;
+	for (; left >= 4; left -= 4, pos += 4) {
+		int aci = (pos[0] >> 5) & 0x03;
+		int acm = (pos[0] >> 4) & 0x01;
+		int queue;
+
+		switch (aci) {
+		case 1:
+			queue = IEEE80211_TX_QUEUE_DATA3;
+			if (acm) {
+				local->wmm_acm |= BIT(0) | BIT(3);
+			}
+			break;
+		case 2:
+			queue = IEEE80211_TX_QUEUE_DATA1;
+			if (acm) {
+				local->wmm_acm |= BIT(4) | BIT(5);
+			}
+			break;
+		case 3:
+			queue = IEEE80211_TX_QUEUE_DATA0;
+			if (acm) {
+				local->wmm_acm |= BIT(6) | BIT(7);
+			}
+			break;
+		case 0:
+		default:
+			queue = IEEE80211_TX_QUEUE_DATA2;
+			if (acm) {
+				local->wmm_acm |= BIT(1) | BIT(2);
+			}
+			break;
+		}
+
+		params.aifs = pos[0] & 0x0f;
+		params.cw_max = ecw2cw((pos[1] & 0xf0) >> 4);
+		params.cw_min = ecw2cw(pos[1] & 0x0f);
+		/* TXOP is in units of 32 usec; burst_time in 0.1 ms */
+		params.burst_time = (pos[2] | (pos[3] << 8)) * 32 / 100;
+		printk(KERN_DEBUG "%s: WMM queue=%d aci=%d acm=%d aifs=%d "
+		       "cWmin=%d cWmax=%d burst=%d\n",
+		       dev->name, queue, aci, acm, params.aifs, params.cw_min,
+		       params.cw_max, params.burst_time);
+		/* TODO: handle ACM (block TX, fallback to next lowest allowed
+		 * AC for now) */
+		if (local->ops->conf_tx(local_to_hw(local), queue, &params)) {
+			printk(KERN_DEBUG "%s: failed to set TX queue "
+			       "parameters for queue %d\n", dev->name, queue);
+		}
+	}
+}
+
+
+static void ieee80211_sta_send_associnfo(struct net_device *dev,
+					 struct ieee80211_if_sta *ifsta)
+{
+	char *buf;
+	size_t len;
+	int i;
+	union iwreq_data wrqu;
+
+	if (!ifsta->assocreq_ies && !ifsta->assocresp_ies)
+		return;
+
+	buf = kmalloc(50 + 2 * (ifsta->assocreq_ies_len +
+				ifsta->assocresp_ies_len), GFP_ATOMIC);
+	if (!buf)
+		return;
+
+	len = sprintf(buf, "ASSOCINFO(");
+	if (ifsta->assocreq_ies) {
+		len += sprintf(buf + len, "ReqIEs=");
+		for (i = 0; i < ifsta->assocreq_ies_len; i++) {
+			len += sprintf(buf + len, "%02x",
+				       ifsta->assocreq_ies[i]);
+		}
+	}
+	if (ifsta->assocresp_ies) {
+		if (ifsta->assocreq_ies)
+			len += sprintf(buf + len, " ");
+		len += sprintf(buf + len, "RespIEs=");
+		for (i = 0; i < ifsta->assocresp_ies_len; i++) {
+			len += sprintf(buf + len, "%02x",
+				       ifsta->assocresp_ies[i]);
+		}
+	}
+	len += sprintf(buf + len, ")");
+
+	if (len > IW_CUSTOM_MAX) {
+		len = sprintf(buf, "ASSOCRESPIE=");
+		for (i = 0; i < ifsta->assocresp_ies_len; i++) {
+			len += sprintf(buf + len, "%02x",
+				       ifsta->assocresp_ies[i]);
+		}
+	}
+
+	memset(&wrqu, 0, sizeof(wrqu));
+	wrqu.data.length = len;
+	wireless_send_event(dev, IWEVCUSTOM, &wrqu, buf);
+
+	kfree(buf);
+}
+
+
+static void ieee80211_set_associated(struct net_device *dev,
+				     struct ieee80211_if_sta *ifsta, int assoc)
+{
+	union iwreq_data wrqu;
+
+	if (ifsta->associated == assoc)
+		return;
+
+	ifsta->associated = assoc;
+
+	if (assoc) {
+		struct ieee80211_sub_if_data *sdata;
+		sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+		if (sdata->type != IEEE80211_IF_TYPE_STA)
+			return;
+		netif_carrier_on(dev);
+		ifsta->prev_bssid_set = 1;
+		memcpy(ifsta->prev_bssid, sdata->u.sta.bssid, ETH_ALEN);
+		memcpy(wrqu.ap_addr.sa_data, sdata->u.sta.bssid, ETH_ALEN);
+		ieee80211_sta_send_associnfo(dev, ifsta);
+	} else {
+		netif_carrier_off(dev);
+		memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
+	}
+	wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+	wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
+	ifsta->last_probe = jiffies;
+}
+
+static void ieee80211_set_disassoc(struct net_device *dev,
+				   struct ieee80211_if_sta *ifsta, int deauth)
+{
+	if (deauth)
+		ifsta->auth_tries = 0;
+	ifsta->assoc_tries = 0;
+	ieee80211_set_associated(dev, ifsta, 0);
+}
+
+static void ieee80211_sta_tx(struct net_device *dev, struct sk_buff *skb,
+			     int encrypt)
+{
+	struct ieee80211_sub_if_data *sdata;
+	struct ieee80211_tx_packet_data *pkt_data;
+
+	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	skb->dev = sdata->local->mdev;
+	skb_set_mac_header(skb, 0);
+	skb_set_network_header(skb, 0);
+	skb_set_transport_header(skb, 0);
+
+	pkt_data = (struct ieee80211_tx_packet_data *) skb->cb;
+	memset(pkt_data, 0, sizeof(struct ieee80211_tx_packet_data));
+	pkt_data->ifindex = sdata->dev->ifindex;
+	pkt_data->mgmt_iface = (sdata->type == IEEE80211_IF_TYPE_MGMT);
+	pkt_data->do_not_encrypt = !encrypt;
+
+	dev_queue_xmit(skb);
+}
+
+
+static void ieee80211_send_auth(struct net_device *dev,
+				struct ieee80211_if_sta *ifsta,
+				int transaction, u8 *extra, size_t extra_len,
+				int encrypt)
+{
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+	struct sk_buff *skb;
+	struct ieee80211_mgmt *mgmt;
+
+	skb = dev_alloc_skb(local->hw.extra_tx_headroom +
+			    sizeof(*mgmt) + 6 + extra_len);
+	if (!skb) {
+		printk(KERN_DEBUG "%s: failed to allocate buffer for auth "
+		       "frame\n", dev->name);
+		return;
+	}
+	skb_reserve(skb, local->hw.extra_tx_headroom);
+
+	mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24 + 6);
+	memset(mgmt, 0, 24 + 6);
+	mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
+					   IEEE80211_STYPE_AUTH);
+	if (encrypt)
+		mgmt->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
+	memcpy(mgmt->da, ifsta->bssid, ETH_ALEN);
+	memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
+	memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
+	mgmt->u.auth.auth_alg = cpu_to_le16(ifsta->auth_alg);
+	mgmt->u.auth.auth_transaction = cpu_to_le16(transaction);
+	ifsta->auth_transaction = transaction + 1;
+	mgmt->u.auth.status_code = cpu_to_le16(0);
+	if (extra)
+		memcpy(skb_put(skb, extra_len), extra, extra_len);
+
+	ieee80211_sta_tx(dev, skb, encrypt);
+}
+
+
+static void ieee80211_authenticate(struct net_device *dev,
+				   struct ieee80211_if_sta *ifsta)
+{
+	ifsta->auth_tries++;
+	if (ifsta->auth_tries > IEEE80211_AUTH_MAX_TRIES) {
+		printk(KERN_DEBUG "%s: authentication with AP " MAC_FMT
+		       " timed out\n",
+		       dev->name, MAC_ARG(ifsta->bssid));
+		ifsta->state = IEEE80211_DISABLED;
+		return;
+	}
+
+	ifsta->state = IEEE80211_AUTHENTICATE;
+	printk(KERN_DEBUG "%s: authenticate with AP " MAC_FMT "\n",
+	       dev->name, MAC_ARG(ifsta->bssid));
+
+	ieee80211_send_auth(dev, ifsta, 1, NULL, 0, 0);
+
+	mod_timer(&ifsta->timer, jiffies + IEEE80211_AUTH_TIMEOUT);
+}
+
+
+static void ieee80211_send_assoc(struct net_device *dev,
+				 struct ieee80211_if_sta *ifsta)
+{
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+	struct ieee80211_hw_mode *mode;
+	struct sk_buff *skb;
+	struct ieee80211_mgmt *mgmt;
+	u8 *pos, *ies;
+	int i, len;
+	u16 capab;
+	struct ieee80211_sta_bss *bss;
+	int wmm = 0;
+
+	skb = dev_alloc_skb(local->hw.extra_tx_headroom +
+			    sizeof(*mgmt) + 200 + ifsta->extra_ie_len +
+			    ifsta->ssid_len);
+	if (!skb) {
+		printk(KERN_DEBUG "%s: failed to allocate buffer for assoc "
+		       "frame\n", dev->name);
+		return;
+	}
+	skb_reserve(skb, local->hw.extra_tx_headroom);
+
+	mode = local->oper_hw_mode;
+	capab = ifsta->capab;
+	if (mode->mode == MODE_IEEE80211G) {
+		capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME |
+			WLAN_CAPABILITY_SHORT_PREAMBLE;
+	}
+	bss = ieee80211_rx_bss_get(dev, ifsta->bssid);
+	if (bss) {
+		if (bss->capability & WLAN_CAPABILITY_PRIVACY)
+			capab |= WLAN_CAPABILITY_PRIVACY;
+		if (bss->wmm_ie) {
+			wmm = 1;
+		}
+		ieee80211_rx_bss_put(dev, bss);
+	}
+
+	mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
+	memset(mgmt, 0, 24);
+	memcpy(mgmt->da, ifsta->bssid, ETH_ALEN);
+	memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
+	memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
+
+	if (ifsta->prev_bssid_set) {
+		skb_put(skb, 10);
+		mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
+						   IEEE80211_STYPE_REASSOC_REQ);
+		mgmt->u.reassoc_req.capab_info = cpu_to_le16(capab);
+		mgmt->u.reassoc_req.listen_interval = cpu_to_le16(1);
+		memcpy(mgmt->u.reassoc_req.current_ap, ifsta->prev_bssid,
+		       ETH_ALEN);
+	} else {
+		skb_put(skb, 4);
+		mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
+						   IEEE80211_STYPE_ASSOC_REQ);
+		mgmt->u.assoc_req.capab_info = cpu_to_le16(capab);
+		mgmt->u.assoc_req.listen_interval = cpu_to_le16(1);
+	}
+
+	/* SSID */
+	ies = pos = skb_put(skb, 2 + ifsta->ssid_len);
+	*pos++ = WLAN_EID_SSID;
+	*pos++ = ifsta->ssid_len;
+	memcpy(pos, ifsta->ssid, ifsta->ssid_len);
+
+	len = mode->num_rates;
+	if (len > 8)
+		len = 8;
+	pos = skb_put(skb, len + 2);
+	*pos++ = WLAN_EID_SUPP_RATES;
+	*pos++ = len;
+	for (i = 0; i < len; i++) {
+		int rate = mode->rates[i].rate;
+		if (mode->mode == MODE_ATHEROS_TURBO)
+			rate /= 2;
+		*pos++ = (u8) (rate / 5);
+	}
+
+	if (mode->num_rates > len) {
+		pos = skb_put(skb, mode->num_rates - len + 2);
+		*pos++ = WLAN_EID_EXT_SUPP_RATES;
+		*pos++ = mode->num_rates - len;
+		for (i = len; i < mode->num_rates; i++) {
+			int rate = mode->rates[i].rate;
+			if (mode->mode == MODE_ATHEROS_TURBO)
+				rate /= 2;
+			*pos++ = (u8) (rate / 5);
+		}
+	}
+
+	if (ifsta->extra_ie) {
+		pos = skb_put(skb, ifsta->extra_ie_len);
+		memcpy(pos, ifsta->extra_ie, ifsta->extra_ie_len);
+	}
+
+	if (wmm && ifsta->wmm_enabled) {
+		pos = skb_put(skb, 9);
+		*pos++ = WLAN_EID_VENDOR_SPECIFIC;
+		*pos++ = 7; /* len */
+		*pos++ = 0x00; /* Microsoft OUI 00:50:F2 */
+		*pos++ = 0x50;
+		*pos++ = 0xf2;
+		*pos++ = 2; /* WME */
+		*pos++ = 0; /* WME info */
+		*pos++ = 1; /* WME ver */
+		*pos++ = 0;
+	}
+
+	kfree(ifsta->assocreq_ies);
+	ifsta->assocreq_ies_len = (skb->data + skb->len) - ies;
+	ifsta->assocreq_ies = kmalloc(ifsta->assocreq_ies_len, GFP_ATOMIC);
+	if (ifsta->assocreq_ies)
+		memcpy(ifsta->assocreq_ies, ies, ifsta->assocreq_ies_len);
+
+	ieee80211_sta_tx(dev, skb, 0);
+}
+
+
+static void ieee80211_send_deauth(struct net_device *dev,
+				  struct ieee80211_if_sta *ifsta, u16 reason)
+{
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+	struct sk_buff *skb;
+	struct ieee80211_mgmt *mgmt;
+
+	skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt));
+	if (!skb) {
+		printk(KERN_DEBUG "%s: failed to allocate buffer for deauth "
+		       "frame\n", dev->name);
+		return;
+	}
+	skb_reserve(skb, local->hw.extra_tx_headroom);
+
+	mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
+	memset(mgmt, 0, 24);
+	memcpy(mgmt->da, ifsta->bssid, ETH_ALEN);
+	memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
+	memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
+	mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
+					   IEEE80211_STYPE_DEAUTH);
+	skb_put(skb, 2);
+	mgmt->u.deauth.reason_code = cpu_to_le16(reason);
+
+	ieee80211_sta_tx(dev, skb, 0);
+}
+
+
+static void ieee80211_send_disassoc(struct net_device *dev,
+				    struct ieee80211_if_sta *ifsta, u16 reason)
+{
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+	struct sk_buff *skb;
+	struct ieee80211_mgmt *mgmt;
+
+	skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt));
+	if (!skb) {
+		printk(KERN_DEBUG "%s: failed to allocate buffer for disassoc "
+		       "frame\n", dev->name);
+		return;
+	}
+	skb_reserve(skb, local->hw.extra_tx_headroom);
+
+	mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
+	memset(mgmt, 0, 24);
+	memcpy(mgmt->da, ifsta->bssid, ETH_ALEN);
+	memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
+	memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
+	mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
+					   IEEE80211_STYPE_DISASSOC);
+	skb_put(skb, 2);
+	mgmt->u.disassoc.reason_code = cpu_to_le16(reason);
+
+	ieee80211_sta_tx(dev, skb, 0);
+}
+
+
+static int ieee80211_privacy_mismatch(struct net_device *dev,
+				      struct ieee80211_if_sta *ifsta)
+{
+	struct ieee80211_sta_bss *bss;
+	int res = 0;
+
+	if (!ifsta || ifsta->mixed_cell ||
+	    ifsta->key_mgmt != IEEE80211_KEY_MGMT_NONE)
+		return 0;
+
+	bss = ieee80211_rx_bss_get(dev, ifsta->bssid);
+	if (!bss)
+		return 0;
+
+	if (ieee80211_sta_wep_configured(dev) !=
+	    !!(bss->capability & WLAN_CAPABILITY_PRIVACY))
+		res = 1;
+
+	ieee80211_rx_bss_put(dev, bss);
+
+	return res;
+}
+
+
+static void ieee80211_associate(struct net_device *dev,
+				struct ieee80211_if_sta *ifsta)
+{
+	ifsta->assoc_tries++;
+	if (ifsta->assoc_tries > IEEE80211_ASSOC_MAX_TRIES) {
+		printk(KERN_DEBUG "%s: association with AP " MAC_FMT
+		       " timed out\n",
+		       dev->name, MAC_ARG(ifsta->bssid));
+		ifsta->state = IEEE80211_DISABLED;
+		return;
+	}
+
+	ifsta->state = IEEE80211_ASSOCIATE;
+	printk(KERN_DEBUG "%s: associate with AP " MAC_FMT "\n",
+	       dev->name, MAC_ARG(ifsta->bssid));
+	if (ieee80211_privacy_mismatch(dev, ifsta)) {
+		printk(KERN_DEBUG "%s: mismatch in privacy configuration and "
+		       "mixed-cell disabled - abort association\n", dev->name);
+		ifsta->state = IEEE80211_DISABLED;
+		return;
+	}
+
+	ieee80211_send_assoc(dev, ifsta);
+
+	mod_timer(&ifsta->timer, jiffies + IEEE80211_ASSOC_TIMEOUT);
+}
+
+
+static void ieee80211_associated(struct net_device *dev,
+				 struct ieee80211_if_sta *ifsta)
+{
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+	struct sta_info *sta;
+	int disassoc;
+
+	/* TODO: start monitoring current AP signal quality and number of
+	 * missed beacons. Scan other channels every now and then and search
+	 * for better APs. */
+	/* TODO: remove expired BSSes */
+
+	ifsta->state = IEEE80211_ASSOCIATED;
+
+	sta = sta_info_get(local, ifsta->bssid);
+	if (!sta) {
+		printk(KERN_DEBUG "%s: No STA entry for own AP " MAC_FMT "\n",
+		       dev->name, MAC_ARG(ifsta->bssid));
+		disassoc = 1;
+	} else {
+		disassoc = 0;
+		if (time_after(jiffies,
+			       sta->last_rx + IEEE80211_MONITORING_INTERVAL)) {
+			if (ifsta->probereq_poll) {
+				printk(KERN_DEBUG "%s: No ProbeResp from "
+				       "current AP " MAC_FMT " - assume out of "
+				       "range\n",
+				       dev->name, MAC_ARG(ifsta->bssid));
+				disassoc = 1;
+				sta_info_free(sta, 0);
+				ifsta->probereq_poll = 0;
+			} else {
+				ieee80211_send_probe_req(dev, ifsta->bssid,
+							 local->scan_ssid,
+							 local->scan_ssid_len);
+				ifsta->probereq_poll = 1;
+			}
+		} else {
+			ifsta->probereq_poll = 0;
+			if (time_after(jiffies, ifsta->last_probe +
+				       IEEE80211_PROBE_INTERVAL)) {
+				ifsta->last_probe = jiffies;
+				ieee80211_send_probe_req(dev, ifsta->bssid,
+							 ifsta->ssid,
+							 ifsta->ssid_len);
+			}
+		}
+		sta_info_put(sta);
+	}
+	if (disassoc) {
+		union iwreq_data wrqu;
+		memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
+		wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+		wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
+		mod_timer(&ifsta->timer, jiffies +
+				      IEEE80211_MONITORING_INTERVAL + 30 * HZ);
+	} else {
+		mod_timer(&ifsta->timer, jiffies +
+				      IEEE80211_MONITORING_INTERVAL);
+	}
+}
+
+
+static void ieee80211_send_probe_req(struct net_device *dev, u8 *dst,
+				     u8 *ssid, size_t ssid_len)
+{
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+	struct ieee80211_hw_mode *mode;
+	struct sk_buff *skb;
+	struct ieee80211_mgmt *mgmt;
+	u8 *pos, *supp_rates, *esupp_rates = NULL;
+	int i;
+
+	skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt) + 200);
+	if (!skb) {
+		printk(KERN_DEBUG "%s: failed to allocate buffer for probe "
+		       "request\n", dev->name);
+		return;
+	}
+	skb_reserve(skb, local->hw.extra_tx_headroom);
+
+	mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
+	memset(mgmt, 0, 24);
+	mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
+					   IEEE80211_STYPE_PROBE_REQ);
+	memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
+	if (dst) {
+		memcpy(mgmt->da, dst, ETH_ALEN);
+		memcpy(mgmt->bssid, dst, ETH_ALEN);
+	} else {
+		memset(mgmt->da, 0xff, ETH_ALEN);
+		memset(mgmt->bssid, 0xff, ETH_ALEN);
+	}
+	pos = skb_put(skb, 2 + ssid_len);
+	*pos++ = WLAN_EID_SSID;
+	*pos++ = ssid_len;
+	memcpy(pos, ssid, ssid_len);
+
+	supp_rates = skb_put(skb, 2);
+	supp_rates[0] = WLAN_EID_SUPP_RATES;
+	supp_rates[1] = 0;
+	mode = local->oper_hw_mode;
+	for (i = 0; i < mode->num_rates; i++) {
+		struct ieee80211_rate *rate = &mode->rates[i];
+		if (!(rate->flags & IEEE80211_RATE_SUPPORTED))
+			continue;
+		if (esupp_rates) {
+			pos = skb_put(skb, 1);
+			esupp_rates[1]++;
+		} else if (supp_rates[1] == 8) {
+			esupp_rates = skb_put(skb, 3);
+			esupp_rates[0] = WLAN_EID_EXT_SUPP_RATES;
+			esupp_rates[1] = 1;
+			pos = &esupp_rates[2];
+		} else {
+			pos = skb_put(skb, 1);
+			supp_rates[1]++;
+		}
+		if (mode->mode == MODE_ATHEROS_TURBO)
+			*pos = rate->rate / 10;
+		else
+			*pos = rate->rate / 5;
+	}
+
+	ieee80211_sta_tx(dev, skb, 0);
+}
+
+
+static int ieee80211_sta_wep_configured(struct net_device *dev)
+{
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	if (!sdata || !sdata->default_key ||
+	    sdata->default_key->alg != ALG_WEP)
+		return 0;
+	return 1;
+}
+
+
+static void ieee80211_auth_completed(struct net_device *dev,
+				     struct ieee80211_if_sta *ifsta)
+{
+	printk(KERN_DEBUG "%s: authenticated\n", dev->name);
+	ifsta->authenticated = 1;
+	ieee80211_associate(dev, ifsta);
+}
+
+
+static void ieee80211_auth_challenge(struct net_device *dev,
+				     struct ieee80211_if_sta *ifsta,
+				     struct ieee80211_mgmt *mgmt,
+				     size_t len)
+{
+	u8 *pos;
+	struct ieee802_11_elems elems;
+
+	printk(KERN_DEBUG "%s: replying to auth challenge\n", dev->name);
+	pos = mgmt->u.auth.variable;
+	if (ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems)
+	    == ParseFailed) {
+		printk(KERN_DEBUG "%s: failed to parse Auth(challenge)\n",
+		       dev->name);
+		return;
+	}
+	if (!elems.challenge) {
+		printk(KERN_DEBUG "%s: no challenge IE in shared key auth "
+		       "frame\n", dev->name);
+		return;
+	}
+	ieee80211_send_auth(dev, ifsta, 3, elems.challenge - 2,
+			    elems.challenge_len + 2, 1);
+}
+
+
+static void ieee80211_rx_mgmt_auth(struct net_device *dev,
+				   struct ieee80211_if_sta *ifsta,
+				   struct ieee80211_mgmt *mgmt,
+				   size_t len)
+{
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	u16 auth_alg, auth_transaction, status_code;
+
+	if (ifsta->state != IEEE80211_AUTHENTICATE &&
+	    sdata->type != IEEE80211_IF_TYPE_IBSS) {
+		printk(KERN_DEBUG "%s: authentication frame received from "
+		       MAC_FMT ", but not in authenticate state - ignored\n",
+		       dev->name, MAC_ARG(mgmt->sa));
+		return;
+	}
+
+	if (len < 24 + 6) {
+		printk(KERN_DEBUG "%s: too short (%zd) authentication frame "
+		       "received from " MAC_FMT " - ignored\n",
+		       dev->name, len, MAC_ARG(mgmt->sa));
+		return;
+	}
+
+	if (sdata->type != IEEE80211_IF_TYPE_IBSS &&
+	    memcmp(ifsta->bssid, mgmt->sa, ETH_ALEN) != 0) {
+		printk(KERN_DEBUG "%s: authentication frame received from "
+		       "unknown AP (SA=" MAC_FMT " BSSID=" MAC_FMT ") - "
+		       "ignored\n", dev->name, MAC_ARG(mgmt->sa),
+		       MAC_ARG(mgmt->bssid));
+		return;
+	}
+
+	if (sdata->type != IEEE80211_IF_TYPE_IBSS &&
+	    memcmp(ifsta->bssid, mgmt->bssid, ETH_ALEN) != 0) {
+		printk(KERN_DEBUG "%s: authentication frame received from "
+		       "unknown BSSID (SA=" MAC_FMT " BSSID=" MAC_FMT ") - "
+		       "ignored\n", dev->name, MAC_ARG(mgmt->sa),
+		       MAC_ARG(mgmt->bssid));
+		return;
+	}
+
+	auth_alg = le16_to_cpu(mgmt->u.auth.auth_alg);
+	auth_transaction = le16_to_cpu(mgmt->u.auth.auth_transaction);
+	status_code = le16_to_cpu(mgmt->u.auth.status_code);
+
+	printk(KERN_DEBUG "%s: RX authentication from " MAC_FMT " (alg=%d "
+	       "transaction=%d status=%d)\n",
+	       dev->name, MAC_ARG(mgmt->sa), auth_alg,
+	       auth_transaction, status_code);
+
+	if (sdata->type == IEEE80211_IF_TYPE_IBSS) {
+		/* IEEE 802.11 standard does not require authentication in IBSS
+		 * networks and most implementations do not seem to use it.
+		 * However, try to reply to authentication attempts if someone
+		 * has actually implemented this.
+		 * TODO: Could implement shared key authentication. */
+		if (auth_alg != WLAN_AUTH_OPEN || auth_transaction != 1) {
+			printk(KERN_DEBUG "%s: unexpected IBSS authentication "
+			       "frame (alg=%d transaction=%d)\n",
+			       dev->name, auth_alg, auth_transaction);
+			return;
+		}
+		ieee80211_send_auth(dev, ifsta, 2, NULL, 0, 0);
+	}
+
+	if (auth_alg != ifsta->auth_alg ||
+	    auth_transaction != ifsta->auth_transaction) {
+		printk(KERN_DEBUG "%s: unexpected authentication frame "
+		       "(alg=%d transaction=%d)\n",
+		       dev->name, auth_alg, auth_transaction);
+		return;
+	}
+
+	if (status_code != WLAN_STATUS_SUCCESS) {
+		printk(KERN_DEBUG "%s: AP denied authentication (auth_alg=%d "
+		       "code=%d)\n", dev->name, ifsta->auth_alg, status_code);
+		if (status_code == WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG) {
+			u8 algs[3];
+			const int num_algs = ARRAY_SIZE(algs);
+			int i, pos;
+			algs[0] = algs[1] = algs[2] = 0xff;
+			if (ifsta->auth_algs & IEEE80211_AUTH_ALG_OPEN)
+				algs[0] = WLAN_AUTH_OPEN;
+			if (ifsta->auth_algs & IEEE80211_AUTH_ALG_SHARED_KEY)
+				algs[1] = WLAN_AUTH_SHARED_KEY;
+			if (ifsta->auth_algs & IEEE80211_AUTH_ALG_LEAP)
+				algs[2] = WLAN_AUTH_LEAP;
+			if (ifsta->auth_alg == WLAN_AUTH_OPEN)
+				pos = 0;
+			else if (ifsta->auth_alg == WLAN_AUTH_SHARED_KEY)
+				pos = 1;
+			else
+				pos = 2;
+			for (i = 0; i < num_algs; i++) {
+				pos++;
+				if (pos >= num_algs)
+					pos = 0;
+				if (algs[pos] == ifsta->auth_alg ||
+				    algs[pos] == 0xff)
+					continue;
+				if (algs[pos] == WLAN_AUTH_SHARED_KEY &&
+				    !ieee80211_sta_wep_configured(dev))
+					continue;
+				ifsta->auth_alg = algs[pos];
+				printk(KERN_DEBUG "%s: set auth_alg=%d for "
+				       "next try\n",
+				       dev->name, ifsta->auth_alg);
+				break;
+			}
+		}
+		return;
+	}
+
+	switch (ifsta->auth_alg) {
+	case WLAN_AUTH_OPEN:
+	case WLAN_AUTH_LEAP:
+		ieee80211_auth_completed(dev, ifsta);
+		break;
+	case WLAN_AUTH_SHARED_KEY:
+		if (ifsta->auth_transaction == 4)
+			ieee80211_auth_completed(dev, ifsta);
+		else
+			ieee80211_auth_challenge(dev, ifsta, mgmt, len);
+		break;
+	}
+}
+
+
+static void ieee80211_rx_mgmt_deauth(struct net_device *dev,
+				     struct ieee80211_if_sta *ifsta,
+				     struct ieee80211_mgmt *mgmt,
+				     size_t len)
+{
+	u16 reason_code;
+
+	if (len < 24 + 2) {
+		printk(KERN_DEBUG "%s: too short (%zd) deauthentication frame "
+		       "received from " MAC_FMT " - ignored\n",
+		       dev->name, len, MAC_ARG(mgmt->sa));
+		return;
+	}
+
+	if (memcmp(ifsta->bssid, mgmt->sa, ETH_ALEN) != 0) {
+		printk(KERN_DEBUG "%s: deauthentication frame received from "
+		       "unknown AP (SA=" MAC_FMT " BSSID=" MAC_FMT ") - "
+		       "ignored\n", dev->name, MAC_ARG(mgmt->sa),
+		       MAC_ARG(mgmt->bssid));
+		return;
+	}
+
+	reason_code = le16_to_cpu(mgmt->u.deauth.reason_code);
+
+	printk(KERN_DEBUG "%s: RX deauthentication from " MAC_FMT
+	       " (reason=%d)\n",
+	       dev->name, MAC_ARG(mgmt->sa), reason_code);
+
+	if (ifsta->authenticated) {
+		printk(KERN_DEBUG "%s: deauthenticated\n", dev->name);
+	}
+
+	if (ifsta->state == IEEE80211_AUTHENTICATE ||
+	    ifsta->state == IEEE80211_ASSOCIATE ||
+	    ifsta->state == IEEE80211_ASSOCIATED) {
+		ifsta->state = IEEE80211_AUTHENTICATE;
+		mod_timer(&ifsta->timer, jiffies +
+				      IEEE80211_RETRY_AUTH_INTERVAL);
+	}
+
+	ieee80211_set_disassoc(dev, ifsta, 1);
+	ifsta->authenticated = 0;
+}
+
+
+static void ieee80211_rx_mgmt_disassoc(struct net_device *dev,
+				       struct ieee80211_if_sta *ifsta,
+				       struct ieee80211_mgmt *mgmt,
+				       size_t len)
+{
+	u16 reason_code;
+
+	if (len < 24 + 2) {
+		printk(KERN_DEBUG "%s: too short (%zd) disassociation frame "
+		       "received from " MAC_FMT " - ignored\n",
+		       dev->name, len, MAC_ARG(mgmt->sa));
+		return;
+	}
+
+	if (memcmp(ifsta->bssid, mgmt->sa, ETH_ALEN) != 0) {
+		printk(KERN_DEBUG "%s: disassociation frame received from "
+		       "unknown AP (SA=" MAC_FMT " BSSID=" MAC_FMT ") - "
+		       "ignored\n", dev->name, MAC_ARG(mgmt->sa),
+		       MAC_ARG(mgmt->bssid));
+		return;
+	}
+
+	reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code);
+
+	printk(KERN_DEBUG "%s: RX disassociation from " MAC_FMT
+	       " (reason=%d)\n",
+	       dev->name, MAC_ARG(mgmt->sa), reason_code);
+
+	if (ifsta->associated)
+		printk(KERN_DEBUG "%s: disassociated\n", dev->name);
+
+	if (ifsta->state == IEEE80211_ASSOCIATED) {
+		ifsta->state = IEEE80211_ASSOCIATE;
+		mod_timer(&ifsta->timer, jiffies +
+				      IEEE80211_RETRY_AUTH_INTERVAL);
+	}
+
+	ieee80211_set_disassoc(dev, ifsta, 0);
+}
+
+
+static void ieee80211_rx_mgmt_assoc_resp(struct net_device *dev,
+					 struct ieee80211_if_sta *ifsta,
+					 struct ieee80211_mgmt *mgmt,
+					 size_t len,
+					 int reassoc)
+{
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+	struct ieee80211_hw_mode *mode;
+	struct sta_info *sta;
+	u32 rates;
+	u16 capab_info, status_code, aid;
+	struct ieee802_11_elems elems;
+	u8 *pos;
+	int i, j;
+
+	/* AssocResp and ReassocResp have identical structure, so process both
+	 * of them in this function. */
+
+	if (ifsta->state != IEEE80211_ASSOCIATE) {
+		printk(KERN_DEBUG "%s: association frame received from "
+		       MAC_FMT ", but not in associate state - ignored\n",
+		       dev->name, MAC_ARG(mgmt->sa));
+		return;
+	}
+
+	if (len < 24 + 6) {
+		printk(KERN_DEBUG "%s: too short (%zd) association frame "
+		       "received from " MAC_FMT " - ignored\n",
+		       dev->name, len, MAC_ARG(mgmt->sa));
+		return;
+	}
+
+	if (memcmp(ifsta->bssid, mgmt->sa, ETH_ALEN) != 0) {
+		printk(KERN_DEBUG "%s: association frame received from "
+		       "unknown AP (SA=" MAC_FMT " BSSID=" MAC_FMT ") - "
+		       "ignored\n", dev->name, MAC_ARG(mgmt->sa),
+		       MAC_ARG(mgmt->bssid));
+		return;
+	}
+
+	capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info);
+	status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code);
+	aid = le16_to_cpu(mgmt->u.assoc_resp.aid);
+	if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14)))
+		printk(KERN_DEBUG "%s: invalid aid value %d; bits 15:14 not "
+		       "set\n", dev->name, aid);
+	aid &= ~(BIT(15) | BIT(14));
+
+	printk(KERN_DEBUG "%s: RX %sssocResp from " MAC_FMT " (capab=0x%x "
+	       "status=%d aid=%d)\n",
+	       dev->name, reassoc ? "Rea" : "A", MAC_ARG(mgmt->sa),
+	       capab_info, status_code, aid);
+
+	if (status_code != WLAN_STATUS_SUCCESS) {
+		printk(KERN_DEBUG "%s: AP denied association (code=%d)\n",
+		       dev->name, status_code);
+		return;
+	}
+
+	pos = mgmt->u.assoc_resp.variable;
+	if (ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems)
+	    == ParseFailed) {
+		printk(KERN_DEBUG "%s: failed to parse AssocResp\n",
+		       dev->name);
+		return;
+	}
+
+	if (!elems.supp_rates) {
+		printk(KERN_DEBUG "%s: no SuppRates element in AssocResp\n",
+		       dev->name);
+		return;
+	}
+
+	printk(KERN_DEBUG "%s: associated\n", dev->name);
+	ifsta->aid = aid;
+	ifsta->ap_capab = capab_info;
+
+	kfree(ifsta->assocresp_ies);
+	ifsta->assocresp_ies_len = len - (pos - (u8 *) mgmt);
+	ifsta->assocresp_ies = kmalloc(ifsta->assocresp_ies_len, GFP_ATOMIC);
+	if (ifsta->assocresp_ies)
+		memcpy(ifsta->assocresp_ies, pos, ifsta->assocresp_ies_len);
+
+	ieee80211_set_associated(dev, ifsta, 1);
+
+	/* Add STA entry for the AP */
+	sta = sta_info_get(local, ifsta->bssid);
+	if (!sta) {
+		struct ieee80211_sta_bss *bss;
+		sta = sta_info_add(local, dev, ifsta->bssid, GFP_ATOMIC);
+		if (!sta) {
+			printk(KERN_DEBUG "%s: failed to add STA entry for the"
+			       " AP\n", dev->name);
+			return;
+		}
+		bss = ieee80211_rx_bss_get(dev, ifsta->bssid);
+		if (bss) {
+			sta->last_rssi = bss->rssi;
+			sta->last_signal = bss->signal;
+			sta->last_noise = bss->noise;
+			ieee80211_rx_bss_put(dev, bss);
+		}
+	}
+
+	sta->dev = dev;
+	sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC;
+	sta->assoc_ap = 1;
+
+	rates = 0;
+	mode = local->oper_hw_mode;
+	for (i = 0; i < elems.supp_rates_len; i++) {
+		int rate = (elems.supp_rates[i] & 0x7f) * 5;
+		if (mode->mode == MODE_ATHEROS_TURBO)
+			rate *= 2;
+		for (j = 0; j < mode->num_rates; j++)
+			if (mode->rates[j].rate == rate)
+				rates |= BIT(j);
+	}
+	for (i = 0; i < elems.ext_supp_rates_len; i++) {
+		int rate = (elems.ext_supp_rates[i] & 0x7f) * 5;
+		if (mode->mode == MODE_ATHEROS_TURBO)
+			rate *= 2;
+		for (j = 0; j < mode->num_rates; j++)
+			if (mode->rates[j].rate == rate)
+				rates |= BIT(j);
+	}
+	sta->supp_rates = rates;
+
+	rate_control_rate_init(sta, local);
+
+	if (elems.wmm_param && ifsta->wmm_enabled) {
+		sta->flags |= WLAN_STA_WME;
+		ieee80211_sta_wmm_params(dev, ifsta, elems.wmm_param,
+					 elems.wmm_param_len);
+	}
+
+
+	sta_info_put(sta);
+
+	ieee80211_associated(dev, ifsta);
+}
+
+
+/* Caller must hold local->sta_bss_lock */
+static void __ieee80211_rx_bss_hash_add(struct net_device *dev,
+					struct ieee80211_sta_bss *bss)
+{
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+	bss->hnext = local->sta_bss_hash[STA_HASH(bss->bssid)];
+	local->sta_bss_hash[STA_HASH(bss->bssid)] = bss;
+}
+
+
+/* Caller must hold local->sta_bss_lock */
+static void __ieee80211_rx_bss_hash_del(struct net_device *dev,
+					struct ieee80211_sta_bss *bss)
+{
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+	struct ieee80211_sta_bss *b, *prev = NULL;
+	b = local->sta_bss_hash[STA_HASH(bss->bssid)];
+	while (b) {
+		if (b == bss) {
+			if (!prev)
+				local->sta_bss_hash[STA_HASH(bss->bssid)] =
+					bss->hnext;
+			else
+				prev->hnext = bss->hnext;
+			break;
+		}
+		prev = b;
+		b = b->hnext;
+	}
+}
+
+
+static struct ieee80211_sta_bss *
+ieee80211_rx_bss_add(struct net_device *dev, u8 *bssid)
+{
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+	struct ieee80211_sta_bss *bss;
+
+	bss = kmalloc(sizeof(*bss), GFP_ATOMIC);
+	if (!bss)
+		return NULL;
+	memset(bss, 0, sizeof(*bss));
+	atomic_inc(&bss->users);
+	atomic_inc(&bss->users);
+	memcpy(bss->bssid, bssid, ETH_ALEN);
+
+	spin_lock_bh(&local->sta_bss_lock);
+	/* TODO: order by RSSI? */
+	list_add_tail(&bss->list, &local->sta_bss_list);
+	__ieee80211_rx_bss_hash_add(dev, bss);
+	spin_unlock_bh(&local->sta_bss_lock);
+	return bss;
+}
+
+
+static struct ieee80211_sta_bss *
+ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid)
+{
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+	struct ieee80211_sta_bss *bss;
+
+	spin_lock_bh(&local->sta_bss_lock);
+	bss = local->sta_bss_hash[STA_HASH(bssid)];
+	while (bss) {
+		if (memcmp(bss->bssid, bssid, ETH_ALEN) == 0) {
+			atomic_inc(&bss->users);
+			break;
+		}
+		bss = bss->hnext;
+	}
+	spin_unlock_bh(&local->sta_bss_lock);
+	return bss;
+}
+
+
+static void ieee80211_rx_bss_free(struct ieee80211_sta_bss *bss)
+{
+	kfree(bss->wpa_ie);
+	kfree(bss->rsn_ie);
+	kfree(bss->wmm_ie);
+	kfree(bss);
+}
+
+
+static void ieee80211_rx_bss_put(struct net_device *dev,
+				 struct ieee80211_sta_bss *bss)
+{
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+	if (!atomic_dec_and_test(&bss->users))
+		return;
+
+	spin_lock_bh(&local->sta_bss_lock);
+	__ieee80211_rx_bss_hash_del(dev, bss);
+	list_del(&bss->list);
+	spin_unlock_bh(&local->sta_bss_lock);
+	ieee80211_rx_bss_free(bss);
+}
+
+
+void ieee80211_rx_bss_list_init(struct net_device *dev)
+{
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+	spin_lock_init(&local->sta_bss_lock);
+	INIT_LIST_HEAD(&local->sta_bss_list);
+}
+
+
+void ieee80211_rx_bss_list_deinit(struct net_device *dev)
+{
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+	struct ieee80211_sta_bss *bss, *tmp;
+
+	list_for_each_entry_safe(bss, tmp, &local->sta_bss_list, list)
+		ieee80211_rx_bss_put(dev, bss);
+}
+
+
+static void ieee80211_rx_bss_info(struct net_device *dev,
+				  struct ieee80211_mgmt *mgmt,
+				  size_t len,
+				  struct ieee80211_rx_status *rx_status,
+				  int beacon)
+{
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+	struct ieee802_11_elems elems;
+	size_t baselen;
+	int channel, invalid = 0, clen;
+	struct ieee80211_sta_bss *bss;
+	struct sta_info *sta;
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	u64 timestamp;
+
+	if (!beacon && memcmp(mgmt->da, dev->dev_addr, ETH_ALEN))
+		return; /* ignore ProbeResp to foreign address */
+
+#if 0
+	printk(KERN_DEBUG "%s: RX %s from " MAC_FMT " to " MAC_FMT "\n",
+	       dev->name, beacon ? "Beacon" : "Probe Response",
+	       MAC_ARG(mgmt->sa), MAC_ARG(mgmt->da));
+#endif
+
+	baselen = (u8 *) mgmt->u.beacon.variable - (u8 *) mgmt;
+	if (baselen > len)
+		return;
+
+	timestamp = le64_to_cpu(mgmt->u.beacon.timestamp);
+
+	if (sdata->type == IEEE80211_IF_TYPE_IBSS && beacon &&
+	    memcmp(mgmt->bssid, sdata->u.sta.bssid, ETH_ALEN) == 0) {
+#ifdef CONFIG_MAC80211_IBSS_DEBUG
+		static unsigned long last_tsf_debug = 0;
+		u64 tsf;
+		if (local->ops->get_tsf)
+			tsf = local->ops->get_tsf(local_to_hw(local));
+		else
+			tsf = -1LLU;
+		if (time_after(jiffies, last_tsf_debug + 5 * HZ)) {
+			printk(KERN_DEBUG "RX beacon SA=" MAC_FMT " BSSID="
+			       MAC_FMT " TSF=0x%llx BCN=0x%llx diff=%lld "
+			       "@%lu\n",
+			       MAC_ARG(mgmt->sa), MAC_ARG(mgmt->bssid),
+			       (unsigned long long)tsf,
+			       (unsigned long long)timestamp,
+			       (unsigned long long)(tsf - timestamp),
+			       jiffies);
+			last_tsf_debug = jiffies;
+		}
+#endif /* CONFIG_MAC80211_IBSS_DEBUG */
+	}
+
+	if (ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen,
+				   &elems) == ParseFailed)
+		invalid = 1;
+
+	if (sdata->type == IEEE80211_IF_TYPE_IBSS && elems.supp_rates &&
+	    memcmp(mgmt->bssid, sdata->u.sta.bssid, ETH_ALEN) == 0 &&
+	    (sta = sta_info_get(local, mgmt->sa))) {
+		struct ieee80211_hw_mode *mode;
+		struct ieee80211_rate *rates;
+		size_t num_rates;
+		u32 supp_rates, prev_rates;
+		int i, j;
+
+		mode = local->sta_scanning ?
+		       local->scan_hw_mode : local->oper_hw_mode;
+		rates = mode->rates;
+		num_rates = mode->num_rates;
+
+		supp_rates = 0;
+		for (i = 0; i < elems.supp_rates_len +
+			     elems.ext_supp_rates_len; i++) {
+			u8 rate = 0;
+			int own_rate;
+			if (i < elems.supp_rates_len)
+				rate = elems.supp_rates[i];
+			else if (elems.ext_supp_rates)
+				rate = elems.ext_supp_rates
+					[i - elems.supp_rates_len];
+			own_rate = 5 * (rate & 0x7f);
+			if (mode->mode == MODE_ATHEROS_TURBO)
+				own_rate *= 2;
+			for (j = 0; j < num_rates; j++)
+				if (rates[j].rate == own_rate)
+					supp_rates |= BIT(j);
+		}
+
+		prev_rates = sta->supp_rates;
+		sta->supp_rates &= supp_rates;
+		if (sta->supp_rates == 0) {
+			/* No matching rates - this should not really happen.
+			 * Make sure that at least one rate is marked
+			 * supported to avoid issues with TX rate ctrl. */
+			sta->supp_rates = sdata->u.sta.supp_rates_bits;
+		}
+		if (sta->supp_rates != prev_rates) {
+			printk(KERN_DEBUG "%s: updated supp_rates set for "
+			       MAC_FMT " based on beacon info (0x%x & 0x%x -> "
+			       "0x%x)\n",
+			       dev->name, MAC_ARG(sta->addr), prev_rates,
+			       supp_rates, sta->supp_rates);
+		}
+		sta_info_put(sta);
+	}
+
+	if (!elems.ssid)
+		return;
+
+	if (elems.ds_params && elems.ds_params_len == 1)
+		channel = elems.ds_params[0];
+	else
+		channel = rx_status->channel;
+
+	bss = ieee80211_rx_bss_get(dev, mgmt->bssid);
+	if (!bss) {
+		bss = ieee80211_rx_bss_add(dev, mgmt->bssid);
+		if (!bss)
+			return;
+	} else {
+#if 0
+		/* TODO: order by RSSI? */
+		spin_lock_bh(&local->sta_bss_lock);
+		list_move_tail(&bss->list, &local->sta_bss_list);
+		spin_unlock_bh(&local->sta_bss_lock);
+#endif
+	}
+
+	if (bss->probe_resp && beacon) {
+		/* Do not allow beacon to override data from Probe Response. */
+		ieee80211_rx_bss_put(dev, bss);
+		return;
+	}
+
+	bss->beacon_int = le16_to_cpu(mgmt->u.beacon.beacon_int);
+	bss->capability = le16_to_cpu(mgmt->u.beacon.capab_info);
+	if (elems.ssid && elems.ssid_len <= IEEE80211_MAX_SSID_LEN) {
+		memcpy(bss->ssid, elems.ssid, elems.ssid_len);
+		bss->ssid_len = elems.ssid_len;
+	}
+
+	bss->supp_rates_len = 0;
+	if (elems.supp_rates) {
+		clen = IEEE80211_MAX_SUPP_RATES - bss->supp_rates_len;
+		if (clen > elems.supp_rates_len)
+			clen = elems.supp_rates_len;
+		memcpy(&bss->supp_rates[bss->supp_rates_len], elems.supp_rates,
+		       clen);
+		bss->supp_rates_len += clen;
+	}
+	if (elems.ext_supp_rates) {
+		clen = IEEE80211_MAX_SUPP_RATES - bss->supp_rates_len;
+		if (clen > elems.ext_supp_rates_len)
+			clen = elems.ext_supp_rates_len;
+		memcpy(&bss->supp_rates[bss->supp_rates_len],
+		       elems.ext_supp_rates, clen);
+		bss->supp_rates_len += clen;
+	}
+
+	if (elems.wpa &&
+	    (!bss->wpa_ie || bss->wpa_ie_len != elems.wpa_len ||
+	     memcmp(bss->wpa_ie, elems.wpa, elems.wpa_len))) {
+		kfree(bss->wpa_ie);
+		bss->wpa_ie = kmalloc(elems.wpa_len + 2, GFP_ATOMIC);
+		if (bss->wpa_ie) {
+			memcpy(bss->wpa_ie, elems.wpa - 2, elems.wpa_len + 2);
+			bss->wpa_ie_len = elems.wpa_len + 2;
+		} else
+			bss->wpa_ie_len = 0;
+	} else if (!elems.wpa && bss->wpa_ie) {
+		kfree(bss->wpa_ie);
+		bss->wpa_ie = NULL;
+		bss->wpa_ie_len = 0;
+	}
+
+	if (elems.rsn &&
+	    (!bss->rsn_ie || bss->rsn_ie_len != elems.rsn_len ||
+	     memcmp(bss->rsn_ie, elems.rsn, elems.rsn_len))) {
+		kfree(bss->rsn_ie);
+		bss->rsn_ie = kmalloc(elems.rsn_len + 2, GFP_ATOMIC);
+		if (bss->rsn_ie) {
+			memcpy(bss->rsn_ie, elems.rsn - 2, elems.rsn_len + 2);
+			bss->rsn_ie_len = elems.rsn_len + 2;
+		} else
+			bss->rsn_ie_len = 0;
+	} else if (!elems.rsn && bss->rsn_ie) {
+		kfree(bss->rsn_ie);
+		bss->rsn_ie = NULL;
+		bss->rsn_ie_len = 0;
+	}
+
+	if (elems.wmm_param &&
+	    (!bss->wmm_ie || bss->wmm_ie_len != elems.wmm_param_len ||
+	     memcmp(bss->wmm_ie, elems.wmm_param, elems.wmm_param_len))) {
+		kfree(bss->wmm_ie);
+		bss->wmm_ie = kmalloc(elems.wmm_param_len + 2, GFP_ATOMIC);
+		if (bss->wmm_ie) {
+			memcpy(bss->wmm_ie, elems.wmm_param - 2,
+			       elems.wmm_param_len + 2);
+			bss->wmm_ie_len = elems.wmm_param_len + 2;
+		} else
+			bss->wmm_ie_len = 0;
+	} else if (!elems.wmm_param && bss->wmm_ie) {
+		kfree(bss->wmm_ie);
+		bss->wmm_ie = NULL;
+		bss->wmm_ie_len = 0;
+	}
+
+
+	bss->hw_mode = rx_status->phymode;
+	bss->channel = channel;
+	bss->freq = rx_status->freq;
+	if (channel != rx_status->channel &&
+	    (bss->hw_mode == MODE_IEEE80211G ||
+	     bss->hw_mode == MODE_IEEE80211B) &&
+	    channel >= 1 && channel <= 14) {
+		static const int freq_list[] = {
+			2412, 2417, 2422, 2427, 2432, 2437, 2442,
+			2447, 2452, 2457, 2462, 2467, 2472, 2484
+		};
+		/* IEEE 802.11g/b mode can receive packets from neighboring
+		 * channels, so map the channel into frequency. */
+		bss->freq = freq_list[channel - 1];
+	}
+	bss->timestamp = timestamp;
+	bss->last_update = jiffies;
+	bss->rssi = rx_status->ssi;
+	bss->signal = rx_status->signal;
+	bss->noise = rx_status->noise;
+	if (!beacon)
+		bss->probe_resp++;
+	ieee80211_rx_bss_put(dev, bss);
+}
+
+
+static void ieee80211_rx_mgmt_probe_resp(struct net_device *dev,
+					 struct ieee80211_mgmt *mgmt,
+					 size_t len,
+					 struct ieee80211_rx_status *rx_status)
+{
+	ieee80211_rx_bss_info(dev, mgmt, len, rx_status, 0);
+}
+
+
+static void ieee80211_rx_mgmt_beacon(struct net_device *dev,
+				     struct ieee80211_mgmt *mgmt,
+				     size_t len,
+				     struct ieee80211_rx_status *rx_status)
+{
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+	struct ieee80211_sub_if_data *sdata;
+	struct ieee80211_if_sta *ifsta;
+	int use_protection;
+	size_t baselen;
+	struct ieee802_11_elems elems;
+
+	ieee80211_rx_bss_info(dev, mgmt, len, rx_status, 1);
+
+	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	if (sdata->type != IEEE80211_IF_TYPE_STA)
+		return;
+	ifsta = &sdata->u.sta;
+
+	if (!ifsta->associated ||
+	    memcmp(ifsta->bssid, mgmt->bssid, ETH_ALEN) != 0)
+		return;
+
+	/* Process beacon from the current BSS */
+	baselen = (u8 *) mgmt->u.beacon.variable - (u8 *) mgmt;
+	if (baselen > len)
+		return;
+
+	if (ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen,
+				   &elems) == ParseFailed)
+		return;
+
+	use_protection = 0;
+	if (elems.erp_info && elems.erp_info_len >= 1) {
+		use_protection =
+			(elems.erp_info[0] & ERP_INFO_USE_PROTECTION) != 0;
+	}
+
+	if (use_protection != !!ifsta->use_protection) {
+		if (net_ratelimit()) {
+			printk(KERN_DEBUG "%s: CTS protection %s (BSSID="
+			       MAC_FMT ")\n",
+			       dev->name,
+			       use_protection ? "enabled" : "disabled",
+			       MAC_ARG(ifsta->bssid));
+		}
+		ifsta->use_protection = use_protection ? 1 : 0;
+		local->cts_protect_erp_frames = use_protection;
+	}
+
+	if (elems.wmm_param && ifsta->wmm_enabled) {
+		ieee80211_sta_wmm_params(dev, ifsta, elems.wmm_param,
+					 elems.wmm_param_len);
+	}
+}
+
+
+static void ieee80211_rx_mgmt_probe_req(struct net_device *dev,
+					struct ieee80211_if_sta *ifsta,
+					struct ieee80211_mgmt *mgmt,
+					size_t len,
+					struct ieee80211_rx_status *rx_status)
+{
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	int tx_last_beacon;
+	struct sk_buff *skb;
+	struct ieee80211_mgmt *resp;
+	u8 *pos, *end;
+
+	if (sdata->type != IEEE80211_IF_TYPE_IBSS ||
+	    ifsta->state != IEEE80211_IBSS_JOINED ||
+	    len < 24 + 2 || !ifsta->probe_resp)
+		return;
+
+	if (local->ops->tx_last_beacon)
+		tx_last_beacon = local->ops->tx_last_beacon(local_to_hw(local));
+	else
+		tx_last_beacon = 1;
+
+#ifdef CONFIG_MAC80211_IBSS_DEBUG
+	printk(KERN_DEBUG "%s: RX ProbeReq SA=" MAC_FMT " DA=" MAC_FMT " BSSID="
+	       MAC_FMT " (tx_last_beacon=%d)\n",
+	       dev->name, MAC_ARG(mgmt->sa), MAC_ARG(mgmt->da),
+	       MAC_ARG(mgmt->bssid), tx_last_beacon);
+#endif /* CONFIG_MAC80211_IBSS_DEBUG */
+
+	if (!tx_last_beacon)
+		return;
+
+	if (memcmp(mgmt->bssid, ifsta->bssid, ETH_ALEN) != 0 &&
+	    memcmp(mgmt->bssid, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) != 0)
+		return;
+
+	end = ((u8 *) mgmt) + len;
+	pos = mgmt->u.probe_req.variable;
+	if (pos[0] != WLAN_EID_SSID ||
+	    pos + 2 + pos[1] > end) {
+		if (net_ratelimit()) {
+			printk(KERN_DEBUG "%s: Invalid SSID IE in ProbeReq "
+			       "from " MAC_FMT "\n",
+			       dev->name, MAC_ARG(mgmt->sa));
+		}
+		return;
+	}
+	if (pos[1] != 0 &&
+	    (pos[1] != ifsta->ssid_len ||
+	     memcmp(pos + 2, ifsta->ssid, ifsta->ssid_len) != 0)) {
+		/* Ignore ProbeReq for foreign SSID */
+		return;
+	}
+
+	/* Reply with ProbeResp */
+	skb = skb_copy(ifsta->probe_resp, GFP_ATOMIC);
+	if (!skb)
+		return;
+
+	resp = (struct ieee80211_mgmt *) skb->data;
+	memcpy(resp->da, mgmt->sa, ETH_ALEN);
+#ifdef CONFIG_MAC80211_IBSS_DEBUG
+	printk(KERN_DEBUG "%s: Sending ProbeResp to " MAC_FMT "\n",
+	       dev->name, MAC_ARG(resp->da));
+#endif /* CONFIG_MAC80211_IBSS_DEBUG */
+	ieee80211_sta_tx(dev, skb, 0);
+}
+
+
+void ieee80211_sta_rx_mgmt(struct net_device *dev, struct sk_buff *skb,
+			   struct ieee80211_rx_status *rx_status)
+{
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+	struct ieee80211_sub_if_data *sdata;
+	struct ieee80211_if_sta *ifsta;
+	struct ieee80211_mgmt *mgmt;
+	u16 fc;
+
+	if (skb->len < 24)
+		goto fail;
+
+	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	ifsta = &sdata->u.sta;
+
+	mgmt = (struct ieee80211_mgmt *) skb->data;
+	fc = le16_to_cpu(mgmt->frame_control);
+
+	switch (fc & IEEE80211_FCTL_STYPE) {
+	case IEEE80211_STYPE_PROBE_REQ:
+	case IEEE80211_STYPE_PROBE_RESP:
+	case IEEE80211_STYPE_BEACON:
+		memcpy(skb->cb, rx_status, sizeof(*rx_status));
+	case IEEE80211_STYPE_AUTH:
+	case IEEE80211_STYPE_ASSOC_RESP:
+	case IEEE80211_STYPE_REASSOC_RESP:
+	case IEEE80211_STYPE_DEAUTH:
+	case IEEE80211_STYPE_DISASSOC:
+		skb_queue_tail(&ifsta->skb_queue, skb);
+		queue_work(local->hw.workqueue, &ifsta->work);
+		return;
+	default:
+		printk(KERN_DEBUG "%s: received unknown management frame - "
+		       "stype=%d\n", dev->name,
+		       (fc & IEEE80211_FCTL_STYPE) >> 4);
+		break;
+	}
+
+ fail:
+	kfree_skb(skb);
+}
+
+
+static void ieee80211_sta_rx_queued_mgmt(struct net_device *dev,
+					 struct sk_buff *skb)
+{
+	struct ieee80211_rx_status *rx_status;
+	struct ieee80211_sub_if_data *sdata;
+	struct ieee80211_if_sta *ifsta;
+	struct ieee80211_mgmt *mgmt;
+	u16 fc;
+
+	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	ifsta = &sdata->u.sta;
+
+	rx_status = (struct ieee80211_rx_status *) skb->cb;
+	mgmt = (struct ieee80211_mgmt *) skb->data;
+	fc = le16_to_cpu(mgmt->frame_control);
+
+	switch (fc & IEEE80211_FCTL_STYPE) {
+	case IEEE80211_STYPE_PROBE_REQ:
+		ieee80211_rx_mgmt_probe_req(dev, ifsta, mgmt, skb->len,
+					    rx_status);
+		break;
+	case IEEE80211_STYPE_PROBE_RESP:
+		ieee80211_rx_mgmt_probe_resp(dev, mgmt, skb->len, rx_status);
+		break;
+	case IEEE80211_STYPE_BEACON:
+		ieee80211_rx_mgmt_beacon(dev, mgmt, skb->len, rx_status);
+		break;
+	case IEEE80211_STYPE_AUTH:
+		ieee80211_rx_mgmt_auth(dev, ifsta, mgmt, skb->len);
+		break;
+	case IEEE80211_STYPE_ASSOC_RESP:
+		ieee80211_rx_mgmt_assoc_resp(dev, ifsta, mgmt, skb->len, 0);
+		break;
+	case IEEE80211_STYPE_REASSOC_RESP:
+		ieee80211_rx_mgmt_assoc_resp(dev, ifsta, mgmt, skb->len, 1);
+		break;
+	case IEEE80211_STYPE_DEAUTH:
+		ieee80211_rx_mgmt_deauth(dev, ifsta, mgmt, skb->len);
+		break;
+	case IEEE80211_STYPE_DISASSOC:
+		ieee80211_rx_mgmt_disassoc(dev, ifsta, mgmt, skb->len);
+		break;
+	}
+
+	kfree_skb(skb);
+}
+
+
+void ieee80211_sta_rx_scan(struct net_device *dev, struct sk_buff *skb,
+			   struct ieee80211_rx_status *rx_status)
+{
+	struct ieee80211_mgmt *mgmt;
+	u16 fc;
+
+	if (skb->len < 24) {
+		dev_kfree_skb(skb);
+		return;
+	}
+
+	mgmt = (struct ieee80211_mgmt *) skb->data;
+	fc = le16_to_cpu(mgmt->frame_control);
+
+	if ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) {
+		if ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PROBE_RESP) {
+			ieee80211_rx_mgmt_probe_resp(dev, mgmt,
+						     skb->len, rx_status);
+		} else if ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_BEACON) {
+			ieee80211_rx_mgmt_beacon(dev, mgmt, skb->len,
+						 rx_status);
+		}
+	}
+
+	dev_kfree_skb(skb);
+}
+
+
+static int ieee80211_sta_active_ibss(struct net_device *dev)
+{
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+	int active = 0;
+	struct sta_info *sta;
+
+	spin_lock_bh(&local->sta_lock);
+	list_for_each_entry(sta, &local->sta_list, list) {
+		if (sta->dev == dev &&
+		    time_after(sta->last_rx + IEEE80211_IBSS_MERGE_INTERVAL,
+			       jiffies)) {
+			active++;
+			break;
+		}
+	}
+	spin_unlock_bh(&local->sta_lock);
+
+	return active;
+}
+
+
+static void ieee80211_sta_expire(struct net_device *dev)
+{
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+	struct sta_info *sta, *tmp;
+
+	spin_lock_bh(&local->sta_lock);
+	list_for_each_entry_safe(sta, tmp, &local->sta_list, list)
+		if (time_after(jiffies, sta->last_rx +
+			       IEEE80211_IBSS_INACTIVITY_LIMIT)) {
+			printk(KERN_DEBUG "%s: expiring inactive STA " MAC_FMT
+			       "\n", dev->name, MAC_ARG(sta->addr));
+			sta_info_free(sta, 1);
+		}
+	spin_unlock_bh(&local->sta_lock);
+}
+
+
+static void ieee80211_sta_merge_ibss(struct net_device *dev,
+				     struct ieee80211_if_sta *ifsta)
+{
+	mod_timer(&ifsta->timer, jiffies + IEEE80211_IBSS_MERGE_INTERVAL);
+
+	ieee80211_sta_expire(dev);
+	if (ieee80211_sta_active_ibss(dev))
+		return;
+
+	printk(KERN_DEBUG "%s: No active IBSS STAs - trying to scan for other "
+	       "IBSS networks with same SSID (merge)\n", dev->name);
+	ieee80211_sta_req_scan(dev, ifsta->ssid, ifsta->ssid_len);
+}
+
+
+void ieee80211_sta_timer(unsigned long data)
+{
+	struct ieee80211_sub_if_data *sdata =
+		(struct ieee80211_sub_if_data *) data;
+	struct ieee80211_if_sta *ifsta = &sdata->u.sta;
+	struct ieee80211_local *local = wdev_priv(&sdata->wdev);
+
+	set_bit(IEEE80211_STA_REQ_RUN, &ifsta->request);
+	queue_work(local->hw.workqueue, &ifsta->work);
+}
+
+
+void ieee80211_sta_work(struct work_struct *work)
+{
+	struct ieee80211_sub_if_data *sdata =
+		container_of(work, struct ieee80211_sub_if_data, u.sta.work);
+	struct net_device *dev = sdata->dev;
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+	struct ieee80211_if_sta *ifsta;
+	struct sk_buff *skb;
+
+	if (!netif_running(dev))
+		return;
+
+	if (local->sta_scanning)
+		return;
+
+	if (sdata->type != IEEE80211_IF_TYPE_STA &&
+	    sdata->type != IEEE80211_IF_TYPE_IBSS) {
+		printk(KERN_DEBUG "%s: ieee80211_sta_work: non-STA interface "
+		       "(type=%d)\n", dev->name, sdata->type);
+		return;
+	}
+	ifsta = &sdata->u.sta;
+
+	while ((skb = skb_dequeue(&ifsta->skb_queue)))
+		ieee80211_sta_rx_queued_mgmt(dev, skb);
+
+	if (ifsta->state != IEEE80211_AUTHENTICATE &&
+	    ifsta->state != IEEE80211_ASSOCIATE &&
+	    test_and_clear_bit(IEEE80211_STA_REQ_SCAN, &ifsta->request)) {
+		ieee80211_sta_start_scan(dev, NULL, 0);
+		return;
+	}
+
+	if (test_and_clear_bit(IEEE80211_STA_REQ_AUTH, &ifsta->request)) {
+		if (ieee80211_sta_config_auth(dev, ifsta))
+			return;
+		clear_bit(IEEE80211_STA_REQ_RUN, &ifsta->request);
+	} else if (!test_and_clear_bit(IEEE80211_STA_REQ_RUN, &ifsta->request))
+		return;
+
+	switch (ifsta->state) {
+	case IEEE80211_DISABLED:
+		break;
+	case IEEE80211_AUTHENTICATE:
+		ieee80211_authenticate(dev, ifsta);
+		break;
+	case IEEE80211_ASSOCIATE:
+		ieee80211_associate(dev, ifsta);
+		break;
+	case IEEE80211_ASSOCIATED:
+		ieee80211_associated(dev, ifsta);
+		break;
+	case IEEE80211_IBSS_SEARCH:
+		ieee80211_sta_find_ibss(dev, ifsta);
+		break;
+	case IEEE80211_IBSS_JOINED:
+		ieee80211_sta_merge_ibss(dev, ifsta);
+		break;
+	default:
+		printk(KERN_DEBUG "ieee80211_sta_work: Unknown state %d\n",
+		       ifsta->state);
+		break;
+	}
+
+	if (ieee80211_privacy_mismatch(dev, ifsta)) {
+		printk(KERN_DEBUG "%s: privacy configuration mismatch and "
+		       "mixed-cell disabled - disassociate\n", dev->name);
+
+		ieee80211_send_disassoc(dev, ifsta, WLAN_REASON_UNSPECIFIED);
+		ieee80211_set_disassoc(dev, ifsta, 0);
+	}
+}
+
+
+static void ieee80211_sta_reset_auth(struct net_device *dev,
+				     struct ieee80211_if_sta *ifsta)
+{
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+
+	if (local->ops->reset_tsf) {
+		/* Reset own TSF to allow time synchronization work. */
+		local->ops->reset_tsf(local_to_hw(local));
+	}
+
+	ifsta->wmm_last_param_set = -1; /* allow any WMM update */
+
+
+	if (ifsta->auth_algs & IEEE80211_AUTH_ALG_OPEN)
+		ifsta->auth_alg = WLAN_AUTH_OPEN;
+	else if (ifsta->auth_algs & IEEE80211_AUTH_ALG_SHARED_KEY)
+		ifsta->auth_alg = WLAN_AUTH_SHARED_KEY;
+	else if (ifsta->auth_algs & IEEE80211_AUTH_ALG_LEAP)
+		ifsta->auth_alg = WLAN_AUTH_LEAP;
+	else
+		ifsta->auth_alg = WLAN_AUTH_OPEN;
+	printk(KERN_DEBUG "%s: Initial auth_alg=%d\n", dev->name,
+	       ifsta->auth_alg);
+	ifsta->auth_transaction = -1;
+	ifsta->associated = ifsta->auth_tries = ifsta->assoc_tries = 0;
+	netif_carrier_off(dev);
+}
+
+
+void ieee80211_sta_req_auth(struct net_device *dev,
+			    struct ieee80211_if_sta *ifsta)
+{
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+
+	if (sdata->type != IEEE80211_IF_TYPE_STA)
+		return;
+
+	if ((ifsta->bssid_set || ifsta->auto_bssid_sel) &&
+	    (ifsta->ssid_set || ifsta->auto_ssid_sel)) {
+		set_bit(IEEE80211_STA_REQ_AUTH, &ifsta->request);
+		queue_work(local->hw.workqueue, &ifsta->work);
+	}
+}
+
+static int ieee80211_sta_match_ssid(struct ieee80211_if_sta *ifsta,
+				    const char *ssid, int ssid_len)
+{
+	int tmp, hidden_ssid;
+
+	if (!memcmp(ifsta->ssid, ssid, ssid_len))
+		return 1;
+
+	if (ifsta->auto_bssid_sel)
+		return 0;
+
+	hidden_ssid = 1;
+	tmp = ssid_len;
+	while (tmp--) {
+		if (ssid[tmp] != '\0') {
+			hidden_ssid = 0;
+			break;
+		}
+	}
+
+	if (hidden_ssid && ifsta->ssid_len == ssid_len)
+		return 1;
+
+	if (ssid_len == 1 && ssid[0] == ' ')
+		return 1;
+
+	return 0;
+}
+
+static int ieee80211_sta_config_auth(struct net_device *dev,
+				     struct ieee80211_if_sta *ifsta)
+{
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	struct ieee80211_sta_bss *bss, *selected = NULL;
+	int top_rssi = 0, freq;
+
+	rtnl_lock();
+
+	if (!ifsta->auto_channel_sel && !ifsta->auto_bssid_sel &&
+	    !ifsta->auto_ssid_sel) {
+		ifsta->state = IEEE80211_AUTHENTICATE;
+		rtnl_unlock();
+		ieee80211_sta_reset_auth(dev, ifsta);
+		return 0;
+	}
+
+	spin_lock_bh(&local->sta_bss_lock);
+	freq = local->oper_channel->freq;
+	list_for_each_entry(bss, &local->sta_bss_list, list) {
+		if (!(bss->capability & WLAN_CAPABILITY_ESS))
+			continue;
+
+		if (!!(bss->capability & WLAN_CAPABILITY_PRIVACY) ^
+		    !!sdata->default_key)
+			continue;
+
+		if (!ifsta->auto_channel_sel && bss->freq != freq)
+			continue;
+
+		if (!ifsta->auto_bssid_sel &&
+		    memcmp(bss->bssid, ifsta->bssid, ETH_ALEN))
+			continue;
+
+		if (!ifsta->auto_ssid_sel &&
+		    !ieee80211_sta_match_ssid(ifsta, bss->ssid, bss->ssid_len))
+			continue;
+
+		if (!selected || top_rssi < bss->rssi) {
+			selected = bss;
+			top_rssi = bss->rssi;
+		}
+	}
+	if (selected)
+		atomic_inc(&selected->users);
+	spin_unlock_bh(&local->sta_bss_lock);
+
+	if (selected) {
+		ieee80211_set_channel(local, -1, selected->freq);
+		if (!ifsta->ssid_set)
+			ieee80211_sta_set_ssid(dev, selected->ssid,
+					       selected->ssid_len);
+		ieee80211_sta_set_bssid(dev, selected->bssid);
+		ieee80211_rx_bss_put(dev, selected);
+		ifsta->state = IEEE80211_AUTHENTICATE;
+		rtnl_unlock();
+		ieee80211_sta_reset_auth(dev, ifsta);
+		return 0;
+	} else {
+		if (ifsta->state != IEEE80211_AUTHENTICATE) {
+			ieee80211_sta_start_scan(dev, NULL, 0);
+			ifsta->state = IEEE80211_AUTHENTICATE;
+			set_bit(IEEE80211_STA_REQ_AUTH, &ifsta->request);
+		} else
+			ifsta->state = IEEE80211_DISABLED;
+	}
+	rtnl_unlock();
+	return -1;
+}
+
+static int ieee80211_sta_join_ibss(struct net_device *dev,
+				   struct ieee80211_if_sta *ifsta,
+				   struct ieee80211_sta_bss *bss)
+{
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+	int res, rates, i, j;
+	struct sk_buff *skb;
+	struct ieee80211_mgmt *mgmt;
+	struct ieee80211_tx_control control;
+	struct ieee80211_rate *rate;
+	struct ieee80211_hw_mode *mode;
+	struct rate_control_extra extra;
+	u8 *pos;
+	struct ieee80211_sub_if_data *sdata;
+
+	/* Remove possible STA entries from other IBSS networks. */
+	sta_info_flush(local, NULL);
+
+	if (local->ops->reset_tsf) {
+		/* Reset own TSF to allow time synchronization work. */
+		local->ops->reset_tsf(local_to_hw(local));
+	}
+	memcpy(ifsta->bssid, bss->bssid, ETH_ALEN);
+	res = ieee80211_if_config(dev);
+	if (res)
+		return res;
+
+	local->hw.conf.beacon_int = bss->beacon_int >= 10 ? bss->beacon_int : 10;
+
+	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	sdata->drop_unencrypted = bss->capability &
+		WLAN_CAPABILITY_PRIVACY ? 1 : 0;
+
+	res = ieee80211_set_channel(local, -1, bss->freq);
+
+	if (!(local->oper_channel->flag & IEEE80211_CHAN_W_IBSS)) {
+		printk(KERN_DEBUG "%s: IBSS not allowed on channel %d "
+		       "(%d MHz)\n", dev->name, local->hw.conf.channel,
+		       local->hw.conf.freq);
+		return -1;
+	}
+
+	/* Set beacon template based on scan results */
+	skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400);
+	do {
+		if (!skb)
+			break;
+
+		skb_reserve(skb, local->hw.extra_tx_headroom);
+
+		mgmt = (struct ieee80211_mgmt *)
+			skb_put(skb, 24 + sizeof(mgmt->u.beacon));
+		memset(mgmt, 0, 24 + sizeof(mgmt->u.beacon));
+		mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
+						   IEEE80211_STYPE_BEACON);
+		memset(mgmt->da, 0xff, ETH_ALEN);
+		memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
+		memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
+		mgmt->u.beacon.beacon_int =
+			cpu_to_le16(local->hw.conf.beacon_int);
+		mgmt->u.beacon.capab_info = cpu_to_le16(bss->capability);
+
+		pos = skb_put(skb, 2 + ifsta->ssid_len);
+		*pos++ = WLAN_EID_SSID;
+		*pos++ = ifsta->ssid_len;
+		memcpy(pos, ifsta->ssid, ifsta->ssid_len);
+
+		rates = bss->supp_rates_len;
+		if (rates > 8)
+			rates = 8;
+		pos = skb_put(skb, 2 + rates);
+		*pos++ = WLAN_EID_SUPP_RATES;
+		*pos++ = rates;
+		memcpy(pos, bss->supp_rates, rates);
+
+		pos = skb_put(skb, 2 + 1);
+		*pos++ = WLAN_EID_DS_PARAMS;
+		*pos++ = 1;
+		*pos++ = bss->channel;
+
+		pos = skb_put(skb, 2 + 2);
+		*pos++ = WLAN_EID_IBSS_PARAMS;
+		*pos++ = 2;
+		/* FIX: set ATIM window based on scan results */
+		*pos++ = 0;
+		*pos++ = 0;
+
+		if (bss->supp_rates_len > 8) {
+			rates = bss->supp_rates_len - 8;
+			pos = skb_put(skb, 2 + rates);
+			*pos++ = WLAN_EID_EXT_SUPP_RATES;
+			*pos++ = rates;
+			memcpy(pos, &bss->supp_rates[8], rates);
+		}
+
+		memset(&control, 0, sizeof(control));
+		memset(&extra, 0, sizeof(extra));
+		extra.mode = local->oper_hw_mode;
+		rate = rate_control_get_rate(local, dev, skb, &extra);
+		if (!rate) {
+			printk(KERN_DEBUG "%s: Failed to determine TX rate "
+			       "for IBSS beacon\n", dev->name);
+			break;
+		}
+		control.tx_rate = (local->short_preamble &&
+				   (rate->flags & IEEE80211_RATE_PREAMBLE2)) ?
+			rate->val2 : rate->val;
+		control.antenna_sel_tx = local->hw.conf.antenna_sel_tx;
+		control.power_level = local->hw.conf.power_level;
+		control.flags |= IEEE80211_TXCTL_NO_ACK;
+		control.retry_limit = 1;
+
+		ifsta->probe_resp = skb_copy(skb, GFP_ATOMIC);
+		if (ifsta->probe_resp) {
+			mgmt = (struct ieee80211_mgmt *)
+				ifsta->probe_resp->data;
+			mgmt->frame_control =
+				IEEE80211_FC(IEEE80211_FTYPE_MGMT,
+					     IEEE80211_STYPE_PROBE_RESP);
+		} else {
+			printk(KERN_DEBUG "%s: Could not allocate ProbeResp "
+			       "template for IBSS\n", dev->name);
+		}
+
+		if (local->ops->beacon_update &&
+		    local->ops->beacon_update(local_to_hw(local),
+					     skb, &control) == 0) {
+			printk(KERN_DEBUG "%s: Configured IBSS beacon "
+			       "template based on scan results\n", dev->name);
+			skb = NULL;
+		}
+
+		rates = 0;
+		mode = local->oper_hw_mode;
+		for (i = 0; i < bss->supp_rates_len; i++) {
+			int bitrate = (bss->supp_rates[i] & 0x7f) * 5;
+			if (mode->mode == MODE_ATHEROS_TURBO)
+				bitrate *= 2;
+			for (j = 0; j < mode->num_rates; j++)
+				if (mode->rates[j].rate == bitrate)
+					rates |= BIT(j);
+		}
+		ifsta->supp_rates_bits = rates;
+	} while (0);
+
+	if (skb) {
+		printk(KERN_DEBUG "%s: Failed to configure IBSS beacon "
+		       "template\n", dev->name);
+		dev_kfree_skb(skb);
+	}
+
+	ifsta->state = IEEE80211_IBSS_JOINED;
+	mod_timer(&ifsta->timer, jiffies + IEEE80211_IBSS_MERGE_INTERVAL);
+
+	ieee80211_rx_bss_put(dev, bss);
+
+	return res;
+}
+
+
+static int ieee80211_sta_create_ibss(struct net_device *dev,
+				     struct ieee80211_if_sta *ifsta)
+{
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+	struct ieee80211_sta_bss *bss;
+	struct ieee80211_sub_if_data *sdata;
+	struct ieee80211_hw_mode *mode;
+	u8 bssid[ETH_ALEN], *pos;
+	int i;
+
+#if 0
+	/* Easier testing, use fixed BSSID. */
+	memset(bssid, 0xfe, ETH_ALEN);
+#else
+	/* Generate random, not broadcast, locally administered BSSID. Mix in
+	 * own MAC address to make sure that devices that do not have proper
+	 * random number generator get different BSSID. */
+	get_random_bytes(bssid, ETH_ALEN);
+	for (i = 0; i < ETH_ALEN; i++)
+		bssid[i] ^= dev->dev_addr[i];
+	bssid[0] &= ~0x01;
+	bssid[0] |= 0x02;
+#endif
+
+	printk(KERN_DEBUG "%s: Creating new IBSS network, BSSID " MAC_FMT "\n",
+	       dev->name, MAC_ARG(bssid));
+
+	bss = ieee80211_rx_bss_add(dev, bssid);
+	if (!bss)
+		return -ENOMEM;
+
+	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	mode = local->oper_hw_mode;
+
+	if (local->hw.conf.beacon_int == 0)
+		local->hw.conf.beacon_int = 100;
+	bss->beacon_int = local->hw.conf.beacon_int;
+	bss->hw_mode = local->hw.conf.phymode;
+	bss->channel = local->hw.conf.channel;
+	bss->freq = local->hw.conf.freq;
+	bss->last_update = jiffies;
+	bss->capability = WLAN_CAPABILITY_IBSS;
+	if (sdata->default_key) {
+		bss->capability |= WLAN_CAPABILITY_PRIVACY;
+	} else
+		sdata->drop_unencrypted = 0;
+	bss->supp_rates_len = mode->num_rates;
+	pos = bss->supp_rates;
+	for (i = 0; i < mode->num_rates; i++) {
+		int rate = mode->rates[i].rate;
+		if (mode->mode == MODE_ATHEROS_TURBO)
+			rate /= 2;
+		*pos++ = (u8) (rate / 5);
+	}
+
+	return ieee80211_sta_join_ibss(dev, ifsta, bss);
+}
+
+
+static int ieee80211_sta_find_ibss(struct net_device *dev,
+				   struct ieee80211_if_sta *ifsta)
+{
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+	struct ieee80211_sta_bss *bss;
+	int found = 0;
+	u8 bssid[ETH_ALEN];
+	int active_ibss;
+
+	if (ifsta->ssid_len == 0)
+		return -EINVAL;
+
+	active_ibss = ieee80211_sta_active_ibss(dev);
+#ifdef CONFIG_MAC80211_IBSS_DEBUG
+	printk(KERN_DEBUG "%s: sta_find_ibss (active_ibss=%d)\n",
+	       dev->name, active_ibss);
+#endif /* CONFIG_MAC80211_IBSS_DEBUG */
+	spin_lock_bh(&local->sta_bss_lock);
+	list_for_each_entry(bss, &local->sta_bss_list, list) {
+		if (ifsta->ssid_len != bss->ssid_len ||
+		    memcmp(ifsta->ssid, bss->ssid, bss->ssid_len) != 0
+		    || !(bss->capability & WLAN_CAPABILITY_IBSS))
+			continue;
+#ifdef CONFIG_MAC80211_IBSS_DEBUG
+		printk(KERN_DEBUG "   bssid=" MAC_FMT " found\n",
+		       MAC_ARG(bss->bssid));
+#endif /* CONFIG_MAC80211_IBSS_DEBUG */
+		memcpy(bssid, bss->bssid, ETH_ALEN);
+		found = 1;
+		if (active_ibss || memcmp(bssid, ifsta->bssid, ETH_ALEN) != 0)
+			break;
+	}
+	spin_unlock_bh(&local->sta_bss_lock);
+
+#ifdef CONFIG_MAC80211_IBSS_DEBUG
+	printk(KERN_DEBUG "   sta_find_ibss: selected " MAC_FMT " current "
+	       MAC_FMT "\n", MAC_ARG(bssid), MAC_ARG(ifsta->bssid));
+#endif /* CONFIG_MAC80211_IBSS_DEBUG */
+	if (found && memcmp(ifsta->bssid, bssid, ETH_ALEN) != 0 &&
+	    (bss = ieee80211_rx_bss_get(dev, bssid))) {
+		printk(KERN_DEBUG "%s: Selected IBSS BSSID " MAC_FMT
+		       " based on configured SSID\n",
+		       dev->name, MAC_ARG(bssid));
+		return ieee80211_sta_join_ibss(dev, ifsta, bss);
+	}
+#ifdef CONFIG_MAC80211_IBSS_DEBUG
+	printk(KERN_DEBUG "   did not try to join ibss\n");
+#endif /* CONFIG_MAC80211_IBSS_DEBUG */
+
+	/* Selected IBSS not found in current scan results - try to scan */
+	if (ifsta->state == IEEE80211_IBSS_JOINED &&
+	    !ieee80211_sta_active_ibss(dev)) {
+		mod_timer(&ifsta->timer, jiffies +
+				      IEEE80211_IBSS_MERGE_INTERVAL);
+	} else if (time_after(jiffies, local->last_scan_completed +
+			      IEEE80211_SCAN_INTERVAL)) {
+		printk(KERN_DEBUG "%s: Trigger new scan to find an IBSS to "
+		       "join\n", dev->name);
+		return ieee80211_sta_req_scan(dev, ifsta->ssid,
+					      ifsta->ssid_len);
+	} else if (ifsta->state != IEEE80211_IBSS_JOINED) {
+		int interval = IEEE80211_SCAN_INTERVAL;
+
+		if (time_after(jiffies, ifsta->ibss_join_req +
+			       IEEE80211_IBSS_JOIN_TIMEOUT)) {
+			if (ifsta->create_ibss &&
+			    local->oper_channel->flag & IEEE80211_CHAN_W_IBSS)
+				return ieee80211_sta_create_ibss(dev, ifsta);
+			if (ifsta->create_ibss) {
+				printk(KERN_DEBUG "%s: IBSS not allowed on the"
+				       " configured channel %d (%d MHz)\n",
+				       dev->name, local->hw.conf.channel,
+				       local->hw.conf.freq);
+			}
+
+			/* No IBSS found - decrease scan interval and continue
+			 * scanning. */
+			interval = IEEE80211_SCAN_INTERVAL_SLOW;
+		}
+
+		ifsta->state = IEEE80211_IBSS_SEARCH;
+		mod_timer(&ifsta->timer, jiffies + interval);
+		return 0;
+	}
+
+	return 0;
+}
+
+
+int ieee80211_sta_set_ssid(struct net_device *dev, char *ssid, size_t len)
+{
+	struct ieee80211_sub_if_data *sdata;
+	struct ieee80211_if_sta *ifsta;
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+
+	if (len > IEEE80211_MAX_SSID_LEN)
+		return -EINVAL;
+
+	/* TODO: This should always be done for IBSS, even if IEEE80211_QOS is
+	 * not defined. */
+	if (local->ops->conf_tx) {
+		struct ieee80211_tx_queue_params qparam;
+		int i;
+
+		memset(&qparam, 0, sizeof(qparam));
+		/* TODO: are these ok defaults for all hw_modes? */
+		qparam.aifs = 2;
+		qparam.cw_min =
+			local->hw.conf.phymode == MODE_IEEE80211B ? 31 : 15;
+		qparam.cw_max = 1023;
+		qparam.burst_time = 0;
+		for (i = IEEE80211_TX_QUEUE_DATA0; i < NUM_TX_DATA_QUEUES; i++)
+		{
+			local->ops->conf_tx(local_to_hw(local),
+					   i + IEEE80211_TX_QUEUE_DATA0,
+					   &qparam);
+		}
+		/* IBSS uses different parameters for Beacon sending */
+		qparam.cw_min++;
+		qparam.cw_min *= 2;
+		qparam.cw_min--;
+		local->ops->conf_tx(local_to_hw(local),
+				   IEEE80211_TX_QUEUE_BEACON, &qparam);
+	}
+
+	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	ifsta = &sdata->u.sta;
+
+	if (ifsta->ssid_len != len || memcmp(ifsta->ssid, ssid, len) != 0)
+		ifsta->prev_bssid_set = 0;
+	memcpy(ifsta->ssid, ssid, len);
+	memset(ifsta->ssid + len, 0, IEEE80211_MAX_SSID_LEN - len);
+	ifsta->ssid_len = len;
+
+	ifsta->ssid_set = len ? 1 : 0;
+	if (sdata->type == IEEE80211_IF_TYPE_IBSS && !ifsta->bssid_set) {
+		ifsta->ibss_join_req = jiffies;
+		ifsta->state = IEEE80211_IBSS_SEARCH;
+		return ieee80211_sta_find_ibss(dev, ifsta);
+	}
+	return 0;
+}
+
+
+int ieee80211_sta_get_ssid(struct net_device *dev, char *ssid, size_t *len)
+{
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	struct ieee80211_if_sta *ifsta = &sdata->u.sta;
+	memcpy(ssid, ifsta->ssid, ifsta->ssid_len);
+	*len = ifsta->ssid_len;
+	return 0;
+}
+
+
+int ieee80211_sta_set_bssid(struct net_device *dev, u8 *bssid)
+{
+	struct ieee80211_sub_if_data *sdata;
+	struct ieee80211_if_sta *ifsta;
+	int res;
+
+	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	ifsta = &sdata->u.sta;
+
+	if (memcmp(ifsta->bssid, bssid, ETH_ALEN) != 0) {
+		memcpy(ifsta->bssid, bssid, ETH_ALEN);
+		res = ieee80211_if_config(dev);
+		if (res) {
+			printk(KERN_DEBUG "%s: Failed to config new BSSID to "
+			       "the low-level driver\n", dev->name);
+			return res;
+		}
+	}
+
+	if (!is_valid_ether_addr(bssid))
+		ifsta->bssid_set = 0;
+	else
+		ifsta->bssid_set = 1;
+	return 0;
+}
+
+
+static void ieee80211_send_nullfunc(struct ieee80211_local *local,
+				    struct ieee80211_sub_if_data *sdata,
+				    int powersave)
+{
+	struct sk_buff *skb;
+	struct ieee80211_hdr *nullfunc;
+	u16 fc;
+
+	skb = dev_alloc_skb(local->hw.extra_tx_headroom + 24);
+	if (!skb) {
+		printk(KERN_DEBUG "%s: failed to allocate buffer for nullfunc "
+		       "frame\n", sdata->dev->name);
+		return;
+	}
+	skb_reserve(skb, local->hw.extra_tx_headroom);
+
+	nullfunc = (struct ieee80211_hdr *) skb_put(skb, 24);
+	memset(nullfunc, 0, 24);
+	fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC |
+	     IEEE80211_FCTL_TODS;
+	if (powersave)
+		fc |= IEEE80211_FCTL_PM;
+	nullfunc->frame_control = cpu_to_le16(fc);
+	memcpy(nullfunc->addr1, sdata->u.sta.bssid, ETH_ALEN);
+	memcpy(nullfunc->addr2, sdata->dev->dev_addr, ETH_ALEN);
+	memcpy(nullfunc->addr3, sdata->u.sta.bssid, ETH_ALEN);
+
+	ieee80211_sta_tx(sdata->dev, skb, 0);
+}
+
+
+void ieee80211_scan_completed(struct ieee80211_hw *hw)
+{
+	struct ieee80211_local *local = hw_to_local(hw);
+	struct net_device *dev = local->scan_dev;
+	struct ieee80211_sub_if_data *sdata;
+	union iwreq_data wrqu;
+
+	local->last_scan_completed = jiffies;
+	wmb();
+	local->sta_scanning = 0;
+
+	if (ieee80211_hw_config(local))
+		printk(KERN_DEBUG "%s: failed to restore operational"
+		       "channel after scan\n", dev->name);
+
+	if (!(local->hw.flags & IEEE80211_HW_NO_PROBE_FILTERING) &&
+	    ieee80211_if_config(dev))
+		printk(KERN_DEBUG "%s: failed to restore operational"
+		       "BSSID after scan\n", dev->name);
+
+	memset(&wrqu, 0, sizeof(wrqu));
+	wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL);
+
+	read_lock(&local->sub_if_lock);
+	list_for_each_entry(sdata, &local->sub_if_list, list) {
+		if (sdata->type == IEEE80211_IF_TYPE_STA) {
+			if (sdata->u.sta.associated)
+				ieee80211_send_nullfunc(local, sdata, 0);
+			ieee80211_sta_timer((unsigned long)sdata);
+		}
+		netif_wake_queue(sdata->dev);
+	}
+	read_unlock(&local->sub_if_lock);
+
+	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	if (sdata->type == IEEE80211_IF_TYPE_IBSS) {
+		struct ieee80211_if_sta *ifsta = &sdata->u.sta;
+		if (!ifsta->bssid_set ||
+		    (!ifsta->state == IEEE80211_IBSS_JOINED &&
+		    !ieee80211_sta_active_ibss(dev)))
+			ieee80211_sta_find_ibss(dev, ifsta);
+	}
+}
+EXPORT_SYMBOL(ieee80211_scan_completed);
+
+void ieee80211_sta_scan_work(struct work_struct *work)
+{
+	struct ieee80211_local *local =
+		container_of(work, struct ieee80211_local, scan_work.work);
+	struct net_device *dev = local->scan_dev;
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	struct ieee80211_hw_mode *mode;
+	struct ieee80211_channel *chan;
+	int skip;
+	unsigned long next_delay = 0;
+
+	if (!local->sta_scanning)
+		return;
+
+	switch (local->scan_state) {
+	case SCAN_SET_CHANNEL:
+		mode = local->scan_hw_mode;
+		if (local->scan_hw_mode->list.next == &local->modes_list &&
+		    local->scan_channel_idx >= mode->num_channels) {
+			ieee80211_scan_completed(local_to_hw(local));
+			return;
+		}
+		skip = !(local->enabled_modes & (1 << mode->mode));
+		chan = &mode->channels[local->scan_channel_idx];
+		if (!(chan->flag & IEEE80211_CHAN_W_SCAN) ||
+		    (sdata->type == IEEE80211_IF_TYPE_IBSS &&
+		     !(chan->flag & IEEE80211_CHAN_W_IBSS)) ||
+		    (local->hw_modes & local->enabled_modes &
+		     (1 << MODE_IEEE80211G) && mode->mode == MODE_IEEE80211B))
+			skip = 1;
+
+		if (!skip) {
+#if 0
+			printk(KERN_DEBUG "%s: scan channel %d (%d MHz)\n",
+			       dev->name, chan->chan, chan->freq);
+#endif
+
+			local->scan_channel = chan;
+			if (ieee80211_hw_config(local)) {
+				printk(KERN_DEBUG "%s: failed to set channel "
+				       "%d (%d MHz) for scan\n", dev->name,
+				       chan->chan, chan->freq);
+				skip = 1;
+			}
+		}
+
+		local->scan_channel_idx++;
+		if (local->scan_channel_idx >= local->scan_hw_mode->num_channels) {
+			if (local->scan_hw_mode->list.next != &local->modes_list) {
+				local->scan_hw_mode = list_entry(local->scan_hw_mode->list.next,
+								 struct ieee80211_hw_mode,
+								 list);
+				local->scan_channel_idx = 0;
+			}
+		}
+
+		if (skip)
+			break;
+
+		next_delay = IEEE80211_PROBE_DELAY +
+			     usecs_to_jiffies(local->hw.channel_change_time);
+		local->scan_state = SCAN_SEND_PROBE;
+		break;
+	case SCAN_SEND_PROBE:
+		if (local->scan_channel->flag & IEEE80211_CHAN_W_ACTIVE_SCAN) {
+			ieee80211_send_probe_req(dev, NULL, local->scan_ssid,
+						 local->scan_ssid_len);
+			next_delay = IEEE80211_CHANNEL_TIME;
+		} else
+			next_delay = IEEE80211_PASSIVE_CHANNEL_TIME;
+		local->scan_state = SCAN_SET_CHANNEL;
+		break;
+	}
+
+	if (local->sta_scanning)
+		queue_delayed_work(local->hw.workqueue, &local->scan_work,
+				   next_delay);
+}
+
+
+static int ieee80211_sta_start_scan(struct net_device *dev,
+				    u8 *ssid, size_t ssid_len)
+{
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+	struct ieee80211_sub_if_data *sdata;
+
+	if (ssid_len > IEEE80211_MAX_SSID_LEN)
+		return -EINVAL;
+
+	/* MLME-SCAN.request (page 118)  page 144 (11.1.3.1)
+	 * BSSType: INFRASTRUCTURE, INDEPENDENT, ANY_BSS
+	 * BSSID: MACAddress
+	 * SSID
+	 * ScanType: ACTIVE, PASSIVE
+	 * ProbeDelay: delay (in microseconds) to be used prior to transmitting
+	 *    a Probe frame during active scanning
+	 * ChannelList
+	 * MinChannelTime (>= ProbeDelay), in TU
+	 * MaxChannelTime: (>= MinChannelTime), in TU
+	 */
+
+	 /* MLME-SCAN.confirm
+	  * BSSDescriptionSet
+	  * ResultCode: SUCCESS, INVALID_PARAMETERS
+	 */
+
+	if (local->sta_scanning) {
+		if (local->scan_dev == dev)
+			return 0;
+		return -EBUSY;
+	}
+
+	if (local->ops->hw_scan) {
+		int rc = local->ops->hw_scan(local_to_hw(local),
+					    ssid, ssid_len);
+		if (!rc) {
+			local->sta_scanning = 1;
+			local->scan_dev = dev;
+		}
+		return rc;
+	}
+
+	local->sta_scanning = 1;
+
+	read_lock(&local->sub_if_lock);
+	list_for_each_entry(sdata, &local->sub_if_list, list) {
+		netif_stop_queue(sdata->dev);
+		if (sdata->type == IEEE80211_IF_TYPE_STA &&
+		    sdata->u.sta.associated)
+			ieee80211_send_nullfunc(local, sdata, 1);
+	}
+	read_unlock(&local->sub_if_lock);
+
+	if (ssid) {
+		local->scan_ssid_len = ssid_len;
+		memcpy(local->scan_ssid, ssid, ssid_len);
+	} else
+		local->scan_ssid_len = 0;
+	local->scan_state = SCAN_SET_CHANNEL;
+	local->scan_hw_mode = list_entry(local->modes_list.next,
+					 struct ieee80211_hw_mode,
+					 list);
+	local->scan_channel_idx = 0;
+	local->scan_dev = dev;
+
+	if (!(local->hw.flags & IEEE80211_HW_NO_PROBE_FILTERING) &&
+	    ieee80211_if_config(dev))
+		printk(KERN_DEBUG "%s: failed to set BSSID for scan\n",
+		       dev->name);
+
+	/* TODO: start scan as soon as all nullfunc frames are ACKed */
+	queue_delayed_work(local->hw.workqueue, &local->scan_work,
+			   IEEE80211_CHANNEL_TIME);
+
+	return 0;
+}
+
+
+int ieee80211_sta_req_scan(struct net_device *dev, u8 *ssid, size_t ssid_len)
+{
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	struct ieee80211_if_sta *ifsta = &sdata->u.sta;
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+
+	if (sdata->type != IEEE80211_IF_TYPE_STA)
+		return ieee80211_sta_start_scan(dev, ssid, ssid_len);
+
+	if (local->sta_scanning) {
+		if (local->scan_dev == dev)
+			return 0;
+		return -EBUSY;
+	}
+
+	set_bit(IEEE80211_STA_REQ_SCAN, &ifsta->request);
+	queue_work(local->hw.workqueue, &ifsta->work);
+	return 0;
+}
+
+static char *
+ieee80211_sta_scan_result(struct net_device *dev,
+			  struct ieee80211_sta_bss *bss,
+			  char *current_ev, char *end_buf)
+{
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+	struct iw_event iwe;
+
+	if (time_after(jiffies,
+		       bss->last_update + IEEE80211_SCAN_RESULT_EXPIRE))
+		return current_ev;
+
+	if (!(local->enabled_modes & (1 << bss->hw_mode)))
+		return current_ev;
+
+	if (local->scan_flags & IEEE80211_SCAN_WPA_ONLY &&
+	    !bss->wpa_ie && !bss->rsn_ie)
+		return current_ev;
+
+	if (local->scan_flags & IEEE80211_SCAN_MATCH_SSID &&
+	    (local->scan_ssid_len != bss->ssid_len ||
+	     memcmp(local->scan_ssid, bss->ssid, bss->ssid_len) != 0))
+		return current_ev;
+
+	memset(&iwe, 0, sizeof(iwe));
+	iwe.cmd = SIOCGIWAP;
+	iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
+	memcpy(iwe.u.ap_addr.sa_data, bss->bssid, ETH_ALEN);
+	current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
+					  IW_EV_ADDR_LEN);
+
+	memset(&iwe, 0, sizeof(iwe));
+	iwe.cmd = SIOCGIWESSID;
+	iwe.u.data.length = bss->ssid_len;
+	iwe.u.data.flags = 1;
+	current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe,
+					  bss->ssid);
+
+	if (bss->capability & (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS)) {
+		memset(&iwe, 0, sizeof(iwe));
+		iwe.cmd = SIOCGIWMODE;
+		if (bss->capability & WLAN_CAPABILITY_ESS)
+			iwe.u.mode = IW_MODE_MASTER;
+		else
+			iwe.u.mode = IW_MODE_ADHOC;
+		current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
+						  IW_EV_UINT_LEN);
+	}
+
+	memset(&iwe, 0, sizeof(iwe));
+	iwe.cmd = SIOCGIWFREQ;
+	iwe.u.freq.m = bss->channel;
+	iwe.u.freq.e = 0;
+	current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
+					  IW_EV_FREQ_LEN);
+	iwe.u.freq.m = bss->freq * 100000;
+	iwe.u.freq.e = 1;
+	current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
+					  IW_EV_FREQ_LEN);
+
+	memset(&iwe, 0, sizeof(iwe));
+	iwe.cmd = IWEVQUAL;
+	iwe.u.qual.qual = bss->signal;
+	iwe.u.qual.level = bss->rssi;
+	iwe.u.qual.noise = bss->noise;
+	iwe.u.qual.updated = local->wstats_flags;
+	current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
+					  IW_EV_QUAL_LEN);
+
+	memset(&iwe, 0, sizeof(iwe));
+	iwe.cmd = SIOCGIWENCODE;
+	if (bss->capability & WLAN_CAPABILITY_PRIVACY)
+		iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
+	else
+		iwe.u.data.flags = IW_ENCODE_DISABLED;
+	iwe.u.data.length = 0;
+	current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, "");
+
+	if (bss && bss->wpa_ie) {
+		memset(&iwe, 0, sizeof(iwe));
+		iwe.cmd = IWEVGENIE;
+		iwe.u.data.length = bss->wpa_ie_len;
+		current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe,
+						  bss->wpa_ie);
+	}
+
+	if (bss && bss->rsn_ie) {
+		memset(&iwe, 0, sizeof(iwe));
+		iwe.cmd = IWEVGENIE;
+		iwe.u.data.length = bss->rsn_ie_len;
+		current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe,
+						  bss->rsn_ie);
+	}
+
+	if (bss && bss->supp_rates_len > 0) {
+		/* display all supported rates in readable format */
+		char *p = current_ev + IW_EV_LCP_LEN;
+		int i;
+
+		memset(&iwe, 0, sizeof(iwe));
+		iwe.cmd = SIOCGIWRATE;
+		/* Those two flags are ignored... */
+		iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
+
+		for (i = 0; i < bss->supp_rates_len; i++) {
+			iwe.u.bitrate.value = ((bss->supp_rates[i] &
+							0x7f) * 500000);
+			p = iwe_stream_add_value(current_ev, p,
+					end_buf, &iwe, IW_EV_PARAM_LEN);
+		}
+		current_ev = p;
+	}
+
+	if (bss) {
+		char *buf;
+		buf = kmalloc(30, GFP_ATOMIC);
+		if (buf) {
+			memset(&iwe, 0, sizeof(iwe));
+			iwe.cmd = IWEVCUSTOM;
+			sprintf(buf, "tsf=%016llx", (unsigned long long)(bss->timestamp));
+			iwe.u.data.length = strlen(buf);
+			current_ev = iwe_stream_add_point(current_ev, end_buf,
+							  &iwe, buf);
+			kfree(buf);
+		}
+	}
+
+	do {
+		char *buf;
+
+		if (!(local->scan_flags & IEEE80211_SCAN_EXTRA_INFO))
+			break;
+
+		buf = kmalloc(100, GFP_ATOMIC);
+		if (!buf)
+			break;
+
+		memset(&iwe, 0, sizeof(iwe));
+		iwe.cmd = IWEVCUSTOM;
+		sprintf(buf, "bcn_int=%d", bss->beacon_int);
+		iwe.u.data.length = strlen(buf);
+		current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe,
+						  buf);
+
+		memset(&iwe, 0, sizeof(iwe));
+		iwe.cmd = IWEVCUSTOM;
+		sprintf(buf, "capab=0x%04x", bss->capability);
+		iwe.u.data.length = strlen(buf);
+		current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe,
+						  buf);
+
+		kfree(buf);
+		break;
+	} while (0);
+
+	return current_ev;
+}
+
+
+int ieee80211_sta_scan_results(struct net_device *dev, char *buf, size_t len)
+{
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+	char *current_ev = buf;
+	char *end_buf = buf + len;
+	struct ieee80211_sta_bss *bss;
+
+	spin_lock_bh(&local->sta_bss_lock);
+	list_for_each_entry(bss, &local->sta_bss_list, list) {
+		if (buf + len - current_ev <= IW_EV_ADDR_LEN) {
+			spin_unlock_bh(&local->sta_bss_lock);
+			return -E2BIG;
+		}
+		current_ev = ieee80211_sta_scan_result(dev, bss, current_ev,
+						       end_buf);
+	}
+	spin_unlock_bh(&local->sta_bss_lock);
+	return current_ev - buf;
+}
+
+
+int ieee80211_sta_set_extra_ie(struct net_device *dev, char *ie, size_t len)
+{
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	struct ieee80211_if_sta *ifsta = &sdata->u.sta;
+	kfree(ifsta->extra_ie);
+	if (len == 0) {
+		ifsta->extra_ie = NULL;
+		ifsta->extra_ie_len = 0;
+		return 0;
+	}
+	ifsta->extra_ie = kmalloc(len, GFP_KERNEL);
+	if (!ifsta->extra_ie) {
+		ifsta->extra_ie_len = 0;
+		return -ENOMEM;
+	}
+	memcpy(ifsta->extra_ie, ie, len);
+	ifsta->extra_ie_len = len;
+	return 0;
+}
+
+
+struct sta_info * ieee80211_ibss_add_sta(struct net_device *dev,
+					 struct sk_buff *skb, u8 *bssid,
+					 u8 *addr)
+{
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+	struct sta_info *sta;
+	struct ieee80211_sub_if_data *sdata = NULL;
+
+	/* TODO: Could consider removing the least recently used entry and
+	 * allow new one to be added. */
+	if (local->num_sta >= IEEE80211_IBSS_MAX_STA_ENTRIES) {
+		if (net_ratelimit()) {
+			printk(KERN_DEBUG "%s: No room for a new IBSS STA "
+			       "entry " MAC_FMT "\n", dev->name, MAC_ARG(addr));
+		}
+		return NULL;
+	}
+
+	printk(KERN_DEBUG "%s: Adding new IBSS station " MAC_FMT " (dev=%s)\n",
+	       local->mdev->name, MAC_ARG(addr), dev->name);
+
+	sta = sta_info_add(local, dev, addr, GFP_ATOMIC);
+	if (!sta)
+		return NULL;
+
+	sta->supp_rates = sdata->u.sta.supp_rates_bits;
+
+	rate_control_rate_init(sta, local);
+
+	return sta; /* caller will call sta_info_put() */
+}
+
+
+int ieee80211_sta_deauthenticate(struct net_device *dev, u16 reason)
+{
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	struct ieee80211_if_sta *ifsta = &sdata->u.sta;
+
+	printk(KERN_DEBUG "%s: deauthenticate(reason=%d)\n",
+	       dev->name, reason);
+
+	if (sdata->type != IEEE80211_IF_TYPE_STA &&
+	    sdata->type != IEEE80211_IF_TYPE_IBSS)
+		return -EINVAL;
+
+	ieee80211_send_deauth(dev, ifsta, reason);
+	ieee80211_set_disassoc(dev, ifsta, 1);
+	return 0;
+}
+
+
+int ieee80211_sta_disassociate(struct net_device *dev, u16 reason)
+{
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	struct ieee80211_if_sta *ifsta = &sdata->u.sta;
+
+	printk(KERN_DEBUG "%s: disassociate(reason=%d)\n",
+	       dev->name, reason);
+
+	if (sdata->type != IEEE80211_IF_TYPE_STA)
+		return -EINVAL;
+
+	if (!ifsta->associated)
+		return -1;
+
+	ieee80211_send_disassoc(dev, ifsta, reason);
+	ieee80211_set_disassoc(dev, ifsta, 0);
+	return 0;
+}
diff --git a/net/mac80211/michael.c b/net/mac80211/michael.c
new file mode 100644
index 0000000..0f844f7
--- /dev/null
+++ b/net/mac80211/michael.c
@@ -0,0 +1,104 @@
+/*
+ * Michael MIC implementation - optimized for TKIP MIC operations
+ * Copyright 2002-2003, Instant802 Networks, Inc.
+ *
+ * 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/types.h>
+
+#include "michael.h"
+
+static inline u32 rotr(u32 val, int bits)
+{
+	return (val >> bits) | (val << (32 - bits));
+}
+
+
+static inline u32 rotl(u32 val, int bits)
+{
+	return (val << bits) | (val >> (32 - bits));
+}
+
+
+static inline u32 xswap(u32 val)
+{
+	return ((val & 0xff00ff00) >> 8) | ((val & 0x00ff00ff) << 8);
+}
+
+
+#define michael_block(l, r) \
+do { \
+	r ^= rotl(l, 17); \
+	l += r; \
+	r ^= xswap(l); \
+	l += r; \
+	r ^= rotl(l, 3); \
+	l += r; \
+	r ^= rotr(l, 2); \
+	l += r; \
+} while (0)
+
+
+static inline u32 michael_get32(u8 *data)
+{
+	return data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
+}
+
+
+static inline void michael_put32(u32 val, u8 *data)
+{
+	data[0] = val & 0xff;
+	data[1] = (val >> 8) & 0xff;
+	data[2] = (val >> 16) & 0xff;
+	data[3] = (val >> 24) & 0xff;
+}
+
+
+void michael_mic(u8 *key, u8 *da, u8 *sa, u8 priority,
+		 u8 *data, size_t data_len, u8 *mic)
+{
+	u32 l, r, val;
+	size_t block, blocks, left;
+
+	l = michael_get32(key);
+	r = michael_get32(key + 4);
+
+	/* A pseudo header (DA, SA, Priority, 0, 0, 0) is used in Michael MIC
+	 * calculation, but it is _not_ transmitted */
+	l ^= michael_get32(da);
+	michael_block(l, r);
+	l ^= da[4] | (da[5] << 8) | (sa[0] << 16) | (sa[1] << 24);
+	michael_block(l, r);
+	l ^= michael_get32(&sa[2]);
+	michael_block(l, r);
+	l ^= priority;
+	michael_block(l, r);
+
+	/* Real data */
+	blocks = data_len / 4;
+	left = data_len % 4;
+
+	for (block = 0; block < blocks; block++) {
+		l ^= michael_get32(&data[block * 4]);
+		michael_block(l, r);
+	}
+
+	/* Partial block of 0..3 bytes and padding: 0x5a + 4..7 zeros to make
+	 * total length a multiple of 4. */
+	val = 0x5a;
+	while (left > 0) {
+		val <<= 8;
+		left--;
+		val |= data[blocks * 4 + left];
+	}
+	l ^= val;
+	michael_block(l, r);
+	/* last block is zero, so l ^ 0 = l */
+	michael_block(l, r);
+
+	michael_put32(l, mic);
+	michael_put32(r, mic + 4);
+}
diff --git a/net/mac80211/michael.h b/net/mac80211/michael.h
new file mode 100644
index 0000000..2e6aeba
--- /dev/null
+++ b/net/mac80211/michael.h
@@ -0,0 +1,20 @@
+/*
+ * Michael MIC implementation - optimized for TKIP MIC operations
+ * Copyright 2002-2003, Instant802 Networks, Inc.
+ *
+ * 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 MICHAEL_H
+#define MICHAEL_H
+
+#include <linux/types.h>
+
+#define MICHAEL_MIC_LEN 8
+
+void michael_mic(u8 *key, u8 *da, u8 *sa, u8 priority,
+		 u8 *data, size_t data_len, u8 *mic);
+
+#endif /* MICHAEL_H */
diff --git a/net/mac80211/rc80211_simple.c b/net/mac80211/rc80211_simple.c
new file mode 100644
index 0000000..2048cfd
--- /dev/null
+++ b/net/mac80211/rc80211_simple.c
@@ -0,0 +1,432 @@
+/*
+ * Copyright 2002-2005, Instant802 Networks, Inc.
+ * Copyright 2005, Devicescape Software, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/skbuff.h>
+#include <linux/compiler.h>
+
+#include <net/mac80211.h>
+#include "ieee80211_i.h"
+#include "ieee80211_rate.h"
+#include "debugfs.h"
+
+
+/* This is a minimal implementation of TX rate controlling that can be used
+ * as the default when no improved mechanisms are available. */
+
+
+#define RATE_CONTROL_EMERG_DEC 2
+#define RATE_CONTROL_INTERVAL (HZ / 20)
+#define RATE_CONTROL_MIN_TX 10
+
+MODULE_ALIAS("rc80211_default");
+
+static void rate_control_rate_inc(struct ieee80211_local *local,
+				  struct sta_info *sta)
+{
+	struct ieee80211_sub_if_data *sdata;
+	struct ieee80211_hw_mode *mode;
+	int i = sta->txrate;
+	int maxrate;
+
+	sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev);
+	if (sdata->bss && sdata->bss->force_unicast_rateidx > -1) {
+		/* forced unicast rate - do not change STA rate */
+		return;
+	}
+
+	mode = local->oper_hw_mode;
+	maxrate = sdata->bss ? sdata->bss->max_ratectrl_rateidx : -1;
+
+	if (i > mode->num_rates)
+		i = mode->num_rates - 2;
+
+	while (i + 1 < mode->num_rates) {
+		i++;
+		if (sta->supp_rates & BIT(i) &&
+		    mode->rates[i].flags & IEEE80211_RATE_SUPPORTED &&
+		    (maxrate < 0 || i <= maxrate)) {
+			sta->txrate = i;
+			break;
+		}
+	}
+}
+
+
+static void rate_control_rate_dec(struct ieee80211_local *local,
+				  struct sta_info *sta)
+{
+	struct ieee80211_sub_if_data *sdata;
+	struct ieee80211_hw_mode *mode;
+	int i = sta->txrate;
+
+	sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev);
+	if (sdata->bss && sdata->bss->force_unicast_rateidx > -1) {
+		/* forced unicast rate - do not change STA rate */
+		return;
+	}
+
+	mode = local->oper_hw_mode;
+	if (i > mode->num_rates)
+		i = mode->num_rates;
+
+	while (i > 0) {
+		i--;
+		if (sta->supp_rates & BIT(i) &&
+		    mode->rates[i].flags & IEEE80211_RATE_SUPPORTED) {
+			sta->txrate = i;
+			break;
+		}
+	}
+}
+
+
+static struct ieee80211_rate *
+rate_control_lowest_rate(struct ieee80211_local *local,
+			 struct ieee80211_hw_mode *mode)
+{
+	int i;
+
+	for (i = 0; i < mode->num_rates; i++) {
+		struct ieee80211_rate *rate = &mode->rates[i];
+
+		if (rate->flags & IEEE80211_RATE_SUPPORTED)
+			return rate;
+	}
+
+	printk(KERN_DEBUG "rate_control_lowest_rate - no supported rates "
+	       "found\n");
+	return &mode->rates[0];
+}
+
+
+struct global_rate_control {
+	int dummy;
+};
+
+struct sta_rate_control {
+	unsigned long last_rate_change;
+	u32 tx_num_failures;
+	u32 tx_num_xmit;
+
+	unsigned long avg_rate_update;
+	u32 tx_avg_rate_sum;
+	u32 tx_avg_rate_num;
+
+#ifdef CONFIG_MAC80211_DEBUGFS
+	struct dentry *tx_avg_rate_sum_dentry;
+	struct dentry *tx_avg_rate_num_dentry;
+#endif
+};
+
+
+static void rate_control_simple_tx_status(void *priv, struct net_device *dev,
+					  struct sk_buff *skb,
+					  struct ieee80211_tx_status *status)
+{
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+	struct sta_info *sta;
+	struct sta_rate_control *srctrl;
+
+	sta = sta_info_get(local, hdr->addr1);
+
+	if (!sta)
+	    return;
+
+	srctrl = sta->rate_ctrl_priv;
+	srctrl->tx_num_xmit++;
+	if (status->excessive_retries) {
+		sta->antenna_sel_tx = sta->antenna_sel_tx == 1 ? 2 : 1;
+		sta->antenna_sel_rx = sta->antenna_sel_rx == 1 ? 2 : 1;
+		if (local->sta_antenna_sel == STA_ANTENNA_SEL_SW_CTRL_DEBUG) {
+			printk(KERN_DEBUG "%s: " MAC_FMT " TX antenna --> %d "
+			       "RX antenna --> %d (@%lu)\n",
+			       dev->name, MAC_ARG(hdr->addr1),
+			       sta->antenna_sel_tx, sta->antenna_sel_rx, jiffies);
+		}
+		srctrl->tx_num_failures++;
+		sta->tx_retry_failed++;
+		sta->tx_num_consecutive_failures++;
+		sta->tx_num_mpdu_fail++;
+	} else {
+		sta->last_ack_rssi[0] = sta->last_ack_rssi[1];
+		sta->last_ack_rssi[1] = sta->last_ack_rssi[2];
+		sta->last_ack_rssi[2] = status->ack_signal;
+		sta->tx_num_consecutive_failures = 0;
+		sta->tx_num_mpdu_ok++;
+	}
+	sta->tx_retry_count += status->retry_count;
+	sta->tx_num_mpdu_fail += status->retry_count;
+
+	if (time_after(jiffies,
+		       srctrl->last_rate_change + RATE_CONTROL_INTERVAL) &&
+		srctrl->tx_num_xmit > RATE_CONTROL_MIN_TX) {
+		u32 per_failed;
+		srctrl->last_rate_change = jiffies;
+
+		per_failed = (100 * sta->tx_num_mpdu_fail) /
+			(sta->tx_num_mpdu_fail + sta->tx_num_mpdu_ok);
+		/* TODO: calculate average per_failed to make adjusting
+		 * parameters easier */
+#if 0
+		if (net_ratelimit()) {
+			printk(KERN_DEBUG "MPDU fail=%d ok=%d per_failed=%d\n",
+			       sta->tx_num_mpdu_fail, sta->tx_num_mpdu_ok,
+			       per_failed);
+		}
+#endif
+
+		if (per_failed > local->rate_ctrl_num_down) {
+			rate_control_rate_dec(local, sta);
+		} else if (per_failed < local->rate_ctrl_num_up) {
+			rate_control_rate_inc(local, sta);
+		}
+		srctrl->tx_avg_rate_sum += status->control.rate->rate;
+		srctrl->tx_avg_rate_num++;
+		srctrl->tx_num_failures = 0;
+		srctrl->tx_num_xmit = 0;
+	} else if (sta->tx_num_consecutive_failures >=
+		   RATE_CONTROL_EMERG_DEC) {
+		rate_control_rate_dec(local, sta);
+	}
+
+	if (srctrl->avg_rate_update + 60 * HZ < jiffies) {
+		srctrl->avg_rate_update = jiffies;
+		if (srctrl->tx_avg_rate_num > 0) {
+#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
+			printk(KERN_DEBUG "%s: STA " MAC_FMT " Average rate: "
+			       "%d (%d/%d)\n",
+			       dev->name, MAC_ARG(sta->addr),
+			       srctrl->tx_avg_rate_sum /
+			       srctrl->tx_avg_rate_num,
+			       srctrl->tx_avg_rate_sum,
+			       srctrl->tx_avg_rate_num);
+#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
+			srctrl->tx_avg_rate_sum = 0;
+			srctrl->tx_avg_rate_num = 0;
+		}
+	}
+
+	sta_info_put(sta);
+}
+
+
+static struct ieee80211_rate *
+rate_control_simple_get_rate(void *priv, struct net_device *dev,
+			     struct sk_buff *skb,
+			     struct rate_control_extra *extra)
+{
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+	struct ieee80211_sub_if_data *sdata;
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+	struct ieee80211_hw_mode *mode = extra->mode;
+	struct sta_info *sta;
+	int rateidx, nonerp_idx;
+	u16 fc;
+
+	memset(extra, 0, sizeof(*extra));
+
+	fc = le16_to_cpu(hdr->frame_control);
+	if ((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA ||
+	    (hdr->addr1[0] & 0x01)) {
+		/* Send management frames and broadcast/multicast data using
+		 * lowest rate. */
+		/* TODO: this could probably be improved.. */
+		return rate_control_lowest_rate(local, mode);
+	}
+
+	sta = sta_info_get(local, hdr->addr1);
+
+	if (!sta)
+		return rate_control_lowest_rate(local, mode);
+
+	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	if (sdata->bss && sdata->bss->force_unicast_rateidx > -1)
+		sta->txrate = sdata->bss->force_unicast_rateidx;
+
+	rateidx = sta->txrate;
+
+	if (rateidx >= mode->num_rates)
+		rateidx = mode->num_rates - 1;
+
+	sta->last_txrate = rateidx;
+	nonerp_idx = rateidx;
+	while (nonerp_idx > 0 &&
+	       ((mode->rates[nonerp_idx].flags & IEEE80211_RATE_ERP) ||
+		!(mode->rates[nonerp_idx].flags & IEEE80211_RATE_SUPPORTED) ||
+		!(sta->supp_rates & BIT(nonerp_idx))))
+		nonerp_idx--;
+	extra->nonerp = &mode->rates[nonerp_idx];
+
+	sta_info_put(sta);
+
+	return &mode->rates[rateidx];
+}
+
+
+static void rate_control_simple_rate_init(void *priv, void *priv_sta,
+					  struct ieee80211_local *local,
+					  struct sta_info *sta)
+{
+	struct ieee80211_hw_mode *mode;
+	int i;
+	sta->txrate = 0;
+	mode = local->oper_hw_mode;
+	/* TODO: what is a good starting rate for STA? About middle? Maybe not
+	 * the lowest or the highest rate.. Could consider using RSSI from
+	 * previous packets? Need to have IEEE 802.1X auth succeed immediately
+	 * after assoc.. */
+	for (i = 0; i < mode->num_rates; i++) {
+		if ((sta->supp_rates & BIT(i)) &&
+		    (mode->rates[i].flags & IEEE80211_RATE_SUPPORTED))
+			sta->txrate = i;
+	}
+}
+
+
+static void * rate_control_simple_alloc(struct ieee80211_local *local)
+{
+	struct global_rate_control *rctrl;
+
+	rctrl = kzalloc(sizeof(*rctrl), GFP_ATOMIC);
+
+	return rctrl;
+}
+
+
+static void rate_control_simple_free(void *priv)
+{
+	struct global_rate_control *rctrl = priv;
+	kfree(rctrl);
+}
+
+
+static void rate_control_simple_clear(void *priv)
+{
+}
+
+
+static void * rate_control_simple_alloc_sta(void *priv, gfp_t gfp)
+{
+	struct sta_rate_control *rctrl;
+
+	rctrl = kzalloc(sizeof(*rctrl), gfp);
+
+	return rctrl;
+}
+
+
+static void rate_control_simple_free_sta(void *priv, void *priv_sta)
+{
+	struct sta_rate_control *rctrl = priv_sta;
+	kfree(rctrl);
+}
+
+#ifdef CONFIG_MAC80211_DEBUGFS
+
+static int open_file_generic(struct inode *inode, struct file *file)
+{
+	file->private_data = inode->i_private;
+	return 0;
+}
+
+static ssize_t sta_tx_avg_rate_sum_read(struct file *file,
+					char __user *userbuf,
+					size_t count, loff_t *ppos)
+{
+	struct sta_rate_control *srctrl = file->private_data;
+	char buf[20];
+
+	sprintf(buf, "%d\n", srctrl->tx_avg_rate_sum);
+	return simple_read_from_buffer(userbuf, count, ppos, buf, strlen(buf));
+}
+
+static const struct file_operations sta_tx_avg_rate_sum_ops = {
+	.read = sta_tx_avg_rate_sum_read,
+	.open = open_file_generic,
+};
+
+static ssize_t sta_tx_avg_rate_num_read(struct file *file,
+					char __user *userbuf,
+					size_t count, loff_t *ppos)
+{
+	struct sta_rate_control *srctrl = file->private_data;
+	char buf[20];
+
+	sprintf(buf, "%d\n", srctrl->tx_avg_rate_num);
+	return simple_read_from_buffer(userbuf, count, ppos, buf, strlen(buf));
+}
+
+static const struct file_operations sta_tx_avg_rate_num_ops = {
+	.read = sta_tx_avg_rate_num_read,
+	.open = open_file_generic,
+};
+
+static void rate_control_simple_add_sta_debugfs(void *priv, void *priv_sta,
+						struct dentry *dir)
+{
+	struct sta_rate_control *srctrl = priv_sta;
+
+	srctrl->tx_avg_rate_num_dentry =
+		debugfs_create_file("rc_simple_sta_tx_avg_rate_num", 0400,
+				    dir, srctrl, &sta_tx_avg_rate_num_ops);
+	srctrl->tx_avg_rate_sum_dentry =
+		debugfs_create_file("rc_simple_sta_tx_avg_rate_sum", 0400,
+				    dir, srctrl, &sta_tx_avg_rate_sum_ops);
+}
+
+static void rate_control_simple_remove_sta_debugfs(void *priv, void *priv_sta)
+{
+	struct sta_rate_control *srctrl = priv_sta;
+
+	debugfs_remove(srctrl->tx_avg_rate_sum_dentry);
+	debugfs_remove(srctrl->tx_avg_rate_num_dentry);
+}
+#endif
+
+static struct rate_control_ops rate_control_simple = {
+	.module = THIS_MODULE,
+	.name = "simple",
+	.tx_status = rate_control_simple_tx_status,
+	.get_rate = rate_control_simple_get_rate,
+	.rate_init = rate_control_simple_rate_init,
+	.clear = rate_control_simple_clear,
+	.alloc = rate_control_simple_alloc,
+	.free = rate_control_simple_free,
+	.alloc_sta = rate_control_simple_alloc_sta,
+	.free_sta = rate_control_simple_free_sta,
+#ifdef CONFIG_MAC80211_DEBUGFS
+	.add_sta_debugfs = rate_control_simple_add_sta_debugfs,
+	.remove_sta_debugfs = rate_control_simple_remove_sta_debugfs,
+#endif
+};
+
+
+static int __init rate_control_simple_init(void)
+{
+	return ieee80211_rate_control_register(&rate_control_simple);
+}
+
+
+static void __exit rate_control_simple_exit(void)
+{
+	ieee80211_rate_control_unregister(&rate_control_simple);
+}
+
+
+module_init(rate_control_simple_init);
+module_exit(rate_control_simple_exit);
+
+MODULE_DESCRIPTION("Simple rate control algorithm for ieee80211");
+MODULE_LICENSE("GPL");
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
new file mode 100644
index 0000000..ab7b1f0
--- /dev/null
+++ b/net/mac80211/sta_info.c
@@ -0,0 +1,470 @@
+/*
+ * Copyright 2002-2005, Instant802 Networks, Inc.
+ * Copyright 2006-2007	Jiri Benc <jbenc@suse.cz>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/skbuff.h>
+#include <linux/if_arp.h>
+
+#include <net/mac80211.h>
+#include "ieee80211_i.h"
+#include "ieee80211_rate.h"
+#include "sta_info.h"
+#include "debugfs_key.h"
+#include "debugfs_sta.h"
+
+/* Caller must hold local->sta_lock */
+static void sta_info_hash_add(struct ieee80211_local *local,
+			      struct sta_info *sta)
+{
+	sta->hnext = local->sta_hash[STA_HASH(sta->addr)];
+	local->sta_hash[STA_HASH(sta->addr)] = sta;
+}
+
+
+/* Caller must hold local->sta_lock */
+static void sta_info_hash_del(struct ieee80211_local *local,
+			      struct sta_info *sta)
+{
+	struct sta_info *s;
+
+	s = local->sta_hash[STA_HASH(sta->addr)];
+	if (!s)
+		return;
+	if (memcmp(s->addr, sta->addr, ETH_ALEN) == 0) {
+		local->sta_hash[STA_HASH(sta->addr)] = s->hnext;
+		return;
+	}
+
+	while (s->hnext && memcmp(s->hnext->addr, sta->addr, ETH_ALEN) != 0)
+		s = s->hnext;
+	if (s->hnext)
+		s->hnext = s->hnext->hnext;
+	else
+		printk(KERN_ERR "%s: could not remove STA " MAC_FMT " from "
+		       "hash table\n", local->mdev->name, MAC_ARG(sta->addr));
+}
+
+static inline void __sta_info_get(struct sta_info *sta)
+{
+	kref_get(&sta->kref);
+}
+
+struct sta_info *sta_info_get(struct ieee80211_local *local, u8 *addr)
+{
+	struct sta_info *sta;
+
+	spin_lock_bh(&local->sta_lock);
+	sta = local->sta_hash[STA_HASH(addr)];
+	while (sta) {
+		if (memcmp(sta->addr, addr, ETH_ALEN) == 0) {
+			__sta_info_get(sta);
+			break;
+		}
+		sta = sta->hnext;
+	}
+	spin_unlock_bh(&local->sta_lock);
+
+	return sta;
+}
+EXPORT_SYMBOL(sta_info_get);
+
+int sta_info_min_txrate_get(struct ieee80211_local *local)
+{
+	struct sta_info *sta;
+	struct ieee80211_hw_mode *mode;
+	int min_txrate = 9999999;
+	int i;
+
+	spin_lock_bh(&local->sta_lock);
+	mode = local->oper_hw_mode;
+	for (i = 0; i < STA_HASH_SIZE; i++) {
+		sta = local->sta_hash[i];
+		while (sta) {
+			if (sta->txrate < min_txrate)
+				min_txrate = sta->txrate;
+			sta = sta->hnext;
+		}
+	}
+	spin_unlock_bh(&local->sta_lock);
+	if (min_txrate == 9999999)
+		min_txrate = 0;
+
+	return mode->rates[min_txrate].rate;
+}
+
+
+static void sta_info_release(struct kref *kref)
+{
+	struct sta_info *sta = container_of(kref, struct sta_info, kref);
+	struct ieee80211_local *local = sta->local;
+	struct sk_buff *skb;
+
+	/* free sta structure; it has already been removed from
+	 * hash table etc. external structures. Make sure that all
+	 * buffered frames are release (one might have been added
+	 * after sta_info_free() was called). */
+	while ((skb = skb_dequeue(&sta->ps_tx_buf)) != NULL) {
+		local->total_ps_buffered--;
+		dev_kfree_skb_any(skb);
+	}
+	while ((skb = skb_dequeue(&sta->tx_filtered)) != NULL) {
+		dev_kfree_skb_any(skb);
+	}
+	rate_control_free_sta(sta->rate_ctrl, sta->rate_ctrl_priv);
+	rate_control_put(sta->rate_ctrl);
+	if (sta->key)
+		ieee80211_debugfs_key_sta_del(sta->key, sta);
+	kfree(sta);
+}
+
+
+void sta_info_put(struct sta_info *sta)
+{
+	kref_put(&sta->kref, sta_info_release);
+}
+EXPORT_SYMBOL(sta_info_put);
+
+
+struct sta_info * sta_info_add(struct ieee80211_local *local,
+			       struct net_device *dev, u8 *addr, gfp_t gfp)
+{
+	struct sta_info *sta;
+
+	sta = kzalloc(sizeof(*sta), gfp);
+	if (!sta)
+		return NULL;
+
+	kref_init(&sta->kref);
+
+	sta->rate_ctrl = rate_control_get(local->rate_ctrl);
+	sta->rate_ctrl_priv = rate_control_alloc_sta(sta->rate_ctrl, gfp);
+	if (!sta->rate_ctrl_priv) {
+		rate_control_put(sta->rate_ctrl);
+		kref_put(&sta->kref, sta_info_release);
+		kfree(sta);
+		return NULL;
+	}
+
+	memcpy(sta->addr, addr, ETH_ALEN);
+	sta->local = local;
+	sta->dev = dev;
+	skb_queue_head_init(&sta->ps_tx_buf);
+	skb_queue_head_init(&sta->tx_filtered);
+	__sta_info_get(sta);	/* sta used by caller, decremented by
+				 * sta_info_put() */
+	spin_lock_bh(&local->sta_lock);
+	list_add(&sta->list, &local->sta_list);
+	local->num_sta++;
+	sta_info_hash_add(local, sta);
+	spin_unlock_bh(&local->sta_lock);
+	if (local->ops->sta_table_notification)
+		local->ops->sta_table_notification(local_to_hw(local),
+						  local->num_sta);
+	sta->key_idx_compression = HW_KEY_IDX_INVALID;
+
+#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
+	printk(KERN_DEBUG "%s: Added STA " MAC_FMT "\n",
+	       local->mdev->name, MAC_ARG(addr));
+#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
+
+#ifdef CONFIG_MAC80211_DEBUGFS
+	if (!in_interrupt()) {
+		sta->debugfs_registered = 1;
+		ieee80211_sta_debugfs_add(sta);
+		rate_control_add_sta_debugfs(sta);
+	} else {
+		/* debugfs entry adding might sleep, so schedule process
+		 * context task for adding entry for STAs that do not yet
+		 * have one. */
+		queue_work(local->hw.workqueue, &local->sta_debugfs_add);
+	}
+#endif
+
+	return sta;
+}
+
+static void finish_sta_info_free(struct ieee80211_local *local,
+				 struct sta_info *sta)
+{
+#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
+	printk(KERN_DEBUG "%s: Removed STA " MAC_FMT "\n",
+	       local->mdev->name, MAC_ARG(sta->addr));
+#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
+
+	if (sta->key) {
+		ieee80211_debugfs_key_remove(sta->key);
+		ieee80211_key_free(sta->key);
+		sta->key = NULL;
+	}
+
+	rate_control_remove_sta_debugfs(sta);
+	ieee80211_sta_debugfs_remove(sta);
+
+	sta_info_put(sta);
+}
+
+static void sta_info_remove(struct sta_info *sta)
+{
+	struct ieee80211_local *local = sta->local;
+	struct ieee80211_sub_if_data *sdata;
+
+	sta_info_hash_del(local, sta);
+	list_del(&sta->list);
+	sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev);
+	if (sta->flags & WLAN_STA_PS) {
+		sta->flags &= ~WLAN_STA_PS;
+		if (sdata->bss)
+			atomic_dec(&sdata->bss->num_sta_ps);
+	}
+	local->num_sta--;
+	sta_info_remove_aid_ptr(sta);
+}
+
+void sta_info_free(struct sta_info *sta, int locked)
+{
+	struct sk_buff *skb;
+	struct ieee80211_local *local = sta->local;
+
+	if (!locked) {
+		spin_lock_bh(&local->sta_lock);
+		sta_info_remove(sta);
+		spin_unlock_bh(&local->sta_lock);
+	} else {
+		sta_info_remove(sta);
+	}
+	if (local->ops->sta_table_notification)
+		local->ops->sta_table_notification(local_to_hw(local),
+						  local->num_sta);
+
+	while ((skb = skb_dequeue(&sta->ps_tx_buf)) != NULL) {
+		local->total_ps_buffered--;
+		dev_kfree_skb_any(skb);
+	}
+	while ((skb = skb_dequeue(&sta->tx_filtered)) != NULL) {
+		dev_kfree_skb_any(skb);
+	}
+
+	if (sta->key) {
+		if (local->ops->set_key) {
+			struct ieee80211_key_conf *key;
+			key = ieee80211_key_data2conf(local, sta->key);
+			if (key) {
+				local->ops->set_key(local_to_hw(local),
+						   DISABLE_KEY,
+						   sta->addr, key, sta->aid);
+				kfree(key);
+			}
+		}
+	} else if (sta->key_idx_compression != HW_KEY_IDX_INVALID) {
+		struct ieee80211_key_conf conf;
+		memset(&conf, 0, sizeof(conf));
+		conf.hw_key_idx = sta->key_idx_compression;
+		conf.alg = ALG_NULL;
+		conf.flags |= IEEE80211_KEY_FORCE_SW_ENCRYPT;
+		local->ops->set_key(local_to_hw(local), DISABLE_KEY,
+				   sta->addr, &conf, sta->aid);
+		sta->key_idx_compression = HW_KEY_IDX_INVALID;
+	}
+
+#ifdef CONFIG_MAC80211_DEBUGFS
+	if (in_atomic()) {
+		list_add(&sta->list, &local->deleted_sta_list);
+		queue_work(local->hw.workqueue, &local->sta_debugfs_add);
+	} else
+#endif
+		finish_sta_info_free(local, sta);
+}
+
+
+static inline int sta_info_buffer_expired(struct ieee80211_local *local,
+					  struct sta_info *sta,
+					  struct sk_buff *skb)
+{
+	struct ieee80211_tx_packet_data *pkt_data;
+	int timeout;
+
+	if (!skb)
+		return 0;
+
+	pkt_data = (struct ieee80211_tx_packet_data *) skb->cb;
+
+	/* Timeout: (2 * listen_interval * beacon_int * 1024 / 1000000) sec */
+	timeout = (sta->listen_interval * local->hw.conf.beacon_int * 32 /
+		   15625) * HZ;
+	if (timeout < STA_TX_BUFFER_EXPIRE)
+		timeout = STA_TX_BUFFER_EXPIRE;
+	return time_after(jiffies, pkt_data->jiffies + timeout);
+}
+
+
+static void sta_info_cleanup_expire_buffered(struct ieee80211_local *local,
+					     struct sta_info *sta)
+{
+	unsigned long flags;
+	struct sk_buff *skb;
+
+	if (skb_queue_empty(&sta->ps_tx_buf))
+		return;
+
+	for (;;) {
+		spin_lock_irqsave(&sta->ps_tx_buf.lock, flags);
+		skb = skb_peek(&sta->ps_tx_buf);
+		if (sta_info_buffer_expired(local, sta, skb)) {
+			skb = __skb_dequeue(&sta->ps_tx_buf);
+			if (skb_queue_empty(&sta->ps_tx_buf))
+				sta->flags &= ~WLAN_STA_TIM;
+		} else
+			skb = NULL;
+		spin_unlock_irqrestore(&sta->ps_tx_buf.lock, flags);
+
+		if (skb) {
+			local->total_ps_buffered--;
+			printk(KERN_DEBUG "Buffered frame expired (STA "
+			       MAC_FMT ")\n", MAC_ARG(sta->addr));
+			dev_kfree_skb(skb);
+		} else
+			break;
+	}
+}
+
+
+static void sta_info_cleanup(unsigned long data)
+{
+	struct ieee80211_local *local = (struct ieee80211_local *) data;
+	struct sta_info *sta;
+
+	spin_lock_bh(&local->sta_lock);
+	list_for_each_entry(sta, &local->sta_list, list) {
+		__sta_info_get(sta);
+		sta_info_cleanup_expire_buffered(local, sta);
+		sta_info_put(sta);
+	}
+	spin_unlock_bh(&local->sta_lock);
+
+	local->sta_cleanup.expires = jiffies + STA_INFO_CLEANUP_INTERVAL;
+	add_timer(&local->sta_cleanup);
+}
+
+#ifdef CONFIG_MAC80211_DEBUGFS
+static void sta_info_debugfs_add_task(struct work_struct *work)
+{
+	struct ieee80211_local *local =
+		container_of(work, struct ieee80211_local, sta_debugfs_add);
+	struct sta_info *sta, *tmp;
+
+	while (1) {
+		spin_lock_bh(&local->sta_lock);
+		if (!list_empty(&local->deleted_sta_list)) {
+			sta = list_entry(local->deleted_sta_list.next,
+					 struct sta_info, list);
+			list_del(local->deleted_sta_list.next);
+		} else
+			sta = NULL;
+		spin_unlock_bh(&local->sta_lock);
+		if (!sta)
+			break;
+		finish_sta_info_free(local, sta);
+	}
+
+	while (1) {
+		sta = NULL;
+		spin_lock_bh(&local->sta_lock);
+		list_for_each_entry(tmp, &local->sta_list, list) {
+			if (!tmp->debugfs_registered) {
+				sta = tmp;
+				__sta_info_get(sta);
+				break;
+			}
+		}
+		spin_unlock_bh(&local->sta_lock);
+
+		if (!sta)
+			break;
+
+		sta->debugfs_registered = 1;
+		ieee80211_sta_debugfs_add(sta);
+		rate_control_add_sta_debugfs(sta);
+		sta_info_put(sta);
+	}
+}
+#endif
+
+void sta_info_init(struct ieee80211_local *local)
+{
+	spin_lock_init(&local->sta_lock);
+	INIT_LIST_HEAD(&local->sta_list);
+	INIT_LIST_HEAD(&local->deleted_sta_list);
+
+	init_timer(&local->sta_cleanup);
+	local->sta_cleanup.expires = jiffies + STA_INFO_CLEANUP_INTERVAL;
+	local->sta_cleanup.data = (unsigned long) local;
+	local->sta_cleanup.function = sta_info_cleanup;
+
+#ifdef CONFIG_MAC80211_DEBUGFS
+	INIT_WORK(&local->sta_debugfs_add, sta_info_debugfs_add_task);
+#endif
+}
+
+int sta_info_start(struct ieee80211_local *local)
+{
+	add_timer(&local->sta_cleanup);
+	return 0;
+}
+
+void sta_info_stop(struct ieee80211_local *local)
+{
+	struct sta_info *sta, *tmp;
+
+	del_timer(&local->sta_cleanup);
+
+	list_for_each_entry_safe(sta, tmp, &local->sta_list, list) {
+		/* sta_info_free must be called with 0 as the last
+		 * parameter to ensure all debugfs sta entries are
+		 * unregistered. We don't need locking at this
+		 * point. */
+		sta_info_free(sta, 0);
+	}
+}
+
+void sta_info_remove_aid_ptr(struct sta_info *sta)
+{
+	struct ieee80211_sub_if_data *sdata;
+
+	if (sta->aid <= 0)
+		return;
+
+	sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev);
+
+	if (sdata->local->ops->set_tim)
+		sdata->local->ops->set_tim(local_to_hw(sdata->local),
+					  sta->aid, 0);
+	if (sdata->bss)
+		__bss_tim_clear(sdata->bss, sta->aid);
+}
+
+
+/**
+ * sta_info_flush - flush matching STA entries from the STA table
+ * @local: local interface data
+ * @dev: matching rule for the net device (sta->dev) or %NULL to match all STAs
+ */
+void sta_info_flush(struct ieee80211_local *local, struct net_device *dev)
+{
+	struct sta_info *sta, *tmp;
+
+	spin_lock_bh(&local->sta_lock);
+	list_for_each_entry_safe(sta, tmp, &local->sta_list, list)
+		if (!dev || dev == sta->dev)
+			sta_info_free(sta, 1);
+	spin_unlock_bh(&local->sta_lock);
+}
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
new file mode 100644
index 0000000..b5591d2
--- /dev/null
+++ b/net/mac80211/sta_info.h
@@ -0,0 +1,164 @@
+/*
+ * Copyright 2002-2005, Devicescape Software, Inc.
+ *
+ * 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 STA_INFO_H
+#define STA_INFO_H
+
+#include <linux/list.h>
+#include <linux/types.h>
+#include <linux/if_ether.h>
+#include <linux/kref.h>
+#include "ieee80211_key.h"
+
+/* Stations flags (struct sta_info::flags) */
+#define WLAN_STA_AUTH BIT(0)
+#define WLAN_STA_ASSOC BIT(1)
+#define WLAN_STA_PS BIT(2)
+#define WLAN_STA_TIM BIT(3) /* TIM bit is on for PS stations */
+#define WLAN_STA_PERM BIT(4) /* permanent; do not remove entry on expiration */
+#define WLAN_STA_AUTHORIZED BIT(5) /* If 802.1X is used, this flag is
+				    * controlling whether STA is authorized to
+				    * send and receive non-IEEE 802.1X frames
+				    */
+#define WLAN_STA_SHORT_PREAMBLE BIT(7)
+#define WLAN_STA_WME BIT(9)
+#define WLAN_STA_WDS BIT(27)
+
+
+struct sta_info {
+	struct kref kref;
+	struct list_head list;
+	struct sta_info *hnext; /* next entry in hash table list */
+
+	struct ieee80211_local *local;
+
+	u8 addr[ETH_ALEN];
+	u16 aid; /* STA's unique AID (1..2007), 0 = not yet assigned */
+	u32 flags; /* WLAN_STA_ */
+
+	struct sk_buff_head ps_tx_buf; /* buffer of TX frames for station in
+					* power saving state */
+	int pspoll; /* whether STA has send a PS Poll frame */
+	struct sk_buff_head tx_filtered; /* buffer of TX frames that were
+					  * already given to low-level driver,
+					  * but were filtered */
+	int clear_dst_mask;
+
+	unsigned long rx_packets, tx_packets; /* number of RX/TX MSDUs */
+	unsigned long rx_bytes, tx_bytes;
+	unsigned long tx_retry_failed, tx_retry_count;
+	unsigned long tx_filtered_count;
+
+	unsigned int wep_weak_iv_count; /* number of RX frames with weak IV */
+
+	unsigned long last_rx;
+	u32 supp_rates; /* bitmap of supported rates in local->curr_rates */
+	int txrate; /* index in local->curr_rates */
+	int last_txrate; /* last rate used to send a frame to this STA */
+	int last_nonerp_idx;
+
+	struct net_device *dev; /* which net device is this station associated
+				 * to */
+
+	struct ieee80211_key *key;
+
+	u32 tx_num_consecutive_failures;
+	u32 tx_num_mpdu_ok;
+	u32 tx_num_mpdu_fail;
+
+	struct rate_control_ref *rate_ctrl;
+	void *rate_ctrl_priv;
+
+	/* last received seq/frag number from this STA (per RX queue) */
+	__le16 last_seq_ctrl[NUM_RX_DATA_QUEUES];
+	unsigned long num_duplicates; /* number of duplicate frames received
+				       * from this STA */
+	unsigned long tx_fragments; /* number of transmitted MPDUs */
+	unsigned long rx_fragments; /* number of received MPDUs */
+	unsigned long rx_dropped; /* number of dropped MPDUs from this STA */
+
+	int last_rssi; /* RSSI of last received frame from this STA */
+	int last_signal; /* signal of last received frame from this STA */
+	int last_noise; /* noise of last received frame from this STA */
+	int last_ack_rssi[3]; /* RSSI of last received ACKs from this STA */
+	unsigned long last_ack;
+	int channel_use;
+	int channel_use_raw;
+
+	u8 antenna_sel_tx;
+	u8 antenna_sel_rx;
+
+
+	int key_idx_compression; /* key table index for compression and TX
+				  * filtering; used only if sta->key is not
+				  * set */
+
+#ifdef CONFIG_MAC80211_DEBUGFS
+	int debugfs_registered;
+#endif
+	int assoc_ap; /* whether this is an AP that we are
+		       * associated with as a client */
+
+#ifdef CONFIG_MAC80211_DEBUG_COUNTERS
+	unsigned int wme_rx_queue[NUM_RX_DATA_QUEUES];
+	unsigned int wme_tx_queue[NUM_RX_DATA_QUEUES];
+#endif /* CONFIG_MAC80211_DEBUG_COUNTERS */
+
+	int vlan_id;
+
+	u16 listen_interval;
+
+#ifdef CONFIG_MAC80211_DEBUGFS
+	struct sta_info_debugfsdentries {
+		struct dentry *dir;
+		struct dentry *flags;
+		struct dentry *num_ps_buf_frames;
+		struct dentry *last_ack_rssi;
+		struct dentry *last_ack_ms;
+		struct dentry *inactive_ms;
+		struct dentry *last_seq_ctrl;
+#ifdef CONFIG_MAC80211_DEBUG_COUNTERS
+		struct dentry *wme_rx_queue;
+		struct dentry *wme_tx_queue;
+#endif
+	} debugfs;
+#endif
+};
+
+
+/* Maximum number of concurrently registered stations */
+#define MAX_STA_COUNT 2007
+
+#define STA_HASH_SIZE 256
+#define STA_HASH(sta) (sta[5])
+
+
+/* Maximum number of frames to buffer per power saving station */
+#define STA_MAX_TX_BUFFER 128
+
+/* Minimum buffered frame expiry time. If STA uses listen interval that is
+ * smaller than this value, the minimum value here is used instead. */
+#define STA_TX_BUFFER_EXPIRE (10 * HZ)
+
+/* How often station data is cleaned up (e.g., expiration of buffered frames)
+ */
+#define STA_INFO_CLEANUP_INTERVAL (10 * HZ)
+
+struct sta_info * sta_info_get(struct ieee80211_local *local, u8 *addr);
+int sta_info_min_txrate_get(struct ieee80211_local *local);
+void sta_info_put(struct sta_info *sta);
+struct sta_info * sta_info_add(struct ieee80211_local *local,
+			       struct net_device *dev, u8 *addr, gfp_t gfp);
+void sta_info_free(struct sta_info *sta, int locked);
+void sta_info_init(struct ieee80211_local *local);
+int sta_info_start(struct ieee80211_local *local);
+void sta_info_stop(struct ieee80211_local *local);
+void sta_info_remove_aid_ptr(struct sta_info *sta);
+void sta_info_flush(struct ieee80211_local *local, struct net_device *dev);
+
+#endif /* STA_INFO_H */
diff --git a/net/mac80211/tkip.c b/net/mac80211/tkip.c
new file mode 100644
index 0000000..4162172
--- /dev/null
+++ b/net/mac80211/tkip.c
@@ -0,0 +1,341 @@
+/*
+ * Copyright 2002-2004, Instant802 Networks, Inc.
+ * Copyright 2005, Devicescape Software, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/netdevice.h>
+
+#include <net/mac80211.h>
+#include "ieee80211_key.h"
+#include "tkip.h"
+#include "wep.h"
+
+
+/* TKIP key mixing functions */
+
+
+#define PHASE1_LOOP_COUNT 8
+
+
+/* 2-byte by 2-byte subset of the full AES S-box table; second part of this
+ * table is identical to first part but byte-swapped */
+static const u16 tkip_sbox[256] =
+{
+	0xC6A5, 0xF884, 0xEE99, 0xF68D, 0xFF0D, 0xD6BD, 0xDEB1, 0x9154,
+	0x6050, 0x0203, 0xCEA9, 0x567D, 0xE719, 0xB562, 0x4DE6, 0xEC9A,
+	0x8F45, 0x1F9D, 0x8940, 0xFA87, 0xEF15, 0xB2EB, 0x8EC9, 0xFB0B,
+	0x41EC, 0xB367, 0x5FFD, 0x45EA, 0x23BF, 0x53F7, 0xE496, 0x9B5B,
+	0x75C2, 0xE11C, 0x3DAE, 0x4C6A, 0x6C5A, 0x7E41, 0xF502, 0x834F,
+	0x685C, 0x51F4, 0xD134, 0xF908, 0xE293, 0xAB73, 0x6253, 0x2A3F,
+	0x080C, 0x9552, 0x4665, 0x9D5E, 0x3028, 0x37A1, 0x0A0F, 0x2FB5,
+	0x0E09, 0x2436, 0x1B9B, 0xDF3D, 0xCD26, 0x4E69, 0x7FCD, 0xEA9F,
+	0x121B, 0x1D9E, 0x5874, 0x342E, 0x362D, 0xDCB2, 0xB4EE, 0x5BFB,
+	0xA4F6, 0x764D, 0xB761, 0x7DCE, 0x527B, 0xDD3E, 0x5E71, 0x1397,
+	0xA6F5, 0xB968, 0x0000, 0xC12C, 0x4060, 0xE31F, 0x79C8, 0xB6ED,
+	0xD4BE, 0x8D46, 0x67D9, 0x724B, 0x94DE, 0x98D4, 0xB0E8, 0x854A,
+	0xBB6B, 0xC52A, 0x4FE5, 0xED16, 0x86C5, 0x9AD7, 0x6655, 0x1194,
+	0x8ACF, 0xE910, 0x0406, 0xFE81, 0xA0F0, 0x7844, 0x25BA, 0x4BE3,
+	0xA2F3, 0x5DFE, 0x80C0, 0x058A, 0x3FAD, 0x21BC, 0x7048, 0xF104,
+	0x63DF, 0x77C1, 0xAF75, 0x4263, 0x2030, 0xE51A, 0xFD0E, 0xBF6D,
+	0x814C, 0x1814, 0x2635, 0xC32F, 0xBEE1, 0x35A2, 0x88CC, 0x2E39,
+	0x9357, 0x55F2, 0xFC82, 0x7A47, 0xC8AC, 0xBAE7, 0x322B, 0xE695,
+	0xC0A0, 0x1998, 0x9ED1, 0xA37F, 0x4466, 0x547E, 0x3BAB, 0x0B83,
+	0x8CCA, 0xC729, 0x6BD3, 0x283C, 0xA779, 0xBCE2, 0x161D, 0xAD76,
+	0xDB3B, 0x6456, 0x744E, 0x141E, 0x92DB, 0x0C0A, 0x486C, 0xB8E4,
+	0x9F5D, 0xBD6E, 0x43EF, 0xC4A6, 0x39A8, 0x31A4, 0xD337, 0xF28B,
+	0xD532, 0x8B43, 0x6E59, 0xDAB7, 0x018C, 0xB164, 0x9CD2, 0x49E0,
+	0xD8B4, 0xACFA, 0xF307, 0xCF25, 0xCAAF, 0xF48E, 0x47E9, 0x1018,
+	0x6FD5, 0xF088, 0x4A6F, 0x5C72, 0x3824, 0x57F1, 0x73C7, 0x9751,
+	0xCB23, 0xA17C, 0xE89C, 0x3E21, 0x96DD, 0x61DC, 0x0D86, 0x0F85,
+	0xE090, 0x7C42, 0x71C4, 0xCCAA, 0x90D8, 0x0605, 0xF701, 0x1C12,
+	0xC2A3, 0x6A5F, 0xAEF9, 0x69D0, 0x1791, 0x9958, 0x3A27, 0x27B9,
+	0xD938, 0xEB13, 0x2BB3, 0x2233, 0xD2BB, 0xA970, 0x0789, 0x33A7,
+	0x2DB6, 0x3C22, 0x1592, 0xC920, 0x8749, 0xAAFF, 0x5078, 0xA57A,
+	0x038F, 0x59F8, 0x0980, 0x1A17, 0x65DA, 0xD731, 0x84C6, 0xD0B8,
+	0x82C3, 0x29B0, 0x5A77, 0x1E11, 0x7BCB, 0xA8FC, 0x6DD6, 0x2C3A,
+};
+
+
+static inline u16 Mk16(u8 x, u8 y)
+{
+	return ((u16) x << 8) | (u16) y;
+}
+
+
+static inline u8 Hi8(u16 v)
+{
+	return v >> 8;
+}
+
+
+static inline u8 Lo8(u16 v)
+{
+	return v & 0xff;
+}
+
+
+static inline u16 Hi16(u32 v)
+{
+	return v >> 16;
+}
+
+
+static inline u16 Lo16(u32 v)
+{
+	return v & 0xffff;
+}
+
+
+static inline u16 RotR1(u16 v)
+{
+	return (v >> 1) | ((v & 0x0001) << 15);
+}
+
+
+static inline u16 tkip_S(u16 val)
+{
+	u16 a = tkip_sbox[Hi8(val)];
+
+	return tkip_sbox[Lo8(val)] ^ Hi8(a) ^ (Lo8(a) << 8);
+}
+
+
+
+/* P1K := Phase1(TA, TK, TSC)
+ * TA = transmitter address (48 bits)
+ * TK = dot11DefaultKeyValue or dot11KeyMappingValue (128 bits)
+ * TSC = TKIP sequence counter (48 bits, only 32 msb bits used)
+ * P1K: 80 bits
+ */
+static void tkip_mixing_phase1(const u8 *ta, const u8 *tk, u32 tsc_IV32,
+			       u16 *p1k)
+{
+	int i, j;
+
+	p1k[0] = Lo16(tsc_IV32);
+	p1k[1] = Hi16(tsc_IV32);
+	p1k[2] = Mk16(ta[1], ta[0]);
+	p1k[3] = Mk16(ta[3], ta[2]);
+	p1k[4] = Mk16(ta[5], ta[4]);
+
+	for (i = 0; i < PHASE1_LOOP_COUNT; i++) {
+		j = 2 * (i & 1);
+		p1k[0] += tkip_S(p1k[4] ^ Mk16(tk[ 1 + j], tk[ 0 + j]));
+		p1k[1] += tkip_S(p1k[0] ^ Mk16(tk[ 5 + j], tk[ 4 + j]));
+		p1k[2] += tkip_S(p1k[1] ^ Mk16(tk[ 9 + j], tk[ 8 + j]));
+		p1k[3] += tkip_S(p1k[2] ^ Mk16(tk[13 + j], tk[12 + j]));
+		p1k[4] += tkip_S(p1k[3] ^ Mk16(tk[ 1 + j], tk[ 0 + j])) + i;
+	}
+}
+
+
+static void tkip_mixing_phase2(const u16 *p1k, const u8 *tk, u16 tsc_IV16,
+			       u8 *rc4key)
+{
+	u16 ppk[6];
+	int i;
+
+	ppk[0] = p1k[0];
+	ppk[1] = p1k[1];
+	ppk[2] = p1k[2];
+	ppk[3] = p1k[3];
+	ppk[4] = p1k[4];
+	ppk[5] = p1k[4] + tsc_IV16;
+
+	ppk[0] += tkip_S(ppk[5] ^ Mk16(tk[ 1], tk[ 0]));
+	ppk[1] += tkip_S(ppk[0] ^ Mk16(tk[ 3], tk[ 2]));
+	ppk[2] += tkip_S(ppk[1] ^ Mk16(tk[ 5], tk[ 4]));
+	ppk[3] += tkip_S(ppk[2] ^ Mk16(tk[ 7], tk[ 6]));
+	ppk[4] += tkip_S(ppk[3] ^ Mk16(tk[ 9], tk[ 8]));
+	ppk[5] += tkip_S(ppk[4] ^ Mk16(tk[11], tk[10]));
+	ppk[0] +=  RotR1(ppk[5] ^ Mk16(tk[13], tk[12]));
+	ppk[1] +=  RotR1(ppk[0] ^ Mk16(tk[15], tk[14]));
+	ppk[2] +=  RotR1(ppk[1]);
+	ppk[3] +=  RotR1(ppk[2]);
+	ppk[4] +=  RotR1(ppk[3]);
+	ppk[5] +=  RotR1(ppk[4]);
+
+	rc4key[0] = Hi8(tsc_IV16);
+	rc4key[1] = (Hi8(tsc_IV16) | 0x20) & 0x7f;
+	rc4key[2] = Lo8(tsc_IV16);
+	rc4key[3] = Lo8((ppk[5] ^ Mk16(tk[1], tk[0])) >> 1);
+
+	for (i = 0; i < 6; i++) {
+		rc4key[4 + 2 * i] = Lo8(ppk[i]);
+		rc4key[5 + 2 * i] = Hi8(ppk[i]);
+	}
+}
+
+
+/* Add TKIP IV and Ext. IV at @pos. @iv0, @iv1, and @iv2 are the first octets
+ * of the IV. Returns pointer to the octet following IVs (i.e., beginning of
+ * the packet payload). */
+u8 * ieee80211_tkip_add_iv(u8 *pos, struct ieee80211_key *key,
+			   u8 iv0, u8 iv1, u8 iv2)
+{
+	*pos++ = iv0;
+	*pos++ = iv1;
+	*pos++ = iv2;
+	*pos++ = (key->keyidx << 6) | (1 << 5) /* Ext IV */;
+	*pos++ = key->u.tkip.iv32 & 0xff;
+	*pos++ = (key->u.tkip.iv32 >> 8) & 0xff;
+	*pos++ = (key->u.tkip.iv32 >> 16) & 0xff;
+	*pos++ = (key->u.tkip.iv32 >> 24) & 0xff;
+	return pos;
+}
+
+
+void ieee80211_tkip_gen_phase1key(struct ieee80211_key *key, u8 *ta,
+				  u16 *phase1key)
+{
+	tkip_mixing_phase1(ta, &key->key[ALG_TKIP_TEMP_ENCR_KEY],
+			   key->u.tkip.iv32, phase1key);
+}
+
+void ieee80211_tkip_gen_rc4key(struct ieee80211_key *key, u8 *ta,
+			       u8 *rc4key)
+{
+	/* Calculate per-packet key */
+	if (key->u.tkip.iv16 == 0 || !key->u.tkip.tx_initialized) {
+		/* IV16 wrapped around - perform TKIP phase 1 */
+		tkip_mixing_phase1(ta, &key->key[ALG_TKIP_TEMP_ENCR_KEY],
+				   key->u.tkip.iv32, key->u.tkip.p1k);
+		key->u.tkip.tx_initialized = 1;
+	}
+
+	tkip_mixing_phase2(key->u.tkip.p1k, &key->key[ALG_TKIP_TEMP_ENCR_KEY],
+			   key->u.tkip.iv16, rc4key);
+}
+
+/* Encrypt packet payload with TKIP using @key. @pos is a pointer to the
+ * beginning of the buffer containing payload. This payload must include
+ * headroom of eight octets for IV and Ext. IV and taildroom of four octets
+ * for ICV. @payload_len is the length of payload (_not_ including extra
+ * headroom and tailroom). @ta is the transmitter addresses. */
+void ieee80211_tkip_encrypt_data(struct crypto_blkcipher *tfm,
+				 struct ieee80211_key *key,
+				 u8 *pos, size_t payload_len, u8 *ta)
+{
+	u8 rc4key[16];
+
+	ieee80211_tkip_gen_rc4key(key, ta, rc4key);
+	pos = ieee80211_tkip_add_iv(pos, key, rc4key[0], rc4key[1], rc4key[2]);
+	ieee80211_wep_encrypt_data(tfm, rc4key, 16, pos, payload_len);
+}
+
+
+/* Decrypt packet payload with TKIP using @key. @pos is a pointer to the
+ * beginning of the buffer containing IEEE 802.11 header payload, i.e.,
+ * including IV, Ext. IV, real data, Michael MIC, ICV. @payload_len is the
+ * length of payload, including IV, Ext. IV, MIC, ICV.  */
+int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm,
+				struct ieee80211_key *key,
+				u8 *payload, size_t payload_len, u8 *ta,
+				int only_iv, int queue)
+{
+	u32 iv32;
+	u32 iv16;
+	u8 rc4key[16], keyid, *pos = payload;
+	int res;
+
+	if (payload_len < 12)
+		return -1;
+
+	iv16 = (pos[0] << 8) | pos[2];
+	keyid = pos[3];
+	iv32 = pos[4] | (pos[5] << 8) | (pos[6] << 16) | (pos[7] << 24);
+	pos += 8;
+#ifdef CONFIG_TKIP_DEBUG
+	{
+		int i;
+		printk(KERN_DEBUG "TKIP decrypt: data(len=%zd)", payload_len);
+		for (i = 0; i < payload_len; i++)
+			printk(" %02x", payload[i]);
+		printk("\n");
+		printk(KERN_DEBUG "TKIP decrypt: iv16=%04x iv32=%08x\n",
+		       iv16, iv32);
+	}
+#endif /* CONFIG_TKIP_DEBUG */
+
+	if (!(keyid & (1 << 5)))
+		return TKIP_DECRYPT_NO_EXT_IV;
+
+	if ((keyid >> 6) != key->keyidx)
+		return TKIP_DECRYPT_INVALID_KEYIDX;
+
+	if (key->u.tkip.rx_initialized[queue] &&
+	    (iv32 < key->u.tkip.iv32_rx[queue] ||
+	     (iv32 == key->u.tkip.iv32_rx[queue] &&
+	      iv16 <= key->u.tkip.iv16_rx[queue]))) {
+#ifdef CONFIG_TKIP_DEBUG
+		printk(KERN_DEBUG "TKIP replay detected for RX frame from "
+		       MAC_FMT " (RX IV (%04x,%02x) <= prev. IV (%04x,%02x)\n",
+		       MAC_ARG(ta),
+		       iv32, iv16, key->u.tkip.iv32_rx[queue],
+		       key->u.tkip.iv16_rx[queue]);
+#endif /* CONFIG_TKIP_DEBUG */
+		return TKIP_DECRYPT_REPLAY;
+	}
+
+	if (only_iv) {
+		res = TKIP_DECRYPT_OK;
+		key->u.tkip.rx_initialized[queue] = 1;
+		goto done;
+	}
+
+	if (!key->u.tkip.rx_initialized[queue] ||
+	    key->u.tkip.iv32_rx[queue] != iv32) {
+		key->u.tkip.rx_initialized[queue] = 1;
+		/* IV16 wrapped around - perform TKIP phase 1 */
+		tkip_mixing_phase1(ta, &key->key[ALG_TKIP_TEMP_ENCR_KEY],
+				   iv32, key->u.tkip.p1k_rx[queue]);
+#ifdef CONFIG_TKIP_DEBUG
+		{
+			int i;
+			printk(KERN_DEBUG "TKIP decrypt: Phase1 TA=" MAC_FMT
+			       " TK=", MAC_ARG(ta));
+			for (i = 0; i < 16; i++)
+				printk("%02x ",
+				       key->key[ALG_TKIP_TEMP_ENCR_KEY + i]);
+			printk("\n");
+			printk(KERN_DEBUG "TKIP decrypt: P1K=");
+			for (i = 0; i < 5; i++)
+				printk("%04x ", key->u.tkip.p1k_rx[queue][i]);
+			printk("\n");
+		}
+#endif /* CONFIG_TKIP_DEBUG */
+	}
+
+	tkip_mixing_phase2(key->u.tkip.p1k_rx[queue],
+			   &key->key[ALG_TKIP_TEMP_ENCR_KEY],
+			   iv16, rc4key);
+#ifdef CONFIG_TKIP_DEBUG
+	{
+		int i;
+		printk(KERN_DEBUG "TKIP decrypt: Phase2 rc4key=");
+		for (i = 0; i < 16; i++)
+			printk("%02x ", rc4key[i]);
+		printk("\n");
+	}
+#endif /* CONFIG_TKIP_DEBUG */
+
+	res = ieee80211_wep_decrypt_data(tfm, rc4key, 16, pos, payload_len - 12);
+ done:
+	if (res == TKIP_DECRYPT_OK) {
+		/* FIX: these should be updated only after Michael MIC has been
+		 * verified */
+		/* Record previously received IV */
+		key->u.tkip.iv32_rx[queue] = iv32;
+		key->u.tkip.iv16_rx[queue] = iv16;
+	}
+
+	return res;
+}
+
+
diff --git a/net/mac80211/tkip.h b/net/mac80211/tkip.h
new file mode 100644
index 0000000..a0d181a
--- /dev/null
+++ b/net/mac80211/tkip.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2002-2004, Instant802 Networks, Inc.
+ *
+ * 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 TKIP_H
+#define TKIP_H
+
+#include <linux/types.h>
+#include <linux/crypto.h>
+#include "ieee80211_key.h"
+
+u8 * ieee80211_tkip_add_iv(u8 *pos, struct ieee80211_key *key,
+			   u8 iv0, u8 iv1, u8 iv2);
+void ieee80211_tkip_gen_phase1key(struct ieee80211_key *key, u8 *ta,
+				  u16 *phase1key);
+void ieee80211_tkip_gen_rc4key(struct ieee80211_key *key, u8 *ta,
+			       u8 *rc4key);
+void ieee80211_tkip_encrypt_data(struct crypto_blkcipher *tfm,
+				 struct ieee80211_key *key,
+				 u8 *pos, size_t payload_len, u8 *ta);
+enum {
+	TKIP_DECRYPT_OK = 0,
+	TKIP_DECRYPT_NO_EXT_IV = -1,
+	TKIP_DECRYPT_INVALID_KEYIDX = -2,
+	TKIP_DECRYPT_REPLAY = -3,
+};
+int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm,
+				struct ieee80211_key *key,
+				u8 *payload, size_t payload_len, u8 *ta,
+				int only_iv, int queue);
+
+#endif /* TKIP_H */
diff --git a/net/mac80211/wep.c b/net/mac80211/wep.c
new file mode 100644
index 0000000..1ad3d75
--- /dev/null
+++ b/net/mac80211/wep.c
@@ -0,0 +1,328 @@
+/*
+ * Software WEP encryption implementation
+ * Copyright 2002, Jouni Malinen <jkmaline@cc.hut.fi>
+ * Copyright 2003, Instant802 Networks, Inc.
+ *
+ * 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/netdevice.h>
+#include <linux/types.h>
+#include <linux/random.h>
+#include <linux/compiler.h>
+#include <linux/crc32.h>
+#include <linux/crypto.h>
+#include <linux/err.h>
+#include <linux/mm.h>
+#include <asm/scatterlist.h>
+
+#include <net/mac80211.h>
+#include "ieee80211_i.h"
+#include "wep.h"
+
+
+int ieee80211_wep_init(struct ieee80211_local *local)
+{
+	/* start WEP IV from a random value */
+	get_random_bytes(&local->wep_iv, WEP_IV_LEN);
+
+	local->wep_tx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0,
+						CRYPTO_ALG_ASYNC);
+	if (IS_ERR(local->wep_tx_tfm))
+		return -ENOMEM;
+
+	local->wep_rx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0,
+						CRYPTO_ALG_ASYNC);
+	if (IS_ERR(local->wep_rx_tfm)) {
+		crypto_free_blkcipher(local->wep_tx_tfm);
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+void ieee80211_wep_free(struct ieee80211_local *local)
+{
+	crypto_free_blkcipher(local->wep_tx_tfm);
+	crypto_free_blkcipher(local->wep_rx_tfm);
+}
+
+static inline int ieee80211_wep_weak_iv(u32 iv, int keylen)
+{
+	/* Fluhrer, Mantin, and Shamir have reported weaknesses in the
+	 * key scheduling algorithm of RC4. At least IVs (KeyByte + 3,
+	 * 0xff, N) can be used to speedup attacks, so avoid using them. */
+	if ((iv & 0xff00) == 0xff00) {
+		u8 B = (iv >> 16) & 0xff;
+		if (B >= 3 && B < 3 + keylen)
+			return 1;
+	}
+	return 0;
+}
+
+
+void ieee80211_wep_get_iv(struct ieee80211_local *local,
+			  struct ieee80211_key *key, u8 *iv)
+{
+	local->wep_iv++;
+	if (ieee80211_wep_weak_iv(local->wep_iv, key->keylen))
+		local->wep_iv += 0x0100;
+
+	if (!iv)
+		return;
+
+	*iv++ = (local->wep_iv >> 16) & 0xff;
+	*iv++ = (local->wep_iv >> 8) & 0xff;
+	*iv++ = local->wep_iv & 0xff;
+	*iv++ = key->keyidx << 6;
+}
+
+
+u8 * ieee80211_wep_add_iv(struct ieee80211_local *local,
+			  struct sk_buff *skb,
+			  struct ieee80211_key *key)
+{
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+	u16 fc;
+	int hdrlen;
+	u8 *newhdr;
+
+	fc = le16_to_cpu(hdr->frame_control);
+	fc |= IEEE80211_FCTL_PROTECTED;
+	hdr->frame_control = cpu_to_le16(fc);
+
+	if ((skb_headroom(skb) < WEP_IV_LEN ||
+	     skb_tailroom(skb) < WEP_ICV_LEN)) {
+		I802_DEBUG_INC(local->tx_expand_skb_head);
+		if (unlikely(pskb_expand_head(skb, WEP_IV_LEN, WEP_ICV_LEN,
+					      GFP_ATOMIC)))
+			return NULL;
+	}
+
+	hdrlen = ieee80211_get_hdrlen(fc);
+	newhdr = skb_push(skb, WEP_IV_LEN);
+	memmove(newhdr, newhdr + WEP_IV_LEN, hdrlen);
+	ieee80211_wep_get_iv(local, key, newhdr + hdrlen);
+	return newhdr + hdrlen;
+}
+
+
+void ieee80211_wep_remove_iv(struct ieee80211_local *local,
+			     struct sk_buff *skb,
+			     struct ieee80211_key *key)
+{
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+	u16 fc;
+	int hdrlen;
+
+	fc = le16_to_cpu(hdr->frame_control);
+	hdrlen = ieee80211_get_hdrlen(fc);
+	memmove(skb->data + WEP_IV_LEN, skb->data, hdrlen);
+	skb_pull(skb, WEP_IV_LEN);
+}
+
+
+/* Perform WEP encryption using given key. data buffer must have tailroom
+ * for 4-byte ICV. data_len must not include this ICV. Note: this function
+ * does _not_ add IV. data = RC4(data | CRC32(data)) */
+void ieee80211_wep_encrypt_data(struct crypto_blkcipher *tfm, u8 *rc4key,
+				size_t klen, u8 *data, size_t data_len)
+{
+	struct blkcipher_desc desc = { .tfm = tfm };
+	struct scatterlist sg;
+	__le32 *icv;
+
+	icv = (__le32 *)(data + data_len);
+	*icv = cpu_to_le32(~crc32_le(~0, data, data_len));
+
+	crypto_blkcipher_setkey(tfm, rc4key, klen);
+	sg.page = virt_to_page(data);
+	sg.offset = offset_in_page(data);
+	sg.length = data_len + WEP_ICV_LEN;
+	crypto_blkcipher_encrypt(&desc, &sg, &sg, sg.length);
+}
+
+
+/* Perform WEP encryption on given skb. 4 bytes of extra space (IV) in the
+ * beginning of the buffer 4 bytes of extra space (ICV) in the end of the
+ * buffer will be added. Both IV and ICV will be transmitted, so the
+ * payload length increases with 8 bytes.
+ *
+ * WEP frame payload: IV + TX key idx, RC4(data), ICV = RC4(CRC32(data))
+ */
+int ieee80211_wep_encrypt(struct ieee80211_local *local, struct sk_buff *skb,
+			  struct ieee80211_key *key)
+{
+	u32 klen;
+	u8 *rc4key, *iv;
+	size_t len;
+
+	if (!key || key->alg != ALG_WEP)
+		return -1;
+
+	klen = 3 + key->keylen;
+	rc4key = kmalloc(klen, GFP_ATOMIC);
+	if (!rc4key)
+		return -1;
+
+	iv = ieee80211_wep_add_iv(local, skb, key);
+	if (!iv) {
+		kfree(rc4key);
+		return -1;
+	}
+
+	len = skb->len - (iv + WEP_IV_LEN - skb->data);
+
+	/* Prepend 24-bit IV to RC4 key */
+	memcpy(rc4key, iv, 3);
+
+	/* Copy rest of the WEP key (the secret part) */
+	memcpy(rc4key + 3, key->key, key->keylen);
+
+	/* Add room for ICV */
+	skb_put(skb, WEP_ICV_LEN);
+
+	ieee80211_wep_encrypt_data(local->wep_tx_tfm, rc4key, klen,
+				   iv + WEP_IV_LEN, len);
+
+	kfree(rc4key);
+
+	return 0;
+}
+
+
+/* Perform WEP decryption using given key. data buffer includes encrypted
+ * payload, including 4-byte ICV, but _not_ IV. data_len must not include ICV.
+ * Return 0 on success and -1 on ICV mismatch. */
+int ieee80211_wep_decrypt_data(struct crypto_blkcipher *tfm, u8 *rc4key,
+			       size_t klen, u8 *data, size_t data_len)
+{
+	struct blkcipher_desc desc = { .tfm = tfm };
+	struct scatterlist sg;
+	__le32 crc;
+
+	crypto_blkcipher_setkey(tfm, rc4key, klen);
+	sg.page = virt_to_page(data);
+	sg.offset = offset_in_page(data);
+	sg.length = data_len + WEP_ICV_LEN;
+	crypto_blkcipher_decrypt(&desc, &sg, &sg, sg.length);
+
+	crc = cpu_to_le32(~crc32_le(~0, data, data_len));
+	if (memcmp(&crc, data + data_len, WEP_ICV_LEN) != 0)
+		/* ICV mismatch */
+		return -1;
+
+	return 0;
+}
+
+
+/* Perform WEP decryption on given skb. Buffer includes whole WEP part of
+ * the frame: IV (4 bytes), encrypted payload (including SNAP header),
+ * ICV (4 bytes). skb->len includes both IV and ICV.
+ *
+ * Returns 0 if frame was decrypted successfully and ICV was correct and -1 on
+ * failure. If frame is OK, IV and ICV will be removed, i.e., decrypted payload
+ * is moved to the beginning of the skb and skb length will be reduced.
+ */
+int ieee80211_wep_decrypt(struct ieee80211_local *local, struct sk_buff *skb,
+			  struct ieee80211_key *key)
+{
+	u32 klen;
+	u8 *rc4key;
+	u8 keyidx;
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+	u16 fc;
+	int hdrlen;
+	size_t len;
+	int ret = 0;
+
+	fc = le16_to_cpu(hdr->frame_control);
+	if (!(fc & IEEE80211_FCTL_PROTECTED))
+		return -1;
+
+	hdrlen = ieee80211_get_hdrlen(fc);
+
+	if (skb->len < 8 + hdrlen)
+		return -1;
+
+	len = skb->len - hdrlen - 8;
+
+	keyidx = skb->data[hdrlen + 3] >> 6;
+
+	if (!key || keyidx != key->keyidx || key->alg != ALG_WEP)
+		return -1;
+
+	klen = 3 + key->keylen;
+
+	rc4key = kmalloc(klen, GFP_ATOMIC);
+	if (!rc4key)
+		return -1;
+
+	/* Prepend 24-bit IV to RC4 key */
+	memcpy(rc4key, skb->data + hdrlen, 3);
+
+	/* Copy rest of the WEP key (the secret part) */
+	memcpy(rc4key + 3, key->key, key->keylen);
+
+	if (ieee80211_wep_decrypt_data(local->wep_rx_tfm, rc4key, klen,
+				       skb->data + hdrlen + WEP_IV_LEN,
+				       len)) {
+		printk(KERN_DEBUG "WEP decrypt failed (ICV)\n");
+		ret = -1;
+	}
+
+	kfree(rc4key);
+
+	/* Trim ICV */
+	skb_trim(skb, skb->len - WEP_ICV_LEN);
+
+	/* Remove IV */
+	memmove(skb->data + WEP_IV_LEN, skb->data, hdrlen);
+	skb_pull(skb, WEP_IV_LEN);
+
+	return ret;
+}
+
+
+int ieee80211_wep_get_keyidx(struct sk_buff *skb)
+{
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+	u16 fc;
+	int hdrlen;
+
+	fc = le16_to_cpu(hdr->frame_control);
+	if (!(fc & IEEE80211_FCTL_PROTECTED))
+		return -1;
+
+	hdrlen = ieee80211_get_hdrlen(fc);
+
+	if (skb->len < 8 + hdrlen)
+		return -1;
+
+	return skb->data[hdrlen + 3] >> 6;
+}
+
+
+u8 * ieee80211_wep_is_weak_iv(struct sk_buff *skb, struct ieee80211_key *key)
+{
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+	u16 fc;
+	int hdrlen;
+	u8 *ivpos;
+	u32 iv;
+
+	fc = le16_to_cpu(hdr->frame_control);
+	if (!(fc & IEEE80211_FCTL_PROTECTED))
+		return NULL;
+
+	hdrlen = ieee80211_get_hdrlen(fc);
+	ivpos = skb->data + hdrlen;
+	iv = (ivpos[0] << 16) | (ivpos[1] << 8) | ivpos[2];
+
+	if (ieee80211_wep_weak_iv(iv, key->keylen))
+		return ivpos;
+
+	return NULL;
+}
diff --git a/net/mac80211/wep.h b/net/mac80211/wep.h
new file mode 100644
index 0000000..bfe29e8
--- /dev/null
+++ b/net/mac80211/wep.h
@@ -0,0 +1,40 @@
+/*
+ * Software WEP encryption implementation
+ * Copyright 2002, Jouni Malinen <jkmaline@cc.hut.fi>
+ * Copyright 2003, Instant802 Networks, Inc.
+ *
+ * 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 WEP_H
+#define WEP_H
+
+#include <linux/skbuff.h>
+#include <linux/types.h>
+#include "ieee80211_i.h"
+#include "ieee80211_key.h"
+
+int ieee80211_wep_init(struct ieee80211_local *local);
+void ieee80211_wep_free(struct ieee80211_local *local);
+void ieee80211_wep_get_iv(struct ieee80211_local *local,
+			  struct ieee80211_key *key, u8 *iv);
+u8 * ieee80211_wep_add_iv(struct ieee80211_local *local,
+			  struct sk_buff *skb,
+			  struct ieee80211_key *key);
+void ieee80211_wep_remove_iv(struct ieee80211_local *local,
+			     struct sk_buff *skb,
+			     struct ieee80211_key *key);
+void ieee80211_wep_encrypt_data(struct crypto_blkcipher *tfm, u8 *rc4key,
+				size_t klen, u8 *data, size_t data_len);
+int ieee80211_wep_decrypt_data(struct crypto_blkcipher *tfm, u8 *rc4key,
+			       size_t klen, u8 *data, size_t data_len);
+int ieee80211_wep_encrypt(struct ieee80211_local *local, struct sk_buff *skb,
+			  struct ieee80211_key *key);
+int ieee80211_wep_decrypt(struct ieee80211_local *local, struct sk_buff *skb,
+			  struct ieee80211_key *key);
+int ieee80211_wep_get_keyidx(struct sk_buff *skb);
+u8 * ieee80211_wep_is_weak_iv(struct sk_buff *skb, struct ieee80211_key *key);
+
+#endif /* WEP_H */
diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c
new file mode 100644
index 0000000..89ce815
--- /dev/null
+++ b/net/mac80211/wme.c
@@ -0,0 +1,678 @@
+/*
+ * Copyright 2004, Instant802 Networks, Inc.
+ *
+ * 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/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/module.h>
+#include <linux/if_arp.h>
+#include <linux/types.h>
+#include <net/ip.h>
+#include <net/pkt_sched.h>
+
+#include <net/mac80211.h>
+#include "ieee80211_i.h"
+#include "wme.h"
+
+static inline int WLAN_FC_IS_QOS_DATA(u16 fc)
+{
+	return (fc & 0x8C) == 0x88;
+}
+
+
+ieee80211_txrx_result
+ieee80211_rx_h_parse_qos(struct ieee80211_txrx_data *rx)
+{
+	u8 *data = rx->skb->data;
+	int tid;
+
+	/* does the frame have a qos control field? */
+	if (WLAN_FC_IS_QOS_DATA(rx->fc)) {
+		u8 *qc = data + ieee80211_get_hdrlen(rx->fc) - QOS_CONTROL_LEN;
+		/* frame has qos control */
+		tid = qc[0] & QOS_CONTROL_TID_MASK;
+	} else {
+		if (unlikely((rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT)) {
+			/* Separate TID for management frames */
+			tid = NUM_RX_DATA_QUEUES - 1;
+		} else {
+			/* no qos control present */
+			tid = 0; /* 802.1d - Best Effort */
+		}
+	}
+#ifdef CONFIG_MAC80211_DEBUG_COUNTERS
+	I802_DEBUG_INC(rx->local->wme_rx_queue[tid]);
+	if (rx->sta) {
+		I802_DEBUG_INC(rx->sta->wme_rx_queue[tid]);
+	}
+#endif /* CONFIG_MAC80211_DEBUG_COUNTERS */
+
+	rx->u.rx.queue = tid;
+	/* Set skb->priority to 1d tag if highest order bit of TID is not set.
+	 * For now, set skb->priority to 0 for other cases. */
+	rx->skb->priority = (tid > 7) ? 0 : tid;
+
+	return TXRX_CONTINUE;
+}
+
+
+ieee80211_txrx_result
+ieee80211_rx_h_remove_qos_control(struct ieee80211_txrx_data *rx)
+{
+	u16 fc = rx->fc;
+	u8 *data = rx->skb->data;
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) data;
+
+	if (!WLAN_FC_IS_QOS_DATA(fc))
+		return TXRX_CONTINUE;
+
+	/* remove the qos control field, update frame type and meta-data */
+	memmove(data + 2, data, ieee80211_get_hdrlen(fc) - 2);
+	hdr = (struct ieee80211_hdr *) skb_pull(rx->skb, 2);
+	/* change frame type to non QOS */
+	rx->fc = fc &= ~IEEE80211_STYPE_QOS_DATA;
+	hdr->frame_control = cpu_to_le16(fc);
+
+	return TXRX_CONTINUE;
+}
+
+
+#ifdef CONFIG_NET_SCHED
+/* maximum number of hardware queues we support. */
+#define TC_80211_MAX_QUEUES 8
+
+struct ieee80211_sched_data
+{
+	struct tcf_proto *filter_list;
+	struct Qdisc *queues[TC_80211_MAX_QUEUES];
+	struct sk_buff_head requeued[TC_80211_MAX_QUEUES];
+};
+
+
+/* given a data frame determine the 802.1p/1d tag to use */
+static inline unsigned classify_1d(struct sk_buff *skb, struct Qdisc *qd)
+{
+	struct iphdr *ip;
+	int dscp;
+	int offset;
+
+	struct ieee80211_sched_data *q = qdisc_priv(qd);
+	struct tcf_result res = { -1, 0 };
+
+	/* if there is a user set filter list, call out to that */
+	if (q->filter_list) {
+		tc_classify(skb, q->filter_list, &res);
+		if (res.class != -1)
+			return res.class;
+	}
+
+	/* skb->priority values from 256->263 are magic values to
+	 * directly indicate a specific 802.1d priority.
+	 * This is used to allow 802.1d priority to be passed directly in
+	 * from VLAN tags, etc. */
+	if (skb->priority >= 256 && skb->priority <= 263)
+		return skb->priority - 256;
+
+	/* check there is a valid IP header present */
+	offset = ieee80211_get_hdrlen_from_skb(skb) + 8 /* LLC + proto */;
+	if (skb->protocol != __constant_htons(ETH_P_IP) ||
+	    skb->len < offset + sizeof(*ip))
+		return 0;
+
+	ip = (struct iphdr *) (skb->data + offset);
+
+	dscp = ip->tos & 0xfc;
+	if (dscp & 0x1c)
+		return 0;
+	return dscp >> 5;
+}
+
+
+static inline int wme_downgrade_ac(struct sk_buff *skb)
+{
+	switch (skb->priority) {
+	case 6:
+	case 7:
+		skb->priority = 5; /* VO -> VI */
+		return 0;
+	case 4:
+	case 5:
+		skb->priority = 3; /* VI -> BE */
+		return 0;
+	case 0:
+	case 3:
+		skb->priority = 2; /* BE -> BK */
+		return 0;
+	default:
+		return -1;
+	}
+}
+
+
+/* positive return value indicates which queue to use
+ * negative return value indicates to drop the frame */
+static inline int classify80211(struct sk_buff *skb, struct Qdisc *qd)
+{
+	struct ieee80211_local *local = wdev_priv(qd->dev->ieee80211_ptr);
+	struct ieee80211_tx_packet_data *pkt_data =
+		(struct ieee80211_tx_packet_data *) skb->cb;
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+	unsigned short fc = le16_to_cpu(hdr->frame_control);
+	int qos;
+	const int ieee802_1d_to_ac[8] = { 2, 3, 3, 2, 1, 1, 0, 0 };
+
+	/* see if frame is data or non data frame */
+	if (unlikely((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA)) {
+		/* management frames go on AC_VO queue, but are sent
+		* without QoS control fields */
+		return IEEE80211_TX_QUEUE_DATA0;
+	}
+
+	if (unlikely(pkt_data->mgmt_iface)) {
+		/* Data frames from hostapd (mainly, EAPOL) use AC_VO
+		* and they will include QoS control fields if
+		* the target STA is using WME. */
+		skb->priority = 7;
+		return ieee802_1d_to_ac[skb->priority];
+	}
+
+	/* is this a QoS frame? */
+	qos = fc & IEEE80211_STYPE_QOS_DATA;
+
+	if (!qos) {
+		skb->priority = 0; /* required for correct WPA/11i MIC */
+		return ieee802_1d_to_ac[skb->priority];
+	}
+
+	/* use the data classifier to determine what 802.1d tag the
+	* data frame has */
+	skb->priority = classify_1d(skb, qd);
+
+	/* incase we are a client verify acm is not set for this ac */
+	while (unlikely(local->wmm_acm & BIT(skb->priority))) {
+		if (wme_downgrade_ac(skb)) {
+			/* No AC with lower priority has acm=0,
+			* drop packet. */
+			return -1;
+		}
+	}
+
+	/* look up which queue to use for frames with this 1d tag */
+	return ieee802_1d_to_ac[skb->priority];
+}
+
+
+static int wme_qdiscop_enqueue(struct sk_buff *skb, struct Qdisc* qd)
+{
+	struct ieee80211_local *local = wdev_priv(qd->dev->ieee80211_ptr);
+	struct ieee80211_sched_data *q = qdisc_priv(qd);
+	struct ieee80211_tx_packet_data *pkt_data =
+		(struct ieee80211_tx_packet_data *) skb->cb;
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+	unsigned short fc = le16_to_cpu(hdr->frame_control);
+	struct Qdisc *qdisc;
+	int err, queue;
+
+	if (pkt_data->requeue) {
+		skb_queue_tail(&q->requeued[pkt_data->queue], skb);
+		qd->q.qlen++;
+		return 0;
+	}
+
+	queue = classify80211(skb, qd);
+
+	/* now we know the 1d priority, fill in the QoS header if there is one
+	 */
+	if (WLAN_FC_IS_QOS_DATA(fc)) {
+		u8 *p = skb->data + ieee80211_get_hdrlen(fc) - 2;
+		u8 qos_hdr = skb->priority & QOS_CONTROL_TAG1D_MASK;
+		if (local->wifi_wme_noack_test)
+			qos_hdr |= QOS_CONTROL_ACK_POLICY_NOACK <<
+					QOS_CONTROL_ACK_POLICY_SHIFT;
+		/* qos header is 2 bytes, second reserved */
+		*p = qos_hdr;
+		p++;
+		*p = 0;
+	}
+
+	if (unlikely(queue >= local->hw.queues)) {
+#if 0
+		if (net_ratelimit()) {
+			printk(KERN_DEBUG "%s - queue=%d (hw does not "
+			       "support) -> %d\n",
+			       __func__, queue, local->hw.queues - 1);
+		}
+#endif
+		queue = local->hw.queues - 1;
+	}
+
+	if (unlikely(queue < 0)) {
+			kfree_skb(skb);
+			err = NET_XMIT_DROP;
+	} else {
+		pkt_data->queue = (unsigned int) queue;
+		qdisc = q->queues[queue];
+		err = qdisc->enqueue(skb, qdisc);
+		if (err == NET_XMIT_SUCCESS) {
+			qd->q.qlen++;
+			qd->bstats.bytes += skb->len;
+			qd->bstats.packets++;
+			return NET_XMIT_SUCCESS;
+		}
+	}
+	qd->qstats.drops++;
+	return err;
+}
+
+
+/* TODO: clean up the cases where master_hard_start_xmit
+ * returns non 0 - it shouldn't ever do that. Once done we
+ * can remove this function */
+static int wme_qdiscop_requeue(struct sk_buff *skb, struct Qdisc* qd)
+{
+	struct ieee80211_sched_data *q = qdisc_priv(qd);
+	struct ieee80211_tx_packet_data *pkt_data =
+		(struct ieee80211_tx_packet_data *) skb->cb;
+	struct Qdisc *qdisc;
+	int err;
+
+	/* we recorded which queue to use earlier! */
+	qdisc = q->queues[pkt_data->queue];
+
+	if ((err = qdisc->ops->requeue(skb, qdisc)) == 0) {
+		qd->q.qlen++;
+		return 0;
+	}
+	qd->qstats.drops++;
+	return err;
+}
+
+
+static struct sk_buff *wme_qdiscop_dequeue(struct Qdisc* qd)
+{
+	struct ieee80211_sched_data *q = qdisc_priv(qd);
+	struct net_device *dev = qd->dev;
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+	struct ieee80211_hw *hw = &local->hw;
+	struct sk_buff *skb;
+	struct Qdisc *qdisc;
+	int queue;
+
+	/* check all the h/w queues in numeric/priority order */
+	for (queue = 0; queue < hw->queues; queue++) {
+		/* see if there is room in this hardware queue */
+		if (test_bit(IEEE80211_LINK_STATE_XOFF,
+			     &local->state[queue]) ||
+		    test_bit(IEEE80211_LINK_STATE_PENDING,
+			     &local->state[queue]))
+			continue;
+
+		/* there is space - try and get a frame */
+		skb = skb_dequeue(&q->requeued[queue]);
+		if (skb) {
+			qd->q.qlen--;
+			return skb;
+		}
+
+		qdisc = q->queues[queue];
+		skb = qdisc->dequeue(qdisc);
+		if (skb) {
+			qd->q.qlen--;
+			return skb;
+		}
+	}
+	/* returning a NULL here when all the h/w queues are full means we
+	 * never need to call netif_stop_queue in the driver */
+	return NULL;
+}
+
+
+static void wme_qdiscop_reset(struct Qdisc* qd)
+{
+	struct ieee80211_sched_data *q = qdisc_priv(qd);
+	struct ieee80211_local *local = wdev_priv(qd->dev->ieee80211_ptr);
+	struct ieee80211_hw *hw = &local->hw;
+	int queue;
+
+	/* QUESTION: should we have some hardware flush functionality here? */
+
+	for (queue = 0; queue < hw->queues; queue++) {
+		skb_queue_purge(&q->requeued[queue]);
+		qdisc_reset(q->queues[queue]);
+	}
+	qd->q.qlen = 0;
+}
+
+
+static void wme_qdiscop_destroy(struct Qdisc* qd)
+{
+	struct ieee80211_sched_data *q = qdisc_priv(qd);
+	struct ieee80211_local *local = wdev_priv(qd->dev->ieee80211_ptr);
+	struct ieee80211_hw *hw = &local->hw;
+	int queue;
+
+	tcf_destroy_chain(q->filter_list);
+	q->filter_list = NULL;
+
+	for (queue=0; queue < hw->queues; queue++) {
+		skb_queue_purge(&q->requeued[queue]);
+		qdisc_destroy(q->queues[queue]);
+		q->queues[queue] = &noop_qdisc;
+	}
+}
+
+
+/* called whenever parameters are updated on existing qdisc */
+static int wme_qdiscop_tune(struct Qdisc *qd, struct rtattr *opt)
+{
+/*	struct ieee80211_sched_data *q = qdisc_priv(qd);
+*/
+	/* check our options block is the right size */
+	/* copy any options to our local structure */
+/*	Ignore options block for now - always use static mapping
+	struct tc_ieee80211_qopt *qopt = RTA_DATA(opt);
+
+	if (opt->rta_len < RTA_LENGTH(sizeof(*qopt)))
+		return -EINVAL;
+	memcpy(q->tag2queue, qopt->tag2queue, sizeof(qopt->tag2queue));
+*/
+	return 0;
+}
+
+
+/* called during initial creation of qdisc on device */
+static int wme_qdiscop_init(struct Qdisc *qd, struct rtattr *opt)
+{
+	struct ieee80211_sched_data *q = qdisc_priv(qd);
+	struct net_device *dev = qd->dev;
+	struct ieee80211_local *local;
+	int queues;
+	int err = 0, i;
+
+	/* check that device is a mac80211 device */
+	if (!dev->ieee80211_ptr ||
+	    dev->ieee80211_ptr->wiphy->privid != mac80211_wiphy_privid)
+		return -EINVAL;
+
+	/* check this device is an ieee80211 master type device */
+	if (dev->type != ARPHRD_IEEE80211)
+		return -EINVAL;
+
+	/* check that there is no qdisc currently attached to device
+	 * this ensures that we will be the root qdisc. (I can't find a better
+	 * way to test this explicitly) */
+	if (dev->qdisc_sleeping != &noop_qdisc)
+		return -EINVAL;
+
+	if (qd->flags & TCQ_F_INGRESS)
+		return -EINVAL;
+
+	local = wdev_priv(dev->ieee80211_ptr);
+	queues = local->hw.queues;
+
+	/* if options were passed in, set them */
+	if (opt) {
+		err = wme_qdiscop_tune(qd, opt);
+	}
+
+	/* create child queues */
+	for (i = 0; i < queues; i++) {
+		skb_queue_head_init(&q->requeued[i]);
+		q->queues[i] = qdisc_create_dflt(qd->dev, &pfifo_qdisc_ops,
+						 qd->handle);
+		if (q->queues[i] == 0) {
+			q->queues[i] = &noop_qdisc;
+			printk(KERN_ERR "%s child qdisc %i creation failed", dev->name, i);
+		}
+	}
+
+	return err;
+}
+
+static int wme_qdiscop_dump(struct Qdisc *qd, struct sk_buff *skb)
+{
+/*	struct ieee80211_sched_data *q = qdisc_priv(qd);
+	unsigned char *p = skb->tail;
+	struct tc_ieee80211_qopt opt;
+
+	memcpy(&opt.tag2queue, q->tag2queue, TC_80211_MAX_TAG + 1);
+	RTA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt);
+*/	return skb->len;
+/*
+rtattr_failure:
+	skb_trim(skb, p - skb->data);*/
+	return -1;
+}
+
+
+static int wme_classop_graft(struct Qdisc *qd, unsigned long arg,
+			     struct Qdisc *new, struct Qdisc **old)
+{
+	struct ieee80211_sched_data *q = qdisc_priv(qd);
+	struct ieee80211_local *local = wdev_priv(qd->dev->ieee80211_ptr);
+	struct ieee80211_hw *hw = &local->hw;
+	unsigned long queue = arg - 1;
+
+	if (queue >= hw->queues)
+		return -EINVAL;
+
+	if (!new)
+		new = &noop_qdisc;
+
+	sch_tree_lock(qd);
+	*old = q->queues[queue];
+	q->queues[queue] = new;
+	qdisc_reset(*old);
+	sch_tree_unlock(qd);
+
+	return 0;
+}
+
+
+static struct Qdisc *
+wme_classop_leaf(struct Qdisc *qd, unsigned long arg)
+{
+	struct ieee80211_sched_data *q = qdisc_priv(qd);
+	struct ieee80211_local *local = wdev_priv(qd->dev->ieee80211_ptr);
+	struct ieee80211_hw *hw = &local->hw;
+	unsigned long queue = arg - 1;
+
+	if (queue >= hw->queues)
+		return NULL;
+
+	return q->queues[queue];
+}
+
+
+static unsigned long wme_classop_get(struct Qdisc *qd, u32 classid)
+{
+	struct ieee80211_local *local = wdev_priv(qd->dev->ieee80211_ptr);
+	struct ieee80211_hw *hw = &local->hw;
+	unsigned long queue = TC_H_MIN(classid);
+
+	if (queue - 1 >= hw->queues)
+		return 0;
+
+	return queue;
+}
+
+
+static unsigned long wme_classop_bind(struct Qdisc *qd, unsigned long parent,
+				      u32 classid)
+{
+	return wme_classop_get(qd, classid);
+}
+
+
+static void wme_classop_put(struct Qdisc *q, unsigned long cl)
+{
+}
+
+
+static int wme_classop_change(struct Qdisc *qd, u32 handle, u32 parent,
+			      struct rtattr **tca, unsigned long *arg)
+{
+	unsigned long cl = *arg;
+	struct ieee80211_local *local = wdev_priv(qd->dev->ieee80211_ptr);
+	struct ieee80211_hw *hw = &local->hw;
+
+	if (cl - 1 > hw->queues)
+		return -ENOENT;
+
+	/* TODO: put code to program hardware queue parameters here,
+	 * to allow programming from tc command line */
+
+	return 0;
+}
+
+
+/* we don't support deleting hardware queues
+ * when we add WMM-SA support - TSPECs may be deleted here */
+static int wme_classop_delete(struct Qdisc *qd, unsigned long cl)
+{
+	struct ieee80211_local *local = wdev_priv(qd->dev->ieee80211_ptr);
+	struct ieee80211_hw *hw = &local->hw;
+
+	if (cl - 1 > hw->queues)
+		return -ENOENT;
+	return 0;
+}
+
+
+static int wme_classop_dump_class(struct Qdisc *qd, unsigned long cl,
+				  struct sk_buff *skb, struct tcmsg *tcm)
+{
+	struct ieee80211_sched_data *q = qdisc_priv(qd);
+	struct ieee80211_local *local = wdev_priv(qd->dev->ieee80211_ptr);
+	struct ieee80211_hw *hw = &local->hw;
+
+	if (cl - 1 > hw->queues)
+		return -ENOENT;
+	tcm->tcm_handle = TC_H_MIN(cl);
+	tcm->tcm_parent = qd->handle;
+	tcm->tcm_info = q->queues[cl-1]->handle; /* do we need this? */
+	return 0;
+}
+
+
+static void wme_classop_walk(struct Qdisc *qd, struct qdisc_walker *arg)
+{
+	struct ieee80211_local *local = wdev_priv(qd->dev->ieee80211_ptr);
+	struct ieee80211_hw *hw = &local->hw;
+	int queue;
+
+	if (arg->stop)
+		return;
+
+	for (queue = 0; queue < hw->queues; queue++) {
+		if (arg->count < arg->skip) {
+			arg->count++;
+			continue;
+		}
+		/* we should return classids for our internal queues here
+		 * as well as the external ones */
+		if (arg->fn(qd, queue+1, arg) < 0) {
+			arg->stop = 1;
+			break;
+		}
+		arg->count++;
+	}
+}
+
+
+static struct tcf_proto ** wme_classop_find_tcf(struct Qdisc *qd,
+						unsigned long cl)
+{
+	struct ieee80211_sched_data *q = qdisc_priv(qd);
+
+	if (cl)
+		return NULL;
+
+	return &q->filter_list;
+}
+
+
+/* this qdisc is classful (i.e. has classes, some of which may have leaf qdiscs attached)
+ * - these are the operations on the classes */
+static struct Qdisc_class_ops class_ops =
+{
+	.graft = wme_classop_graft,
+	.leaf = wme_classop_leaf,
+
+	.get = wme_classop_get,
+	.put = wme_classop_put,
+	.change = wme_classop_change,
+	.delete = wme_classop_delete,
+	.walk = wme_classop_walk,
+
+	.tcf_chain = wme_classop_find_tcf,
+	.bind_tcf = wme_classop_bind,
+	.unbind_tcf = wme_classop_put,
+
+	.dump = wme_classop_dump_class,
+};
+
+
+/* queueing discipline operations */
+static struct Qdisc_ops wme_qdisc_ops =
+{
+	.next = NULL,
+	.cl_ops = &class_ops,
+	.id = "ieee80211",
+	.priv_size = sizeof(struct ieee80211_sched_data),
+
+	.enqueue = wme_qdiscop_enqueue,
+	.dequeue = wme_qdiscop_dequeue,
+	.requeue = wme_qdiscop_requeue,
+	.drop = NULL, /* drop not needed since we are always the root qdisc */
+
+	.init = wme_qdiscop_init,
+	.reset = wme_qdiscop_reset,
+	.destroy = wme_qdiscop_destroy,
+	.change = wme_qdiscop_tune,
+
+	.dump = wme_qdiscop_dump,
+};
+
+
+void ieee80211_install_qdisc(struct net_device *dev)
+{
+	struct Qdisc *qdisc;
+
+	qdisc = qdisc_create_dflt(dev, &wme_qdisc_ops, TC_H_ROOT);
+	if (!qdisc) {
+		printk(KERN_ERR "%s: qdisc installation failed\n", dev->name);
+		return;
+	}
+
+	/* same handle as would be allocated by qdisc_alloc_handle() */
+	qdisc->handle = 0x80010000;
+
+	qdisc_lock_tree(dev);
+	list_add_tail(&qdisc->list, &dev->qdisc_list);
+	dev->qdisc_sleeping = qdisc;
+	qdisc_unlock_tree(dev);
+}
+
+
+int ieee80211_qdisc_installed(struct net_device *dev)
+{
+	return dev->qdisc_sleeping->ops == &wme_qdisc_ops;
+}
+
+
+int ieee80211_wme_register(void)
+{
+	return register_qdisc(&wme_qdisc_ops);
+}
+
+
+void ieee80211_wme_unregister(void)
+{
+	unregister_qdisc(&wme_qdisc_ops);
+}
+#endif /* CONFIG_NET_SCHED */
diff --git a/net/mac80211/wme.h b/net/mac80211/wme.h
new file mode 100644
index 0000000..f0bff10
--- /dev/null
+++ b/net/mac80211/wme.h
@@ -0,0 +1,57 @@
+/*
+ * IEEE 802.11 driver (80211.o) - QoS datatypes
+ * Copyright 2004, Instant802 Networks, Inc.
+ * Copyright 2005, Devicescape Software, Inc.
+ *
+ * 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 _WME_H
+#define _WME_H
+
+#include <linux/netdevice.h>
+#include "ieee80211_i.h"
+
+#define QOS_CONTROL_LEN 2
+
+#define QOS_CONTROL_ACK_POLICY_NORMAL 0
+#define QOS_CONTROL_ACK_POLICY_NOACK 1
+
+#define QOS_CONTROL_TID_MASK 0x0f
+#define QOS_CONTROL_ACK_POLICY_SHIFT 5
+
+#define QOS_CONTROL_TAG1D_MASK 0x07
+
+ieee80211_txrx_result
+ieee80211_rx_h_parse_qos(struct ieee80211_txrx_data *rx);
+
+ieee80211_txrx_result
+ieee80211_rx_h_remove_qos_control(struct ieee80211_txrx_data *rx);
+
+#ifdef CONFIG_NET_SCHED
+void ieee80211_install_qdisc(struct net_device *dev);
+int ieee80211_qdisc_installed(struct net_device *dev);
+
+int ieee80211_wme_register(void);
+void ieee80211_wme_unregister(void);
+#else
+static inline void ieee80211_install_qdisc(struct net_device *dev)
+{
+}
+static inline int ieee80211_qdisc_installed(struct net_device *dev)
+{
+	return 0;
+}
+
+static inline int ieee80211_wme_register(void)
+{
+	return 0;
+}
+static inline void ieee80211_wme_unregister(void)
+{
+}
+#endif /* CONFIG_NET_SCHED */
+
+#endif /* _WME_H */
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c
new file mode 100644
index 0000000..783af32
--- /dev/null
+++ b/net/mac80211/wpa.c
@@ -0,0 +1,660 @@
+/*
+ * Copyright 2002-2004, Instant802 Networks, Inc.
+ *
+ * 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/netdevice.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/skbuff.h>
+#include <linux/compiler.h>
+#include <net/iw_handler.h>
+
+#include <net/mac80211.h>
+#include "ieee80211_common.h"
+#include "ieee80211_i.h"
+#include "michael.h"
+#include "tkip.h"
+#include "aes_ccm.h"
+#include "wpa.h"
+
+static int ieee80211_get_hdr_info(const struct sk_buff *skb, u8 **sa, u8 **da,
+				  u8 *qos_tid, u8 **data, size_t *data_len)
+{
+	struct ieee80211_hdr *hdr;
+	size_t hdrlen;
+	u16 fc;
+	int a4_included;
+	u8 *pos;
+
+	hdr = (struct ieee80211_hdr *) skb->data;
+	fc = le16_to_cpu(hdr->frame_control);
+
+	hdrlen = 24;
+	if ((fc & (IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS)) ==
+	    (IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS)) {
+		hdrlen += ETH_ALEN;
+		*sa = hdr->addr4;
+		*da = hdr->addr3;
+	} else if (fc & IEEE80211_FCTL_FROMDS) {
+		*sa = hdr->addr3;
+		*da = hdr->addr1;
+	} else if (fc & IEEE80211_FCTL_TODS) {
+		*sa = hdr->addr2;
+		*da = hdr->addr3;
+	} else {
+		*sa = hdr->addr2;
+		*da = hdr->addr1;
+	}
+
+	if (fc & 0x80)
+		hdrlen += 2;
+
+	*data = skb->data + hdrlen;
+	*data_len = skb->len - hdrlen;
+
+	a4_included = (fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) ==
+		(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS);
+	if ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA &&
+	    fc & IEEE80211_STYPE_QOS_DATA) {
+		pos = (u8 *) &hdr->addr4;
+		if (a4_included)
+			pos += 6;
+		*qos_tid = pos[0] & 0x0f;
+		*qos_tid |= 0x80; /* qos_included flag */
+	} else
+		*qos_tid = 0;
+
+	return skb->len < hdrlen ? -1 : 0;
+}
+
+
+ieee80211_txrx_result
+ieee80211_tx_h_michael_mic_add(struct ieee80211_txrx_data *tx)
+{
+	u8 *data, *sa, *da, *key, *mic, qos_tid;
+	size_t data_len;
+	u16 fc;
+	struct sk_buff *skb = tx->skb;
+	int authenticator;
+	int wpa_test = 0;
+
+	fc = tx->fc;
+
+	if (!tx->key || tx->key->alg != ALG_TKIP || skb->len < 24 ||
+	    !WLAN_FC_DATA_PRESENT(fc))
+		return TXRX_CONTINUE;
+
+	if (ieee80211_get_hdr_info(skb, &sa, &da, &qos_tid, &data, &data_len))
+		return TXRX_DROP;
+
+	if (!tx->key->force_sw_encrypt &&
+	    !tx->fragmented &&
+	    !(tx->local->hw.flags & IEEE80211_HW_TKIP_INCLUDE_MMIC) &&
+	    !wpa_test) {
+		/* hwaccel - with no need for preallocated room for Michael MIC
+		 */
+		return TXRX_CONTINUE;
+	}
+
+	if (skb_tailroom(skb) < MICHAEL_MIC_LEN) {
+		I802_DEBUG_INC(tx->local->tx_expand_skb_head);
+		if (unlikely(pskb_expand_head(skb, TKIP_IV_LEN,
+					      MICHAEL_MIC_LEN + TKIP_ICV_LEN,
+					      GFP_ATOMIC))) {
+			printk(KERN_DEBUG "%s: failed to allocate more memory "
+			       "for Michael MIC\n", tx->dev->name);
+			return TXRX_DROP;
+		}
+	}
+
+#if 0
+	authenticator = fc & IEEE80211_FCTL_FROMDS; /* FIX */
+#else
+	authenticator = 1;
+#endif
+	key = &tx->key->key[authenticator ? ALG_TKIP_TEMP_AUTH_TX_MIC_KEY :
+			    ALG_TKIP_TEMP_AUTH_RX_MIC_KEY];
+	mic = skb_put(skb, MICHAEL_MIC_LEN);
+	michael_mic(key, da, sa, qos_tid & 0x0f, data, data_len, mic);
+
+	return TXRX_CONTINUE;
+}
+
+
+ieee80211_txrx_result
+ieee80211_rx_h_michael_mic_verify(struct ieee80211_txrx_data *rx)
+{
+	u8 *data, *sa, *da, *key = NULL, qos_tid;
+	size_t data_len;
+	u16 fc;
+	u8 mic[MICHAEL_MIC_LEN];
+	struct sk_buff *skb = rx->skb;
+	int authenticator = 1, wpa_test = 0;
+
+	fc = rx->fc;
+
+	/* If device handles decryption totally, skip this check */
+	if ((rx->local->hw.flags & IEEE80211_HW_DEVICE_HIDES_WEP) ||
+	    (rx->local->hw.flags & IEEE80211_HW_DEVICE_STRIPS_MIC))
+		return TXRX_CONTINUE;
+
+	if (!rx->key || rx->key->alg != ALG_TKIP ||
+	    !(rx->fc & IEEE80211_FCTL_PROTECTED) || !WLAN_FC_DATA_PRESENT(fc))
+		return TXRX_CONTINUE;
+
+	if ((rx->u.rx.status->flag & RX_FLAG_DECRYPTED) &&
+	    !rx->key->force_sw_encrypt) {
+		if (rx->local->hw.flags & IEEE80211_HW_WEP_INCLUDE_IV) {
+			if (skb->len < MICHAEL_MIC_LEN)
+				return TXRX_DROP;
+		}
+		/* Need to verify Michael MIC sometimes in software even when
+		 * hwaccel is used. Atheros ar5212: fragmented frames and QoS
+		 * frames. */
+		if (!rx->fragmented && !wpa_test)
+			goto remove_mic;
+	}
+
+	if (ieee80211_get_hdr_info(skb, &sa, &da, &qos_tid, &data, &data_len)
+	    || data_len < MICHAEL_MIC_LEN)
+		return TXRX_DROP;
+
+	data_len -= MICHAEL_MIC_LEN;
+
+#if 0
+	authenticator = fc & IEEE80211_FCTL_TODS; /* FIX */
+#else
+	authenticator = 1;
+#endif
+	key = &rx->key->key[authenticator ? ALG_TKIP_TEMP_AUTH_RX_MIC_KEY :
+			    ALG_TKIP_TEMP_AUTH_TX_MIC_KEY];
+	michael_mic(key, da, sa, qos_tid & 0x0f, data, data_len, mic);
+	if (memcmp(mic, data + data_len, MICHAEL_MIC_LEN) != 0 || wpa_test) {
+		if (!rx->u.rx.ra_match)
+			return TXRX_DROP;
+
+		printk(KERN_DEBUG "%s: invalid Michael MIC in data frame from "
+		       MAC_FMT "\n", rx->dev->name, MAC_ARG(sa));
+
+		do {
+			struct ieee80211_hdr *hdr;
+			union iwreq_data wrqu;
+			char *buf = kmalloc(128, GFP_ATOMIC);
+			if (!buf)
+				break;
+
+			/* TODO: needed parameters: count, key type, TSC */
+			hdr = (struct ieee80211_hdr *) skb->data;
+			sprintf(buf, "MLME-MICHAELMICFAILURE.indication("
+				"keyid=%d %scast addr=" MAC_FMT ")",
+				rx->key->keyidx,
+				hdr->addr1[0] & 0x01 ? "broad" : "uni",
+				MAC_ARG(hdr->addr2));
+			memset(&wrqu, 0, sizeof(wrqu));
+			wrqu.data.length = strlen(buf);
+			wireless_send_event(rx->dev, IWEVCUSTOM, &wrqu, buf);
+			kfree(buf);
+		} while (0);
+
+		if (!rx->local->apdev)
+			return TXRX_DROP;
+
+		ieee80211_rx_mgmt(rx->local, rx->skb, rx->u.rx.status,
+				  ieee80211_msg_michael_mic_failure);
+
+		return TXRX_QUEUED;
+	}
+
+ remove_mic:
+	/* remove Michael MIC from payload */
+	skb_trim(skb, skb->len - MICHAEL_MIC_LEN);
+
+	return TXRX_CONTINUE;
+}
+
+
+static int tkip_encrypt_skb(struct ieee80211_txrx_data *tx,
+			    struct sk_buff *skb, int test)
+{
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+	struct ieee80211_key *key = tx->key;
+	int hdrlen, len, tailneed;
+	u16 fc;
+	u8 *pos;
+
+	fc = le16_to_cpu(hdr->frame_control);
+	hdrlen = ieee80211_get_hdrlen(fc);
+	len = skb->len - hdrlen;
+
+	tailneed = !tx->key->force_sw_encrypt ? 0 : TKIP_ICV_LEN;
+	if ((skb_headroom(skb) < TKIP_IV_LEN ||
+	     skb_tailroom(skb) < tailneed)) {
+		I802_DEBUG_INC(tx->local->tx_expand_skb_head);
+		if (unlikely(pskb_expand_head(skb, TKIP_IV_LEN, tailneed,
+					      GFP_ATOMIC)))
+			return -1;
+	}
+
+	pos = skb_push(skb, TKIP_IV_LEN);
+	memmove(pos, pos + TKIP_IV_LEN, hdrlen);
+	pos += hdrlen;
+
+	/* Increase IV for the frame */
+	key->u.tkip.iv16++;
+	if (key->u.tkip.iv16 == 0)
+		key->u.tkip.iv32++;
+
+	if (!tx->key->force_sw_encrypt) {
+		u32 flags = tx->local->hw.flags;
+		hdr = (struct ieee80211_hdr *)skb->data;
+
+		/* hwaccel - with preallocated room for IV */
+		ieee80211_tkip_add_iv(pos, key,
+				      (u8) (key->u.tkip.iv16 >> 8),
+				      (u8) (((key->u.tkip.iv16 >> 8) | 0x20) &
+					    0x7f),
+				      (u8) key->u.tkip.iv16);
+
+		if (flags & IEEE80211_HW_TKIP_REQ_PHASE2_KEY)
+			ieee80211_tkip_gen_rc4key(key, hdr->addr2,
+						  tx->u.tx.control->tkip_key);
+		else if (flags & IEEE80211_HW_TKIP_REQ_PHASE1_KEY) {
+			if (key->u.tkip.iv16 == 0 ||
+			    !key->u.tkip.tx_initialized) {
+				ieee80211_tkip_gen_phase1key(key, hdr->addr2,
+					    (u16 *)tx->u.tx.control->tkip_key);
+				key->u.tkip.tx_initialized = 1;
+				tx->u.tx.control->flags |=
+					    IEEE80211_TXCTL_TKIP_NEW_PHASE1_KEY;
+			} else
+				tx->u.tx.control->flags &=
+					    ~IEEE80211_TXCTL_TKIP_NEW_PHASE1_KEY;
+		}
+
+		tx->u.tx.control->key_idx = tx->key->hw_key_idx;
+		return 0;
+	}
+
+	/* Add room for ICV */
+	skb_put(skb, TKIP_ICV_LEN);
+
+	hdr = (struct ieee80211_hdr *) skb->data;
+	ieee80211_tkip_encrypt_data(tx->local->wep_tx_tfm,
+				    key, pos, len, hdr->addr2);
+	return 0;
+}
+
+
+ieee80211_txrx_result
+ieee80211_tx_h_tkip_encrypt(struct ieee80211_txrx_data *tx)
+{
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx->skb->data;
+	u16 fc;
+	struct ieee80211_key *key = tx->key;
+	struct sk_buff *skb = tx->skb;
+	int wpa_test = 0, test = 0;
+
+	fc = le16_to_cpu(hdr->frame_control);
+
+	if (!key || key->alg != ALG_TKIP || !WLAN_FC_DATA_PRESENT(fc))
+		return TXRX_CONTINUE;
+
+	tx->u.tx.control->icv_len = TKIP_ICV_LEN;
+	tx->u.tx.control->iv_len = TKIP_IV_LEN;
+	ieee80211_tx_set_iswep(tx);
+
+	if (!tx->key->force_sw_encrypt &&
+	    !(tx->local->hw.flags & IEEE80211_HW_WEP_INCLUDE_IV) &&
+	    !wpa_test) {
+		/* hwaccel - with no need for preallocated room for IV/ICV */
+		tx->u.tx.control->key_idx = tx->key->hw_key_idx;
+		return TXRX_CONTINUE;
+	}
+
+	if (tkip_encrypt_skb(tx, skb, test) < 0)
+		return TXRX_DROP;
+
+	if (tx->u.tx.extra_frag) {
+		int i;
+		for (i = 0; i < tx->u.tx.num_extra_frag; i++) {
+			if (tkip_encrypt_skb(tx, tx->u.tx.extra_frag[i], test)
+			    < 0)
+				return TXRX_DROP;
+		}
+	}
+
+	return TXRX_CONTINUE;
+}
+
+
+ieee80211_txrx_result
+ieee80211_rx_h_tkip_decrypt(struct ieee80211_txrx_data *rx)
+{
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data;
+	u16 fc;
+	int hdrlen, res, hwaccel = 0, wpa_test = 0;
+	struct ieee80211_key *key = rx->key;
+	struct sk_buff *skb = rx->skb;
+
+	fc = le16_to_cpu(hdr->frame_control);
+	hdrlen = ieee80211_get_hdrlen(fc);
+
+	if (!rx->key || rx->key->alg != ALG_TKIP ||
+	    !(rx->fc & IEEE80211_FCTL_PROTECTED) ||
+	    (rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA)
+		return TXRX_CONTINUE;
+
+	if (!rx->sta || skb->len - hdrlen < 12)
+		return TXRX_DROP;
+
+	if ((rx->u.rx.status->flag & RX_FLAG_DECRYPTED) &&
+	    !rx->key->force_sw_encrypt) {
+		if (!(rx->local->hw.flags & IEEE80211_HW_WEP_INCLUDE_IV)) {
+			/* Hardware takes care of all processing, including
+			 * replay protection, so no need to continue here. */
+			return TXRX_CONTINUE;
+		}
+
+		/* let TKIP code verify IV, but skip decryption */
+		hwaccel = 1;
+	}
+
+	res = ieee80211_tkip_decrypt_data(rx->local->wep_rx_tfm,
+					  key, skb->data + hdrlen,
+					  skb->len - hdrlen, rx->sta->addr,
+					  hwaccel, rx->u.rx.queue);
+	if (res != TKIP_DECRYPT_OK || wpa_test) {
+		printk(KERN_DEBUG "%s: TKIP decrypt failed for RX frame from "
+		       MAC_FMT " (res=%d)\n",
+		       rx->dev->name, MAC_ARG(rx->sta->addr), res);
+		return TXRX_DROP;
+	}
+
+	/* Trim ICV */
+	skb_trim(skb, skb->len - TKIP_ICV_LEN);
+
+	/* Remove IV */
+	memmove(skb->data + TKIP_IV_LEN, skb->data, hdrlen);
+	skb_pull(skb, TKIP_IV_LEN);
+
+	return TXRX_CONTINUE;
+}
+
+
+static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *b_0, u8 *aad,
+				int encrypted)
+{
+	u16 fc;
+	int a4_included, qos_included;
+	u8 qos_tid, *fc_pos, *data, *sa, *da;
+	int len_a;
+	size_t data_len;
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+
+	fc_pos = (u8 *) &hdr->frame_control;
+	fc = fc_pos[0] ^ (fc_pos[1] << 8);
+	a4_included = (fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) ==
+		(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS);
+
+	ieee80211_get_hdr_info(skb, &sa, &da, &qos_tid, &data, &data_len);
+	data_len -= CCMP_HDR_LEN + (encrypted ? CCMP_MIC_LEN : 0);
+	if (qos_tid & 0x80) {
+		qos_included = 1;
+		qos_tid &= 0x0f;
+	} else
+		qos_included = 0;
+	/* First block, b_0 */
+
+	b_0[0] = 0x59; /* flags: Adata: 1, M: 011, L: 001 */
+	/* Nonce: QoS Priority | A2 | PN */
+	b_0[1] = qos_tid;
+	memcpy(&b_0[2], hdr->addr2, 6);
+	memcpy(&b_0[8], pn, CCMP_PN_LEN);
+	/* l(m) */
+	b_0[14] = (data_len >> 8) & 0xff;
+	b_0[15] = data_len & 0xff;
+
+
+	/* AAD (extra authenticate-only data) / masked 802.11 header
+	 * FC | A1 | A2 | A3 | SC | [A4] | [QC] */
+
+	len_a = a4_included ? 28 : 22;
+	if (qos_included)
+		len_a += 2;
+
+	aad[0] = 0; /* (len_a >> 8) & 0xff; */
+	aad[1] = len_a & 0xff;
+	/* Mask FC: zero subtype b4 b5 b6 */
+	aad[2] = fc_pos[0] & ~(BIT(4) | BIT(5) | BIT(6));
+	/* Retry, PwrMgt, MoreData; set Protected */
+	aad[3] = (fc_pos[1] & ~(BIT(3) | BIT(4) | BIT(5))) | BIT(6);
+	memcpy(&aad[4], &hdr->addr1, 18);
+
+	/* Mask Seq#, leave Frag# */
+	aad[22] = *((u8 *) &hdr->seq_ctrl) & 0x0f;
+	aad[23] = 0;
+	if (a4_included) {
+		memcpy(&aad[24], hdr->addr4, 6);
+		aad[30] = 0;
+		aad[31] = 0;
+	} else
+		memset(&aad[24], 0, 8);
+	if (qos_included) {
+		u8 *dpos = &aad[a4_included ? 30 : 24];
+
+		/* Mask QoS Control field */
+		dpos[0] = qos_tid;
+		dpos[1] = 0;
+	}
+}
+
+
+static inline void ccmp_pn2hdr(u8 *hdr, u8 *pn, int key_id)
+{
+	hdr[0] = pn[5];
+	hdr[1] = pn[4];
+	hdr[2] = 0;
+	hdr[3] = 0x20 | (key_id << 6);
+	hdr[4] = pn[3];
+	hdr[5] = pn[2];
+	hdr[6] = pn[1];
+	hdr[7] = pn[0];
+}
+
+
+static inline int ccmp_hdr2pn(u8 *pn, u8 *hdr)
+{
+	pn[0] = hdr[7];
+	pn[1] = hdr[6];
+	pn[2] = hdr[5];
+	pn[3] = hdr[4];
+	pn[4] = hdr[1];
+	pn[5] = hdr[0];
+	return (hdr[3] >> 6) & 0x03;
+}
+
+
+static int ccmp_encrypt_skb(struct ieee80211_txrx_data *tx,
+			    struct sk_buff *skb, int test)
+{
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+	struct ieee80211_key *key = tx->key;
+	int hdrlen, len, tailneed;
+	u16 fc;
+	u8 *pos, *pn, *b_0, *aad, *scratch;
+	int i;
+
+	scratch = key->u.ccmp.tx_crypto_buf;
+	b_0 = scratch + 3 * AES_BLOCK_LEN;
+	aad = scratch + 4 * AES_BLOCK_LEN;
+
+	fc = le16_to_cpu(hdr->frame_control);
+	hdrlen = ieee80211_get_hdrlen(fc);
+	len = skb->len - hdrlen;
+
+	tailneed = !key->force_sw_encrypt ? 0 : CCMP_MIC_LEN;
+
+	if ((skb_headroom(skb) < CCMP_HDR_LEN ||
+	     skb_tailroom(skb) < tailneed)) {
+		I802_DEBUG_INC(tx->local->tx_expand_skb_head);
+		if (unlikely(pskb_expand_head(skb, CCMP_HDR_LEN, tailneed,
+					      GFP_ATOMIC)))
+			return -1;
+	}
+
+	pos = skb_push(skb, CCMP_HDR_LEN);
+	memmove(pos, pos + CCMP_HDR_LEN, hdrlen);
+	hdr = (struct ieee80211_hdr *) pos;
+	pos += hdrlen;
+
+	/* PN = PN + 1 */
+	pn = key->u.ccmp.tx_pn;
+
+	for (i = CCMP_PN_LEN - 1; i >= 0; i--) {
+		pn[i]++;
+		if (pn[i])
+			break;
+	}
+
+	ccmp_pn2hdr(pos, pn, key->keyidx);
+
+	if (!key->force_sw_encrypt) {
+		/* hwaccel - with preallocated room for CCMP header */
+		tx->u.tx.control->key_idx = key->hw_key_idx;
+		return 0;
+	}
+
+	pos += CCMP_HDR_LEN;
+	ccmp_special_blocks(skb, pn, b_0, aad, 0);
+	ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, scratch, b_0, aad, pos, len,
+				  pos, skb_put(skb, CCMP_MIC_LEN));
+
+	return 0;
+}
+
+
+ieee80211_txrx_result
+ieee80211_tx_h_ccmp_encrypt(struct ieee80211_txrx_data *tx)
+{
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx->skb->data;
+	struct ieee80211_key *key = tx->key;
+	u16 fc;
+	struct sk_buff *skb = tx->skb;
+	int test = 0;
+
+	fc = le16_to_cpu(hdr->frame_control);
+
+	if (!key || key->alg != ALG_CCMP || !WLAN_FC_DATA_PRESENT(fc))
+		return TXRX_CONTINUE;
+
+	tx->u.tx.control->icv_len = CCMP_MIC_LEN;
+	tx->u.tx.control->iv_len = CCMP_HDR_LEN;
+	ieee80211_tx_set_iswep(tx);
+
+	if (!tx->key->force_sw_encrypt &&
+	    !(tx->local->hw.flags & IEEE80211_HW_WEP_INCLUDE_IV)) {
+		/* hwaccel - with no need for preallocated room for CCMP "
+		 * header or MIC fields */
+		tx->u.tx.control->key_idx = tx->key->hw_key_idx;
+		return TXRX_CONTINUE;
+	}
+
+	if (ccmp_encrypt_skb(tx, skb, test) < 0)
+		return TXRX_DROP;
+
+	if (tx->u.tx.extra_frag) {
+		int i;
+
+		for (i = 0; i < tx->u.tx.num_extra_frag; i++) {
+			if (ccmp_encrypt_skb(tx, tx->u.tx.extra_frag[i], test)
+			    < 0)
+				return TXRX_DROP;
+		}
+	}
+
+	return TXRX_CONTINUE;
+}
+
+
+ieee80211_txrx_result
+ieee80211_rx_h_ccmp_decrypt(struct ieee80211_txrx_data *rx)
+{
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data;
+	u16 fc;
+	int hdrlen;
+	struct ieee80211_key *key = rx->key;
+	struct sk_buff *skb = rx->skb;
+	u8 pn[CCMP_PN_LEN];
+	int data_len;
+
+	fc = le16_to_cpu(hdr->frame_control);
+	hdrlen = ieee80211_get_hdrlen(fc);
+
+	if (!key || key->alg != ALG_CCMP ||
+	    !(rx->fc & IEEE80211_FCTL_PROTECTED) ||
+	    (rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA)
+		return TXRX_CONTINUE;
+
+	data_len = skb->len - hdrlen - CCMP_HDR_LEN - CCMP_MIC_LEN;
+	if (!rx->sta || data_len < 0)
+		return TXRX_DROP;
+
+	if ((rx->u.rx.status->flag & RX_FLAG_DECRYPTED) &&
+	    !key->force_sw_encrypt &&
+	    !(rx->local->hw.flags & IEEE80211_HW_WEP_INCLUDE_IV))
+		return TXRX_CONTINUE;
+
+	(void) ccmp_hdr2pn(pn, skb->data + hdrlen);
+
+	if (memcmp(pn, key->u.ccmp.rx_pn[rx->u.rx.queue], CCMP_PN_LEN) <= 0) {
+#ifdef CONFIG_MAC80211_DEBUG
+		u8 *ppn = key->u.ccmp.rx_pn[rx->u.rx.queue];
+		printk(KERN_DEBUG "%s: CCMP replay detected for RX frame from "
+		       MAC_FMT " (RX PN %02x%02x%02x%02x%02x%02x <= prev. PN "
+		       "%02x%02x%02x%02x%02x%02x)\n", rx->dev->name,
+		       MAC_ARG(rx->sta->addr),
+		       pn[0], pn[1], pn[2], pn[3], pn[4], pn[5],
+		       ppn[0], ppn[1], ppn[2], ppn[3], ppn[4], ppn[5]);
+#endif /* CONFIG_MAC80211_DEBUG */
+		key->u.ccmp.replays++;
+		return TXRX_DROP;
+	}
+
+	if ((rx->u.rx.status->flag & RX_FLAG_DECRYPTED) &&
+	    !key->force_sw_encrypt) {
+		/* hwaccel has already decrypted frame and verified MIC */
+	} else {
+		u8 *scratch, *b_0, *aad;
+
+		scratch = key->u.ccmp.rx_crypto_buf;
+		b_0 = scratch + 3 * AES_BLOCK_LEN;
+		aad = scratch + 4 * AES_BLOCK_LEN;
+
+		ccmp_special_blocks(skb, pn, b_0, aad, 1);
+
+		if (ieee80211_aes_ccm_decrypt(
+			    key->u.ccmp.tfm, scratch, b_0, aad,
+			    skb->data + hdrlen + CCMP_HDR_LEN, data_len,
+			    skb->data + skb->len - CCMP_MIC_LEN,
+			    skb->data + hdrlen + CCMP_HDR_LEN)) {
+			printk(KERN_DEBUG "%s: CCMP decrypt failed for RX "
+			       "frame from " MAC_FMT "\n", rx->dev->name,
+			       MAC_ARG(rx->sta->addr));
+			return TXRX_DROP;
+		}
+	}
+
+	memcpy(key->u.ccmp.rx_pn[rx->u.rx.queue], pn, CCMP_PN_LEN);
+
+	/* Remove CCMP header and MIC */
+	skb_trim(skb, skb->len - CCMP_MIC_LEN);
+	memmove(skb->data + CCMP_HDR_LEN, skb->data, hdrlen);
+	skb_pull(skb, CCMP_HDR_LEN);
+
+	return TXRX_CONTINUE;
+}
+
diff --git a/net/mac80211/wpa.h b/net/mac80211/wpa.h
new file mode 100644
index 0000000..da3b959
--- /dev/null
+++ b/net/mac80211/wpa.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2002-2004, Instant802 Networks, Inc.
+ *
+ * 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 WPA_H
+#define WPA_H
+
+#include <linux/skbuff.h>
+#include <linux/types.h>
+#include "ieee80211_i.h"
+
+ieee80211_txrx_result
+ieee80211_tx_h_michael_mic_add(struct ieee80211_txrx_data *tx);
+ieee80211_txrx_result
+ieee80211_rx_h_michael_mic_verify(struct ieee80211_txrx_data *rx);
+
+ieee80211_txrx_result
+ieee80211_tx_h_tkip_encrypt(struct ieee80211_txrx_data *tx);
+ieee80211_txrx_result
+ieee80211_rx_h_tkip_decrypt(struct ieee80211_txrx_data *rx);
+
+ieee80211_txrx_result
+ieee80211_tx_h_ccmp_encrypt(struct ieee80211_txrx_data *tx);
+ieee80211_txrx_result
+ieee80211_rx_h_ccmp_decrypt(struct ieee80211_txrx_data *rx);
+
+#endif /* WPA_H */
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 42d2fb9..507828d 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -140,6 +140,14 @@
 
 static void netlink_sock_destruct(struct sock *sk)
 {
+	struct netlink_sock *nlk = nlk_sk(sk);
+
+	if (nlk->cb) {
+		if (nlk->cb->done)
+			nlk->cb->done(nlk->cb);
+		netlink_destroy_callback(nlk->cb);
+	}
+
 	skb_queue_purge(&sk->sk_receive_queue);
 
 	if (!sock_flag(sk, SOCK_DEAD)) {
@@ -148,7 +156,6 @@
 	}
 	BUG_TRAP(!atomic_read(&sk->sk_rmem_alloc));
 	BUG_TRAP(!atomic_read(&sk->sk_wmem_alloc));
-	BUG_TRAP(!nlk_sk(sk)->cb);
 	BUG_TRAP(!nlk_sk(sk)->groups);
 }
 
@@ -456,17 +463,10 @@
 	sock_orphan(sk);
 	nlk = nlk_sk(sk);
 
-	mutex_lock(nlk->cb_mutex);
-	if (nlk->cb) {
-		if (nlk->cb->done)
-			nlk->cb->done(nlk->cb);
-		netlink_destroy_callback(nlk->cb);
-		nlk->cb = NULL;
-	}
-	mutex_unlock(nlk->cb_mutex);
-
-	/* OK. Socket is unlinked, and, therefore,
-	   no new packets will arrive */
+	/*
+	 * OK. Socket is unlinked, any packets that arrive now
+	 * will be purged.
+	 */
 
 	sock->sk = NULL;
 	wake_up_interruptible_all(&nlk->wait);
@@ -1245,16 +1245,14 @@
 		siocb->scm = &scm;
 	}
 	siocb->scm->creds = *NETLINK_CREDS(skb);
+	if (flags & MSG_TRUNC)
+		copied = skb->len;
 	skb_free_datagram(sk, skb);
 
 	if (nlk->cb && atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf / 2)
 		netlink_dump(sk);
 
 	scm_recv(sock, msg, siocb->scm, flags);
-
-	if (flags & MSG_TRUNC)
-		copied = skb->len;
-
 out:
 	netlink_rcv_wake(sk);
 	return err ? : copied;
@@ -1426,9 +1424,9 @@
 		return -ECONNREFUSED;
 	}
 	nlk = nlk_sk(sk);
-	/* A dump or destruction is in progress... */
+	/* A dump is in progress... */
 	mutex_lock(nlk->cb_mutex);
-	if (nlk->cb || sock_flag(sk, SOCK_DEAD)) {
+	if (nlk->cb) {
 		mutex_unlock(nlk->cb_mutex);
 		netlink_destroy_callback(cb);
 		sock_put(sk);
diff --git a/net/netrom/nr_route.c b/net/netrom/nr_route.c
index 8e6bd4e..2f76e062 100644
--- a/net/netrom/nr_route.c
+++ b/net/netrom/nr_route.c
@@ -598,7 +598,7 @@
 	struct net_device *dev, *first = NULL;
 
 	read_lock(&dev_base_lock);
-	for (dev = dev_base; dev != NULL; dev = dev->next) {
+	for_each_netdev(dev) {
 		if ((dev->flags & IFF_UP) && dev->type == ARPHRD_NETROM)
 			if (first == NULL || strncmp(dev->name, first->name, 3) < 0)
 				first = dev;
@@ -618,12 +618,13 @@
 	struct net_device *dev;
 
 	read_lock(&dev_base_lock);
-	for (dev = dev_base; dev != NULL; dev = dev->next) {
+	for_each_netdev(dev) {
 		if ((dev->flags & IFF_UP) && dev->type == ARPHRD_NETROM && ax25cmp(addr, (ax25_address *)dev->dev_addr) == 0) {
 			dev_hold(dev);
 			goto out;
 		}
 	}
+	dev = NULL;
 out:
 	read_unlock(&dev_base_lock);
 	return dev;
diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c
index 1f9aefd..929a784 100644
--- a/net/rose/rose_route.c
+++ b/net/rose/rose_route.c
@@ -596,7 +596,7 @@
 	struct net_device *dev, *first = NULL;
 
 	read_lock(&dev_base_lock);
-	for (dev = dev_base; dev != NULL; dev = dev->next) {
+	for_each_netdev(dev) {
 		if ((dev->flags & IFF_UP) && dev->type == ARPHRD_ROSE)
 			if (first == NULL || strncmp(dev->name, first->name, 3) < 0)
 				first = dev;
@@ -614,12 +614,13 @@
 	struct net_device *dev;
 
 	read_lock(&dev_base_lock);
-	for (dev = dev_base; dev != NULL; dev = dev->next) {
+	for_each_netdev(dev) {
 		if ((dev->flags & IFF_UP) && dev->type == ARPHRD_ROSE && rosecmp(addr, (rose_address *)dev->dev_addr) == 0) {
 			dev_hold(dev);
 			goto out;
 		}
 	}
+	dev = NULL;
 out:
 	read_unlock(&dev_base_lock);
 	return dev;
@@ -630,10 +631,11 @@
 	struct net_device *dev;
 
 	read_lock(&dev_base_lock);
-	for (dev = dev_base; dev != NULL; dev = dev->next) {
+	for_each_netdev(dev) {
 		if ((dev->flags & IFF_UP) && dev->type == ARPHRD_ROSE && rosecmp(addr, (rose_address *)dev->dev_addr) == 0)
 			goto out;
 	}
+	dev = NULL;
 out:
 	read_unlock(&dev_base_lock);
 	return dev != NULL;
diff --git a/net/rxrpc/Kconfig b/net/rxrpc/Kconfig
index 8750f6d..91b3d52 100644
--- a/net/rxrpc/Kconfig
+++ b/net/rxrpc/Kconfig
@@ -5,6 +5,7 @@
 config AF_RXRPC
 	tristate "RxRPC session sockets"
 	depends on EXPERIMENTAL
+	select KEYS
 	help
 	  Say Y or M here to include support for RxRPC session sockets (just
 	  the transport part, not the presentation part: (un)marshalling is
@@ -29,7 +30,7 @@
 
 config RXKAD
 	tristate "RxRPC Kerberos security"
-	depends on AF_RXRPC && KEYS
+	depends on AF_RXRPC
 	select CRYPTO
 	select CRYPTO_MANAGER
 	select CRYPTO_BLKCIPHER
diff --git a/net/rxrpc/ar-ack.c b/net/rxrpc/ar-ack.c
index fc07a92..657ee69 100644
--- a/net/rxrpc/ar-ack.c
+++ b/net/rxrpc/ar-ack.c
@@ -543,6 +543,38 @@
 }
 
 /*
+ * process the extra information that may be appended to an ACK packet
+ */
+static void rxrpc_extract_ackinfo(struct rxrpc_call *call, struct sk_buff *skb,
+				  unsigned latest, int nAcks)
+{
+	struct rxrpc_ackinfo ackinfo;
+	struct rxrpc_peer *peer;
+	unsigned mtu;
+
+	if (skb_copy_bits(skb, nAcks + 3, &ackinfo, sizeof(ackinfo)) < 0) {
+		_leave(" [no ackinfo]");
+		return;
+	}
+
+	_proto("Rx ACK %%%u Info { rx=%u max=%u rwin=%u jm=%u }",
+	       latest,
+	       ntohl(ackinfo.rxMTU), ntohl(ackinfo.maxMTU),
+	       ntohl(ackinfo.rwind), ntohl(ackinfo.jumbo_max));
+
+	mtu = min(ntohl(ackinfo.rxMTU), ntohl(ackinfo.maxMTU));
+
+	peer = call->conn->trans->peer;
+	if (mtu < peer->maxdata) {
+		spin_lock_bh(&peer->lock);
+		peer->maxdata = mtu;
+		peer->mtu = mtu + peer->hdrsize;
+		spin_unlock_bh(&peer->lock);
+		_net("Net MTU %u (maxdata %u)", peer->mtu, peer->maxdata);
+	}
+}
+
+/*
  * process packets in the reception queue
  */
 static int rxrpc_process_rx_queue(struct rxrpc_call *call,
@@ -606,6 +638,8 @@
 		       rxrpc_acks[ack.reason],
 		       ack.nAcks);
 
+		rxrpc_extract_ackinfo(call, skb, latest, ack.nAcks);
+
 		if (ack.reason == RXRPC_ACK_PING) {
 			_proto("Rx ACK %%%u PING Request", latest);
 			rxrpc_propose_ACK(call, RXRPC_ACK_PING_RESPONSE,
@@ -801,9 +835,9 @@
 	struct msghdr msg;
 	struct kvec iov[5];
 	unsigned long bits;
-	__be32 data;
+	__be32 data, pad;
 	size_t len;
-	int genbit, loop, nbit, ioc, ret;
+	int genbit, loop, nbit, ioc, ret, mtu;
 	u32 abort_code = RX_PROTOCOL_ERROR;
 	u8 *acks = NULL;
 
@@ -899,9 +933,30 @@
 	}
 
 	if (test_bit(RXRPC_CALL_ACK_FINAL, &call->events)) {
-		hdr.type = RXRPC_PACKET_TYPE_ACKALL;
 		genbit = RXRPC_CALL_ACK_FINAL;
-		goto send_message;
+
+		ack.bufferSpace	= htons(8);
+		ack.maxSkew	= 0;
+		ack.serial	= 0;
+		ack.reason	= RXRPC_ACK_IDLE;
+		ack.nAcks	= 0;
+		call->ackr_reason = 0;
+
+		spin_lock_bh(&call->lock);
+		ack.serial = call->ackr_serial;
+		ack.previousPacket = call->ackr_prev_seq;
+		ack.firstPacket = htonl(call->rx_data_eaten + 1);
+		spin_unlock_bh(&call->lock);
+
+		pad = 0;
+
+		iov[1].iov_base = &ack;
+		iov[1].iov_len	= sizeof(ack);
+		iov[2].iov_base = &pad;
+		iov[2].iov_len	= 3;
+		iov[3].iov_base = &ackinfo;
+		iov[3].iov_len	= sizeof(ackinfo);
+		goto send_ACK;
 	}
 
 	if (call->events & ((1 << RXRPC_CALL_RCVD_BUSY) |
@@ -971,8 +1026,6 @@
 
 	/* consider sending an ordinary ACK */
 	if (test_bit(RXRPC_CALL_ACK, &call->events)) {
-		__be32 pad;
-
 		_debug("send ACK: window: %d - %d { %lx }",
 		       call->rx_data_eaten, call->ackr_win_top,
 		       call->ackr_window[0]);
@@ -997,12 +1050,6 @@
 		ack.serial	= 0;
 		ack.reason	= 0;
 
-		ackinfo.rxMTU	= htonl(5692);
-//		ackinfo.rxMTU	= htonl(call->conn->trans->peer->maxdata);
-		ackinfo.maxMTU	= htonl(call->conn->trans->peer->maxdata);
-		ackinfo.rwind	= htonl(32);
-		ackinfo.jumbo_max = htonl(4);
-
 		spin_lock_bh(&call->lock);
 		ack.reason = call->ackr_reason;
 		ack.serial = call->ackr_serial;
@@ -1116,6 +1163,15 @@
 	ack.maxSkew = htons(atomic_read(&call->conn->hi_serial) -
 			    ntohl(ack.serial));
 send_ACK:
+	mtu = call->conn->trans->peer->if_mtu;
+	mtu -= call->conn->trans->peer->hdrsize;
+	ackinfo.maxMTU	= htonl(mtu);
+	ackinfo.rwind	= htonl(32);
+
+	/* permit the peer to send us jumbo packets if it wants to */
+	ackinfo.rxMTU	= htonl(5692);
+	ackinfo.jumbo_max = htonl(4);
+
 	hdr.serial = htonl(atomic_inc_return(&call->conn->serial));
 	_proto("Tx ACK %%%u { m=%hu f=#%u p=#%u s=%%%u r=%s n=%u }",
 	       ntohl(hdr.serial),
diff --git a/net/rxrpc/ar-error.c b/net/rxrpc/ar-error.c
index 2c27df1..6cb3e88 100644
--- a/net/rxrpc/ar-error.c
+++ b/net/rxrpc/ar-error.c
@@ -100,8 +100,10 @@
 		}
 
 		if (mtu < peer->mtu) {
+			spin_lock_bh(&peer->lock);
 			peer->mtu = mtu;
 			peer->maxdata = peer->mtu - peer->hdrsize;
+			spin_unlock_bh(&peer->lock);
 			_net("Net MTU %u (maxdata %u)",
 			     peer->mtu, peer->maxdata);
 		}
diff --git a/net/rxrpc/ar-output.c b/net/rxrpc/ar-output.c
index 5cdde4a..591c442 100644
--- a/net/rxrpc/ar-output.c
+++ b/net/rxrpc/ar-output.c
@@ -582,7 +582,7 @@
 			max &= ~(call->conn->size_align - 1UL);
 
 			chunk = max;
-			if (chunk > len)
+			if (chunk > len && !more)
 				chunk = len;
 
 			space = chunk + call->conn->size_align;
diff --git a/net/rxrpc/ar-peer.c b/net/rxrpc/ar-peer.c
index d399de4..ce08b78 100644
--- a/net/rxrpc/ar-peer.c
+++ b/net/rxrpc/ar-peer.c
@@ -19,6 +19,7 @@
 #include <net/sock.h>
 #include <net/af_rxrpc.h>
 #include <net/ip.h>
+#include <net/route.h>
 #include "ar-internal.h"
 
 static LIST_HEAD(rxrpc_peers);
@@ -28,6 +29,47 @@
 static void rxrpc_destroy_peer(struct work_struct *work);
 
 /*
+ * assess the MTU size for the network interface through which this peer is
+ * reached
+ */
+static void rxrpc_assess_MTU_size(struct rxrpc_peer *peer)
+{
+	struct rtable *rt;
+	struct flowi fl;
+	int ret;
+
+	peer->if_mtu = 1500;
+
+	memset(&fl, 0, sizeof(fl));
+
+	switch (peer->srx.transport.family) {
+	case AF_INET:
+		fl.oif = 0;
+		fl.proto = IPPROTO_UDP,
+		fl.nl_u.ip4_u.saddr = 0;
+		fl.nl_u.ip4_u.daddr = peer->srx.transport.sin.sin_addr.s_addr;
+		fl.nl_u.ip4_u.tos = 0;
+		/* assume AFS.CM talking to AFS.FS */
+		fl.uli_u.ports.sport = htons(7001);
+		fl.uli_u.ports.dport = htons(7000);
+		break;
+	default:
+		BUG();
+	}
+
+	ret = ip_route_output_key(&rt, &fl);
+	if (ret < 0) {
+		kleave(" [route err %d]", ret);
+		return;
+	}
+
+	peer->if_mtu = dst_mtu(&rt->u.dst);
+	dst_release(&rt->u.dst);
+
+	kleave(" [if_mtu %u]", peer->if_mtu);
+}
+
+/*
  * allocate a new peer
  */
 static struct rxrpc_peer *rxrpc_alloc_peer(struct sockaddr_rxrpc *srx,
@@ -47,7 +89,8 @@
 		peer->debug_id = atomic_inc_return(&rxrpc_debug_id);
 		memcpy(&peer->srx, srx, sizeof(*srx));
 
-		peer->mtu = peer->if_mtu = 65535;
+		rxrpc_assess_MTU_size(peer);
+		peer->mtu = peer->if_mtu;
 
 		if (srx->transport.family == AF_INET) {
 			peer->hdrsize = sizeof(struct iphdr);
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
index 8699e70..bec600a 100644
--- a/net/sched/sch_api.c
+++ b/net/sched/sch_api.c
@@ -894,9 +894,10 @@
 	s_idx = cb->args[0];
 	s_q_idx = q_idx = cb->args[1];
 	read_lock(&dev_base_lock);
-	for (dev=dev_base, idx=0; dev; dev = dev->next, idx++) {
+	idx = 0;
+	for_each_netdev(dev) {
 		if (idx < s_idx)
-			continue;
+			goto cont;
 		if (idx > s_idx)
 			s_q_idx = 0;
 		q_idx = 0;
@@ -910,6 +911,8 @@
 				goto done;
 			q_idx++;
 		}
+cont:
+		idx++;
 	}
 
 done:
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index db73ef9..df94e3c 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c
@@ -1103,6 +1103,13 @@
 			asoc->ssnmap = new->ssnmap;
 			new->ssnmap = NULL;
 		}
+
+		if (!asoc->assoc_id) {
+			/* get a new association id since we don't have one
+			 * yet.
+			 */
+			sctp_assoc_set_id(asoc, GFP_ATOMIC);
+		}
 	}
 }
 
@@ -1375,3 +1382,25 @@
 	sctp_read_unlock(&asoc->base.addr_lock);
 	return found;
 }
+
+/* Set an association id for a given association */
+int sctp_assoc_set_id(struct sctp_association *asoc, gfp_t gfp)
+{
+	int assoc_id;
+	int error = 0;
+retry:
+	if (unlikely(!idr_pre_get(&sctp_assocs_id, gfp)))
+		return -ENOMEM;
+
+	spin_lock_bh(&sctp_assocs_id_lock);
+	error = idr_get_new_above(&sctp_assocs_id, (void *)asoc,
+				    1, &assoc_id);
+	spin_unlock_bh(&sctp_assocs_id_lock);
+	if (error == -EAGAIN)
+		goto retry;
+	else if (error)
+		return error;
+
+	asoc->assoc_id = (sctp_assoc_t) assoc_id;
+	return error;
+}
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
index ca527a2..84cd536 100644
--- a/net/sctp/ipv6.c
+++ b/net/sctp/ipv6.c
@@ -992,21 +992,10 @@
 	.af            = &sctp_ipv6_specific,
 };
 
-/* Initialize IPv6 support and register with inet6 stack.  */
+/* Initialize IPv6 support and register with socket layer.  */
 int sctp_v6_init(void)
 {
-	int rc = proto_register(&sctpv6_prot, 1);
-
-	if (rc)
-		goto out;
-	/* Register inet6 protocol. */
-	rc = -EAGAIN;
-	if (inet6_add_protocol(&sctpv6_protocol, IPPROTO_SCTP) < 0)
-		goto out_unregister_sctp_proto;
-
-	/* Add SCTPv6(UDP and TCP style) to inetsw6 linked list. */
-	inet6_register_protosw(&sctpv6_seqpacket_protosw);
-	inet6_register_protosw(&sctpv6_stream_protosw);
+	int rc;
 
 	/* Register the SCTP specific PF_INET6 functions. */
 	sctp_register_pf(&sctp_pf_inet6_specific, PF_INET6);
@@ -1014,23 +1003,41 @@
 	/* Register the SCTP specific AF_INET6 functions. */
 	sctp_register_af(&sctp_ipv6_specific);
 
+	rc = proto_register(&sctpv6_prot, 1);
+	if (rc)
+		return rc;
+
+	/* Add SCTPv6(UDP and TCP style) to inetsw6 linked list. */
+	inet6_register_protosw(&sctpv6_seqpacket_protosw);
+	inet6_register_protosw(&sctpv6_stream_protosw);
+
+	return 0;
+}
+
+/* Register with inet6 layer. */
+int sctp_v6_add_protocol(void)
+{
 	/* Register notifier for inet6 address additions/deletions. */
 	register_inet6addr_notifier(&sctp_inet6addr_notifier);
-	rc = 0;
-out:
-	return rc;
-out_unregister_sctp_proto:
-	proto_unregister(&sctpv6_prot);
-	goto out;
+
+	if (inet6_add_protocol(&sctpv6_protocol, IPPROTO_SCTP) < 0)
+		return -EAGAIN;
+
+	return 0;
 }
 
 /* IPv6 specific exit support. */
 void sctp_v6_exit(void)
 {
-	list_del(&sctp_ipv6_specific.list);
-	inet6_del_protocol(&sctpv6_protocol, IPPROTO_SCTP);
 	inet6_unregister_protosw(&sctpv6_seqpacket_protosw);
 	inet6_unregister_protosw(&sctpv6_stream_protosw);
-	unregister_inet6addr_notifier(&sctp_inet6addr_notifier);
 	proto_unregister(&sctpv6_prot);
+	list_del(&sctp_ipv6_specific.list);
+}
+
+/* Unregister with inet6 layer. */
+void sctp_v6_del_protocol(void)
+{
+	inet6_del_protocol(&sctpv6_protocol, IPPROTO_SCTP);
+	unregister_inet6addr_notifier(&sctp_inet6addr_notifier);
 }
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index c361deb..34bab36 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -170,7 +170,7 @@
 	struct sctp_af *af;
 
 	read_lock(&dev_base_lock);
-	for (dev = dev_base; dev; dev = dev->next) {
+	for_each_netdev(dev) {
 		__list_for_each(pos, &sctp_address_families) {
 			af = list_entry(pos, struct sctp_af, list);
 			af->copy_addrlist(&sctp_local_addr_list, dev);
@@ -975,28 +975,14 @@
 	if (!sctp_sanity_check())
 		goto out;
 
-	status = proto_register(&sctp_prot, 1);
-	if (status)
-		goto out;
-
-	/* Add SCTP to inet_protos hash table.  */
-	status = -EAGAIN;
-	if (inet_add_protocol(&sctp_protocol, IPPROTO_SCTP) < 0)
-		goto err_add_protocol;
-
-	/* Add SCTP(TCP and UDP style) to inetsw linked list.  */
-	inet_register_protosw(&sctp_seqpacket_protosw);
-	inet_register_protosw(&sctp_stream_protosw);
-
-	/* Allocate a cache pools. */
+	/* Allocate bind_bucket and chunk caches. */
 	status = -ENOBUFS;
 	sctp_bucket_cachep = kmem_cache_create("sctp_bind_bucket",
 					       sizeof(struct sctp_bind_bucket),
 					       0, SLAB_HWCACHE_ALIGN,
 					       NULL, NULL);
-
 	if (!sctp_bucket_cachep)
-		goto err_bucket_cachep;
+		goto out;
 
 	sctp_chunk_cachep = kmem_cache_create("sctp_chunk",
 					       sizeof(struct sctp_chunk),
@@ -1153,6 +1139,14 @@
 	INIT_LIST_HEAD(&sctp_address_families);
 	sctp_register_af(&sctp_ipv4_specific);
 
+	status = proto_register(&sctp_prot, 1);
+	if (status)
+		goto err_proto_register;
+
+	/* Register SCTP(UDP and TCP style) with socket layer.  */
+	inet_register_protosw(&sctp_seqpacket_protosw);
+	inet_register_protosw(&sctp_stream_protosw);
+
 	status = sctp_v6_init();
 	if (status)
 		goto err_v6_init;
@@ -1166,19 +1160,39 @@
 
 	/* Initialize the local address list. */
 	INIT_LIST_HEAD(&sctp_local_addr_list);
-
 	sctp_get_local_addr_list();
 
 	/* Register notifier for inet address additions/deletions. */
 	register_inetaddr_notifier(&sctp_inetaddr_notifier);
 
+	/* Register SCTP with inet layer.  */
+	if (inet_add_protocol(&sctp_protocol, IPPROTO_SCTP) < 0) {
+		status = -EAGAIN;
+		goto err_add_protocol;
+	}
+
+	/* Register SCTP with inet6 layer.  */
+	status = sctp_v6_add_protocol();
+	if (status)
+		goto err_v6_add_protocol;
+
 	__unsafe(THIS_MODULE);
 	status = 0;
 out:
 	return status;
+err_v6_add_protocol:
+	inet_del_protocol(&sctp_protocol, IPPROTO_SCTP);
+	unregister_inetaddr_notifier(&sctp_inetaddr_notifier);
+err_add_protocol:
+	sctp_free_local_addr_list();
+	sock_release(sctp_ctl_socket);
 err_ctl_sock_init:
 	sctp_v6_exit();
 err_v6_init:
+	inet_unregister_protosw(&sctp_stream_protosw);
+	inet_unregister_protosw(&sctp_seqpacket_protosw);
+	proto_unregister(&sctp_prot);
+err_proto_register:
 	sctp_sysctl_unregister();
 	list_del(&sctp_ipv4_specific.list);
 	free_pages((unsigned long)sctp_port_hashtable,
@@ -1192,19 +1206,13 @@
 			     sizeof(struct sctp_hashbucket)));
 err_ahash_alloc:
 	sctp_dbg_objcnt_exit();
-err_init_proc:
 	sctp_proc_exit();
+err_init_proc:
 	cleanup_sctp_mibs();
 err_init_mibs:
 	kmem_cache_destroy(sctp_chunk_cachep);
 err_chunk_cachep:
 	kmem_cache_destroy(sctp_bucket_cachep);
-err_bucket_cachep:
-	inet_del_protocol(&sctp_protocol, IPPROTO_SCTP);
-	inet_unregister_protosw(&sctp_seqpacket_protosw);
-	inet_unregister_protosw(&sctp_stream_protosw);
-err_add_protocol:
-	proto_unregister(&sctp_prot);
 	goto out;
 }
 
@@ -1215,8 +1223,9 @@
 	 * up all the remaining associations and all that memory.
 	 */
 
-	/* Unregister notifier for inet address additions/deletions. */
-	unregister_inetaddr_notifier(&sctp_inetaddr_notifier);
+	/* Unregister with inet6/inet layers. */
+	sctp_v6_del_protocol();
+	inet_del_protocol(&sctp_protocol, IPPROTO_SCTP);
 
 	/* Free the local address list.  */
 	sctp_free_local_addr_list();
@@ -1224,7 +1233,16 @@
 	/* Free the control endpoint.  */
 	sock_release(sctp_ctl_socket);
 
+	/* Cleanup v6 initializations. */
 	sctp_v6_exit();
+
+	/* Unregister with socket layer. */
+	inet_unregister_protosw(&sctp_stream_protosw);
+	inet_unregister_protosw(&sctp_seqpacket_protosw);
+
+	/* Unregister notifier for inet address additions/deletions. */
+	unregister_inetaddr_notifier(&sctp_inetaddr_notifier);
+
 	sctp_sysctl_unregister();
 	list_del(&sctp_ipv4_specific.list);
 
@@ -1236,16 +1254,13 @@
 		   get_order(sctp_port_hashsize *
 			     sizeof(struct sctp_bind_hashbucket)));
 
-	kmem_cache_destroy(sctp_chunk_cachep);
-	kmem_cache_destroy(sctp_bucket_cachep);
-
 	sctp_dbg_objcnt_exit();
 	sctp_proc_exit();
 	cleanup_sctp_mibs();
 
-	inet_del_protocol(&sctp_protocol, IPPROTO_SCTP);
-	inet_unregister_protosw(&sctp_seqpacket_protosw);
-	inet_unregister_protosw(&sctp_stream_protosw);
+	kmem_cache_destroy(sctp_chunk_cachep);
+	kmem_cache_destroy(sctp_bucket_cachep);
+
 	proto_unregister(&sctp_prot);
 }
 
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index be783a3..8d18f57 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -1939,7 +1939,6 @@
 	 * association.
 	 */
 	if (!asoc->temp) {
-		int assoc_id;
 		int error;
 
 		asoc->ssnmap = sctp_ssnmap_new(asoc->c.sinit_max_instreams,
@@ -1947,19 +1946,9 @@
 		if (!asoc->ssnmap)
 			goto clean_up;
 
-	retry:
-		if (unlikely(!idr_pre_get(&sctp_assocs_id, gfp)))
+		error = sctp_assoc_set_id(asoc, gfp);
+		if (error)
 			goto clean_up;
-		spin_lock_bh(&sctp_assocs_id_lock);
-		error = idr_get_new_above(&sctp_assocs_id, (void *)asoc, 1,
-					  &assoc_id);
-		spin_unlock_bh(&sctp_assocs_id_lock);
-		if (error == -EAGAIN)
-			goto retry;
-		else if (error)
-			goto clean_up;
-
-		asoc->assoc_id = (sctp_assoc_t) assoc_id;
 	}
 
 	/* ADDIP Section 4.1 ASCONF Chunk Procedures
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c
index b37a7ad..d9fad4f 100644
--- a/net/sctp/sm_sideeffect.c
+++ b/net/sctp/sm_sideeffect.c
@@ -862,6 +862,33 @@
 		sk->sk_err = error;
 }
 
+/* Helper function to generate an association change event */
+static void sctp_cmd_assoc_change(sctp_cmd_seq_t *commands,
+				 struct sctp_association *asoc,
+				 u8 state)
+{
+	struct sctp_ulpevent *ev;
+
+	ev = sctp_ulpevent_make_assoc_change(asoc, 0, state, 0,
+					    asoc->c.sinit_num_ostreams,
+					    asoc->c.sinit_max_instreams,
+					    NULL, GFP_ATOMIC);
+	if (ev)
+		sctp_ulpq_tail_event(&asoc->ulpq, ev);
+}
+
+/* Helper function to generate an adaptation indication event */
+static void sctp_cmd_adaptation_ind(sctp_cmd_seq_t *commands,
+				    struct sctp_association *asoc)
+{
+	struct sctp_ulpevent *ev;
+
+	ev = sctp_ulpevent_make_adaptation_indication(asoc, GFP_ATOMIC);
+
+	if (ev)
+		sctp_ulpq_tail_event(&asoc->ulpq, ev);
+}
+
 /* These three macros allow us to pull the debugging code out of the
  * main flow of sctp_do_sm() to keep attention focused on the real
  * functionality there.
@@ -1485,6 +1512,14 @@
 		case SCTP_CMD_SET_SK_ERR:
 			sctp_cmd_set_sk_err(asoc, cmd->obj.error);
 			break;
+		case SCTP_CMD_ASSOC_CHANGE:
+			sctp_cmd_assoc_change(commands, asoc,
+					      cmd->obj.u8);
+			break;
+		case SCTP_CMD_ADAPTATION_IND:
+			sctp_cmd_adaptation_ind(commands, asoc);
+			break;
+
 		default:
 			printk(KERN_WARNING "Impossible command: %u, %p\n",
 			       cmd->verb, cmd->obj.ptr);
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index 9e28a5d..f02ce3d 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -1656,7 +1656,6 @@
 					struct sctp_association *new_asoc)
 {
 	sctp_init_chunk_t *peer_init;
-	struct sctp_ulpevent *ev;
 	struct sctp_chunk *repl;
 
 	/* new_asoc is a brand-new association, so these are not yet
@@ -1687,34 +1686,28 @@
 	 * D) IMPLEMENTATION NOTE: An implementation may choose to
 	 * send the Communication Up notification to the SCTP user
 	 * upon reception of a valid COOKIE ECHO chunk.
+	 *
+	 * Sadly, this needs to be implemented as a side-effect, because
+	 * we are not guaranteed to have set the association id of the real
+	 * association and so these notifications need to be delayed until
+	 * the association id is allocated.
 	 */
-	ev = sctp_ulpevent_make_assoc_change(asoc, 0, SCTP_COMM_UP, 0,
-					     new_asoc->c.sinit_num_ostreams,
-					     new_asoc->c.sinit_max_instreams,
-					     NULL, GFP_ATOMIC);
-	if (!ev)
-		goto nomem_ev;
 
-	sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, SCTP_ULPEVENT(ev));
+	sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_CHANGE, SCTP_U8(SCTP_COMM_UP));
 
 	/* Sockets API Draft Section 5.3.1.6
 	 * When a peer sends a Adaptation Layer Indication parameter , SCTP
 	 * delivers this notification to inform the application that of the
 	 * peers requested adaptation layer.
+	 *
+	 * This also needs to be done as a side effect for the same reason as
+	 * above.
 	 */
-	if (asoc->peer.adaptation_ind) {
-		ev = sctp_ulpevent_make_adaptation_indication(asoc, GFP_ATOMIC);
-		if (!ev)
-			goto nomem_ev;
-
-		sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP,
-				SCTP_ULPEVENT(ev));
-	}
+	if (asoc->peer.adaptation_ind)
+		sctp_add_cmd_sf(commands, SCTP_CMD_ADAPTATION_IND, SCTP_NULL());
 
 	return SCTP_DISPOSITION_CONSUME;
 
-nomem_ev:
-	sctp_chunk_free(repl);
 nomem:
 	return SCTP_DISPOSITION_NOMEM;
 }
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 2fc0a92..9f1a908 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -972,6 +972,7 @@
 	int walk_size = 0;
 	union sctp_addr *sa_addr;
 	void *addr_buf;
+	unsigned short port;
 
 	sp = sctp_sk(sk);
 	ep = sp->ep;
@@ -992,6 +993,7 @@
 	while (walk_size < addrs_size) {
 		sa_addr = (union sctp_addr *)addr_buf;
 		af = sctp_get_af_specific(sa_addr->sa.sa_family);
+		port = ntohs(sa_addr->v4.sin_port);
 
 		/* If the address family is not supported or if this address
 		 * causes the address buffer to overflow return EINVAL.
@@ -1005,6 +1007,12 @@
 		if (err)
 			goto out_free;
 
+		/* Make sure the destination port is correctly set
+		 * in all addresses.
+		 */
+		if (asoc && asoc->peer.port && asoc->peer.port != port)
+			goto out_free;
+
 		memcpy(&to, sa_addr, af->sockaddr_len);
 
 		/* Check if there already is a matching association on the
@@ -5012,7 +5020,8 @@
 		struct hlist_node *node;
 
 		SCTP_DEBUG_PRINTK("sctp_get_port() found a possible match\n");
-		if (pp->fastreuse && sk->sk_reuse)
+		if (pp->fastreuse && sk->sk_reuse &&
+			sk->sk_state != SCTP_SS_LISTENING)
 			goto success;
 
 		/* Run through the list of sockets bound to the port
@@ -5029,7 +5038,8 @@
 			struct sctp_endpoint *ep2;
 			ep2 = sctp_sk(sk2)->ep;
 
-			if (reuse && sk2->sk_reuse)
+			if (reuse && sk2->sk_reuse &&
+			    sk2->sk_state != SCTP_SS_LISTENING)
 				continue;
 
 			if (sctp_bind_addr_match(&ep2->base.bind_addr, addr,
@@ -5050,9 +5060,13 @@
 	 * if sk->sk_reuse is too (that is, if the caller requested
 	 * SO_REUSEADDR on this socket -sk-).
 	 */
-	if (hlist_empty(&pp->owner))
-		pp->fastreuse = sk->sk_reuse ? 1 : 0;
-	else if (pp->fastreuse && !sk->sk_reuse)
+	if (hlist_empty(&pp->owner)) {
+		if (sk->sk_reuse && sk->sk_state != SCTP_SS_LISTENING)
+			pp->fastreuse = 1;
+		else
+			pp->fastreuse = 0;
+	} else if (pp->fastreuse &&
+		(!sk->sk_reuse || sk->sk_state == SCTP_SS_LISTENING))
 		pp->fastreuse = 0;
 
 	/* We are set, so fill up all the data in the hash table
@@ -5060,8 +5074,8 @@
 	 * sockets FIXME: Blurry, NPI (ipg).
 	 */
 success:
-	inet_sk(sk)->num = snum;
 	if (!sctp_sk(sk)->bind_hash) {
+		inet_sk(sk)->num = snum;
 		sk_add_bind_node(sk, &pp->owner);
 		sctp_sk(sk)->bind_hash = pp;
 	}
@@ -5134,12 +5148,16 @@
 	 * This is not currently spelled out in the SCTP sockets
 	 * extensions draft, but follows the practice as seen in TCP
 	 * sockets.
+	 *
+	 * Additionally, turn off fastreuse flag since we are not listening
 	 */
+	sk->sk_state = SCTP_SS_LISTENING;
 	if (!ep->base.bind_addr.port) {
 		if (sctp_autobind(sk))
 			return -EAGAIN;
-	}
-	sk->sk_state = SCTP_SS_LISTENING;
+	} else
+		sctp_sk(sk)->bind_hash->fastreuse = 0;
+
 	sctp_hash_endpoint(ep);
 	return 0;
 }
@@ -5177,11 +5195,13 @@
 	 * extensions draft, but follows the practice as seen in TCP
 	 * sockets.
 	 */
+	sk->sk_state = SCTP_SS_LISTENING;
 	if (!ep->base.bind_addr.port) {
 		if (sctp_autobind(sk))
 			return -EAGAIN;
-	}
-	sk->sk_state = SCTP_SS_LISTENING;
+	} else
+		sctp_sk(sk)->bind_hash->fastreuse = 0;
+
 	sk->sk_max_ack_backlog = backlog;
 	sctp_hash_endpoint(ep);
 	return 0;
diff --git a/net/sunrpc/Makefile b/net/sunrpc/Makefile
index cdcab9c..8ebfc4d 100644
--- a/net/sunrpc/Makefile
+++ b/net/sunrpc/Makefile
@@ -9,7 +9,7 @@
 sunrpc-y := clnt.o xprt.o socklib.o xprtsock.o sched.o \
 	    auth.o auth_null.o auth_unix.o \
 	    svc.o svcsock.o svcauth.o svcauth_unix.o \
-	    pmap_clnt.o timer.o xdr.o \
+	    rpcb_clnt.o timer.o xdr.o \
 	    sunrpc_syms.o cache.o rpc_pipe.o
 sunrpc-$(CONFIG_PROC_FS) += stats.o
 sunrpc-$(CONFIG_SYSCTL) += sysctl.o
diff --git a/net/sunrpc/auth_gss/gss_spkm3_seal.c b/net/sunrpc/auth_gss/gss_spkm3_seal.c
index 104cbf4..d158635 100644
--- a/net/sunrpc/auth_gss/gss_spkm3_seal.c
+++ b/net/sunrpc/auth_gss/gss_spkm3_seal.c
@@ -123,9 +123,6 @@
 
 	return  GSS_S_COMPLETE;
 out_err:
-	if (md5cksum.data)
-		kfree(md5cksum.data);
-
 	token->data = NULL;
 	token->len = 0;
 	return GSS_S_FAILURE;
@@ -152,7 +149,7 @@
 
 	switch (cksumtype) {
 		case CKSUMTYPE_HMAC_MD5:
-			cksumname = "md5";
+			cksumname = "hmac(md5)";
 			break;
 		default:
 			dprintk("RPC:       spkm3_make_checksum:"
@@ -172,8 +169,12 @@
 	if (err)
 		goto out;
 
+	err = crypto_hash_init(&desc);
+	if (err)
+		goto out;
+
 	sg_set_buf(sg, header, hdrlen);
-	crypto_hash_update(&desc, sg, 1);
+	crypto_hash_update(&desc, sg, sg->length);
 
 	xdr_process_buf(body, body_offset, body->len - body_offset,
 			spkm3_checksummer, &desc);
@@ -184,5 +185,3 @@
 
 	return err ? GSS_S_FAILURE : 0;
 }
-
-EXPORT_SYMBOL(make_spkm3_checksum);
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index 396cdbe..d8fbee4 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -36,8 +36,6 @@
 #include <linux/sunrpc/metrics.h>
 
 
-#define RPC_SLACK_SPACE		(1024)	/* total overkill */
-
 #ifdef RPC_DEBUG
 # define RPCDBG_FACILITY	RPCDBG_CALL
 #endif
@@ -747,21 +745,38 @@
 static void
 call_allocate(struct rpc_task *task)
 {
+	unsigned int slack = task->tk_auth->au_cslack;
 	struct rpc_rqst *req = task->tk_rqstp;
 	struct rpc_xprt *xprt = task->tk_xprt;
-	unsigned int	bufsiz;
+	struct rpc_procinfo *proc = task->tk_msg.rpc_proc;
 
 	dprint_status(task);
 
+	task->tk_status = 0;
 	task->tk_action = call_bind;
+
 	if (req->rq_buffer)
 		return;
 
-	/* FIXME: compute buffer requirements more exactly using
-	 * auth->au_wslack */
-	bufsiz = task->tk_msg.rpc_proc->p_bufsiz + RPC_SLACK_SPACE;
+	if (proc->p_proc != 0) {
+		BUG_ON(proc->p_arglen == 0);
+		if (proc->p_decode != NULL)
+			BUG_ON(proc->p_replen == 0);
+	}
 
-	if (xprt->ops->buf_alloc(task, bufsiz << 1) != NULL)
+	/*
+	 * Calculate the size (in quads) of the RPC call
+	 * and reply headers, and convert both values
+	 * to byte sizes.
+	 */
+	req->rq_callsize = RPC_CALLHDRSIZE + (slack << 1) + proc->p_arglen;
+	req->rq_callsize <<= 2;
+	req->rq_rcvsize = RPC_REPHDRSIZE + slack + proc->p_replen;
+	req->rq_rcvsize <<= 2;
+
+	req->rq_buffer = xprt->ops->buf_alloc(task,
+					req->rq_callsize + req->rq_rcvsize);
+	if (req->rq_buffer != NULL)
 		return;
 
 	dprintk("RPC: %5u rpc_buffer allocation failed\n", task->tk_pid);
@@ -788,6 +803,17 @@
 	task->tk_rqstp->rq_snd_buf.len = 0;
 }
 
+static inline void
+rpc_xdr_buf_init(struct xdr_buf *buf, void *start, size_t len)
+{
+	buf->head[0].iov_base = start;
+	buf->head[0].iov_len = len;
+	buf->tail[0].iov_len = 0;
+	buf->page_len = 0;
+	buf->len = 0;
+	buf->buflen = len;
+}
+
 /*
  * 3.	Encode arguments of an RPC call
  */
@@ -795,28 +821,17 @@
 call_encode(struct rpc_task *task)
 {
 	struct rpc_rqst	*req = task->tk_rqstp;
-	struct xdr_buf *sndbuf = &req->rq_snd_buf;
-	struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
-	unsigned int	bufsiz;
 	kxdrproc_t	encode;
 	__be32		*p;
 
 	dprint_status(task);
 
-	/* Default buffer setup */
-	bufsiz = req->rq_bufsize >> 1;
-	sndbuf->head[0].iov_base = (void *)req->rq_buffer;
-	sndbuf->head[0].iov_len  = bufsiz;
-	sndbuf->tail[0].iov_len  = 0;
-	sndbuf->page_len	 = 0;
-	sndbuf->len		 = 0;
-	sndbuf->buflen		 = bufsiz;
-	rcvbuf->head[0].iov_base = (void *)((char *)req->rq_buffer + bufsiz);
-	rcvbuf->head[0].iov_len  = bufsiz;
-	rcvbuf->tail[0].iov_len  = 0;
-	rcvbuf->page_len	 = 0;
-	rcvbuf->len		 = 0;
-	rcvbuf->buflen		 = bufsiz;
+	rpc_xdr_buf_init(&req->rq_snd_buf,
+			 req->rq_buffer,
+			 req->rq_callsize);
+	rpc_xdr_buf_init(&req->rq_rcv_buf,
+			 (char *)req->rq_buffer + req->rq_callsize,
+			 req->rq_rcvsize);
 
 	/* Encode header and provided arguments */
 	encode = task->tk_msg.rpc_proc->p_encode;
@@ -887,9 +902,11 @@
 				task->tk_pid);
 		break;
 	case -EPROTONOSUPPORT:
-		dprintk("RPC: %5u remote rpcbind version 2 unavailable\n",
+		dprintk("RPC: %5u remote rpcbind version unavailable, retrying\n",
 				task->tk_pid);
-		break;
+		task->tk_status = 0;
+		task->tk_action = call_bind;
+		return;
 	default:
 		dprintk("RPC: %5u unrecognized rpcbind error (%d)\n",
 				task->tk_pid, -task->tk_status);
diff --git a/net/sunrpc/pmap_clnt.c b/net/sunrpc/pmap_clnt.c
deleted file mode 100644
index d9f7653..0000000
--- a/net/sunrpc/pmap_clnt.c
+++ /dev/null
@@ -1,383 +0,0 @@
-/*
- * linux/net/sunrpc/pmap_clnt.c
- *
- * In-kernel RPC portmapper client.
- *
- * Portmapper supports version 2 of the rpcbind protocol (RFC 1833).
- *
- * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de>
- */
-
-#include <linux/types.h>
-#include <linux/socket.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/uio.h>
-#include <linux/in.h>
-#include <linux/sunrpc/clnt.h>
-#include <linux/sunrpc/sched.h>
-
-#ifdef RPC_DEBUG
-# define RPCDBG_FACILITY	RPCDBG_PMAP
-#endif
-
-#define PMAP_SET		1
-#define PMAP_UNSET		2
-#define PMAP_GETPORT		3
-
-struct portmap_args {
-	u32			pm_prog;
-	u32			pm_vers;
-	u32			pm_prot;
-	unsigned short		pm_port;
-	struct rpc_xprt *	pm_xprt;
-};
-
-static struct rpc_procinfo	pmap_procedures[];
-static struct rpc_clnt *	pmap_create(char *, struct sockaddr_in *, int, int);
-static void			pmap_getport_done(struct rpc_task *, void *);
-static struct rpc_program	pmap_program;
-
-static void pmap_getport_prepare(struct rpc_task *task, void *calldata)
-{
-	struct portmap_args *map = calldata;
-	struct rpc_message msg = {
-		.rpc_proc	= &pmap_procedures[PMAP_GETPORT],
-		.rpc_argp	= map,
-		.rpc_resp	= &map->pm_port,
-	};
-
-	rpc_call_setup(task, &msg, 0);
-}
-
-static inline struct portmap_args *pmap_map_alloc(void)
-{
-	return kmalloc(sizeof(struct portmap_args), GFP_NOFS);
-}
-
-static inline void pmap_map_free(struct portmap_args *map)
-{
-	kfree(map);
-}
-
-static void pmap_map_release(void *data)
-{
-	struct portmap_args *map = data;
-
-	xprt_put(map->pm_xprt);
-	pmap_map_free(map);
-}
-
-static const struct rpc_call_ops pmap_getport_ops = {
-	.rpc_call_prepare	= pmap_getport_prepare,
-	.rpc_call_done		= pmap_getport_done,
-	.rpc_release		= pmap_map_release,
-};
-
-static inline void pmap_wake_portmap_waiters(struct rpc_xprt *xprt, int status)
-{
-	xprt_clear_binding(xprt);
-	rpc_wake_up_status(&xprt->binding, status);
-}
-
-/**
- * rpc_getport - obtain the port for a given RPC service on a given host
- * @task: task that is waiting for portmapper request
- *
- * This one can be called for an ongoing RPC request, and can be used in
- * an async (rpciod) context.
- */
-void rpc_getport(struct rpc_task *task)
-{
-	struct rpc_clnt *clnt = task->tk_client;
-	struct rpc_xprt *xprt = task->tk_xprt;
-	struct sockaddr_in addr;
-	struct portmap_args *map;
-	struct rpc_clnt	*pmap_clnt;
-	struct rpc_task *child;
-	int status;
-
-	dprintk("RPC: %5u rpc_getport(%s, %u, %u, %d)\n",
-			task->tk_pid, clnt->cl_server,
-			clnt->cl_prog, clnt->cl_vers, xprt->prot);
-
-	/* Autobind on cloned rpc clients is discouraged */
-	BUG_ON(clnt->cl_parent != clnt);
-
-	status = -EACCES;		/* tell caller to check again */
-	if (xprt_test_and_set_binding(xprt))
-		goto bailout_nowake;
-
-	/* Put self on queue before sending rpcbind request, in case
-	 * pmap_getport_done completes before we return from rpc_run_task */
-	rpc_sleep_on(&xprt->binding, task, NULL, NULL);
-
-	/* Someone else may have bound if we slept */
-	status = 0;
-	if (xprt_bound(xprt))
-		goto bailout_nofree;
-
-	status = -ENOMEM;
-	map = pmap_map_alloc();
-	if (!map)
-		goto bailout_nofree;
-	map->pm_prog = clnt->cl_prog;
-	map->pm_vers = clnt->cl_vers;
-	map->pm_prot = xprt->prot;
-	map->pm_port = 0;
-	map->pm_xprt = xprt_get(xprt);
-
-	rpc_peeraddr(clnt, (struct sockaddr *) &addr, sizeof(addr));
-	pmap_clnt = pmap_create(clnt->cl_server, &addr, map->pm_prot, 0);
-	status = PTR_ERR(pmap_clnt);
-	if (IS_ERR(pmap_clnt))
-		goto bailout;
-
-	status = -EIO;
-	child = rpc_run_task(pmap_clnt, RPC_TASK_ASYNC, &pmap_getport_ops, map);
-	if (IS_ERR(child))
-		goto bailout_nofree;
-	rpc_put_task(child);
-
-	task->tk_xprt->stat.bind_count++;
-	return;
-
-bailout:
-	pmap_map_free(map);
-	xprt_put(xprt);
-bailout_nofree:
-	pmap_wake_portmap_waiters(xprt, status);
-bailout_nowake:
-	task->tk_status = status;
-}
-
-#ifdef CONFIG_ROOT_NFS
-/**
- * rpc_getport_external - obtain the port for a given RPC service on a given host
- * @sin: address of remote peer
- * @prog: RPC program number to bind
- * @vers: RPC version number to bind
- * @prot: transport protocol to use to make this request
- *
- * This one is called from outside the RPC client in a synchronous task context.
- */
-int rpc_getport_external(struct sockaddr_in *sin, __u32 prog, __u32 vers, int prot)
-{
-	struct portmap_args map = {
-		.pm_prog	= prog,
-		.pm_vers	= vers,
-		.pm_prot	= prot,
-		.pm_port	= 0
-	};
-	struct rpc_message msg = {
-		.rpc_proc	= &pmap_procedures[PMAP_GETPORT],
-		.rpc_argp	= &map,
-		.rpc_resp	= &map.pm_port,
-	};
-	struct rpc_clnt	*pmap_clnt;
-	char		hostname[32];
-	int		status;
-
-	dprintk("RPC:       rpc_getport_external(%u.%u.%u.%u, %u, %u, %d)\n",
-			NIPQUAD(sin->sin_addr.s_addr), prog, vers, prot);
-
-	sprintf(hostname, "%u.%u.%u.%u", NIPQUAD(sin->sin_addr.s_addr));
-	pmap_clnt = pmap_create(hostname, sin, prot, 0);
-	if (IS_ERR(pmap_clnt))
-		return PTR_ERR(pmap_clnt);
-
-	/* Setup the call info struct */
-	status = rpc_call_sync(pmap_clnt, &msg, 0);
-
-	if (status >= 0) {
-		if (map.pm_port != 0)
-			return map.pm_port;
-		status = -EACCES;
-	}
-	return status;
-}
-#endif
-
-/*
- * Portmapper child task invokes this callback via tk_exit.
- */
-static void pmap_getport_done(struct rpc_task *child, void *data)
-{
-	struct portmap_args *map = data;
-	struct rpc_xprt *xprt = map->pm_xprt;
-	int status = child->tk_status;
-
-	if (status < 0) {
-		/* Portmapper not available */
-		xprt->ops->set_port(xprt, 0);
-	} else if (map->pm_port == 0) {
-		/* Requested RPC service wasn't registered */
-		xprt->ops->set_port(xprt, 0);
-		status = -EACCES;
-	} else {
-		/* Succeeded */
-		xprt->ops->set_port(xprt, map->pm_port);
-		xprt_set_bound(xprt);
-		status = 0;
-	}
-
-	dprintk("RPC: %5u pmap_getport_done(status %d, port %u)\n",
-			child->tk_pid, status, map->pm_port);
-
-	pmap_wake_portmap_waiters(xprt, status);
-}
-
-/**
- * rpc_register - set or unset a port registration with the local portmapper
- * @prog: RPC program number to bind
- * @vers: RPC version number to bind
- * @prot: transport protocol to use to make this request
- * @port: port value to register
- * @okay: result code
- *
- * port == 0 means unregister, port != 0 means register.
- */
-int rpc_register(u32 prog, u32 vers, int prot, unsigned short port, int *okay)
-{
-	struct sockaddr_in	sin = {
-		.sin_family	= AF_INET,
-		.sin_addr.s_addr = htonl(INADDR_LOOPBACK),
-	};
-	struct portmap_args	map = {
-		.pm_prog	= prog,
-		.pm_vers	= vers,
-		.pm_prot	= prot,
-		.pm_port	= port,
-	};
-	struct rpc_message msg = {
-		.rpc_proc	= &pmap_procedures[port ? PMAP_SET : PMAP_UNSET],
-		.rpc_argp	= &map,
-		.rpc_resp	= okay,
-	};
-	struct rpc_clnt		*pmap_clnt;
-	int error = 0;
-
-	dprintk("RPC:       registering (%u, %u, %d, %u) with portmapper.\n",
-			prog, vers, prot, port);
-
-	pmap_clnt = pmap_create("localhost", &sin, IPPROTO_UDP, 1);
-	if (IS_ERR(pmap_clnt)) {
-		error = PTR_ERR(pmap_clnt);
-		dprintk("RPC:       couldn't create pmap client. Error = %d\n",
-				error);
-		return error;
-	}
-
-	error = rpc_call_sync(pmap_clnt, &msg, 0);
-
-	if (error < 0) {
-		printk(KERN_WARNING
-			"RPC: failed to contact portmap (errno %d).\n",
-			error);
-	}
-	dprintk("RPC:       registration status %d/%d\n", error, *okay);
-
-	/* Client deleted automatically because cl_oneshot == 1 */
-	return error;
-}
-
-static struct rpc_clnt *pmap_create(char *hostname, struct sockaddr_in *srvaddr, int proto, int privileged)
-{
-	struct rpc_create_args args = {
-		.protocol	= proto,
-		.address	= (struct sockaddr *)srvaddr,
-		.addrsize	= sizeof(*srvaddr),
-		.servername	= hostname,
-		.program	= &pmap_program,
-		.version	= RPC_PMAP_VERSION,
-		.authflavor	= RPC_AUTH_UNIX,
-		.flags		= (RPC_CLNT_CREATE_ONESHOT |
-				   RPC_CLNT_CREATE_NOPING),
-	};
-
-	srvaddr->sin_port = htons(RPC_PMAP_PORT);
-	if (!privileged)
-		args.flags |= RPC_CLNT_CREATE_NONPRIVPORT;
-	return rpc_create(&args);
-}
-
-/*
- * XDR encode/decode functions for PMAP
- */
-static int xdr_encode_mapping(struct rpc_rqst *req, __be32 *p, struct portmap_args *map)
-{
-	dprintk("RPC:       xdr_encode_mapping(%u, %u, %u, %u)\n",
-			map->pm_prog, map->pm_vers,
-			map->pm_prot, map->pm_port);
-	*p++ = htonl(map->pm_prog);
-	*p++ = htonl(map->pm_vers);
-	*p++ = htonl(map->pm_prot);
-	*p++ = htonl(map->pm_port);
-
-	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
-	return 0;
-}
-
-static int xdr_decode_port(struct rpc_rqst *req, __be32 *p, unsigned short *portp)
-{
-	*portp = (unsigned short) ntohl(*p++);
-	return 0;
-}
-
-static int xdr_decode_bool(struct rpc_rqst *req, __be32 *p, unsigned int *boolp)
-{
-	*boolp = (unsigned int) ntohl(*p++);
-	return 0;
-}
-
-static struct rpc_procinfo	pmap_procedures[] = {
-[PMAP_SET] = {
-	  .p_proc		= PMAP_SET,
-	  .p_encode		= (kxdrproc_t) xdr_encode_mapping,
-	  .p_decode		= (kxdrproc_t) xdr_decode_bool,
-	  .p_bufsiz		= 4,
-	  .p_count		= 1,
-	  .p_statidx		= PMAP_SET,
-	  .p_name		= "SET",
-	},
-[PMAP_UNSET] = {
-	  .p_proc		= PMAP_UNSET,
-	  .p_encode		= (kxdrproc_t) xdr_encode_mapping,
-	  .p_decode		= (kxdrproc_t) xdr_decode_bool,
-	  .p_bufsiz		= 4,
-	  .p_count		= 1,
-	  .p_statidx		= PMAP_UNSET,
-	  .p_name		= "UNSET",
-	},
-[PMAP_GETPORT] = {
-	  .p_proc		= PMAP_GETPORT,
-	  .p_encode		= (kxdrproc_t) xdr_encode_mapping,
-	  .p_decode		= (kxdrproc_t) xdr_decode_port,
-	  .p_bufsiz		= 4,
-	  .p_count		= 1,
-	  .p_statidx		= PMAP_GETPORT,
-	  .p_name		= "GETPORT",
-	},
-};
-
-static struct rpc_version	pmap_version2 = {
-	.number		= 2,
-	.nrprocs	= 4,
-	.procs		= pmap_procedures
-};
-
-static struct rpc_version *	pmap_version[] = {
-	NULL,
-	NULL,
-	&pmap_version2
-};
-
-static struct rpc_stat		pmap_stats;
-
-static struct rpc_program	pmap_program = {
-	.name		= "portmap",
-	.number		= RPC_PMAP_PROGRAM,
-	.nrvers		= ARRAY_SIZE(pmap_version),
-	.version	= pmap_version,
-	.stats		= &pmap_stats,
-};
diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c
new file mode 100644
index 0000000..6c7aa8a
--- /dev/null
+++ b/net/sunrpc/rpcb_clnt.c
@@ -0,0 +1,625 @@
+/*
+ * In-kernel rpcbind client supporting versions 2, 3, and 4 of the rpcbind
+ * protocol
+ *
+ * Based on RFC 1833: "Binding Protocols for ONC RPC Version 2" and
+ * RFC 3530: "Network File System (NFS) version 4 Protocol"
+ *
+ * Original: Gilles Quillard, Bull Open Source, 2005 <gilles.quillard@bull.net>
+ * Updated: Chuck Lever, Oracle Corporation, 2007 <chuck.lever@oracle.com>
+ *
+ * Descended from net/sunrpc/pmap_clnt.c,
+ *  Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de>
+ */
+
+#include <linux/types.h>
+#include <linux/socket.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+
+#include <linux/sunrpc/clnt.h>
+#include <linux/sunrpc/sched.h>
+
+#ifdef RPC_DEBUG
+# define RPCDBG_FACILITY	RPCDBG_BIND
+#endif
+
+#define RPCBIND_PROGRAM		(100000u)
+#define RPCBIND_PORT		(111u)
+
+enum {
+	RPCBPROC_NULL,
+	RPCBPROC_SET,
+	RPCBPROC_UNSET,
+	RPCBPROC_GETPORT,
+	RPCBPROC_GETADDR = 3,		/* alias for GETPORT */
+	RPCBPROC_DUMP,
+	RPCBPROC_CALLIT,
+	RPCBPROC_BCAST = 5,		/* alias for CALLIT */
+	RPCBPROC_GETTIME,
+	RPCBPROC_UADDR2TADDR,
+	RPCBPROC_TADDR2UADDR,
+	RPCBPROC_GETVERSADDR,
+	RPCBPROC_INDIRECT,
+	RPCBPROC_GETADDRLIST,
+	RPCBPROC_GETSTAT,
+};
+
+#define RPCB_HIGHPROC_2		RPCBPROC_CALLIT
+#define RPCB_HIGHPROC_3		RPCBPROC_TADDR2UADDR
+#define RPCB_HIGHPROC_4		RPCBPROC_GETSTAT
+
+/*
+ * r_addr
+ *
+ * Quoting RFC 3530, section 2.2:
+ *
+ * For TCP over IPv4 and for UDP over IPv4, the format of r_addr is the
+ * US-ASCII string:
+ *
+ *	h1.h2.h3.h4.p1.p2
+ *
+ * The prefix, "h1.h2.h3.h4", is the standard textual form for
+ * representing an IPv4 address, which is always four octets long.
+ * Assuming big-endian ordering, h1, h2, h3, and h4, are respectively,
+ * the first through fourth octets each converted to ASCII-decimal.
+ * Assuming big-endian ordering, p1 and p2 are, respectively, the first
+ * and second octets each converted to ASCII-decimal.  For example, if a
+ * host, in big-endian order, has an address of 0x0A010307 and there is
+ * a service listening on, in big endian order, port 0x020F (decimal
+ * 527), then the complete universal address is "10.1.3.7.2.15".
+ *
+ * ...
+ *
+ * For TCP over IPv6 and for UDP over IPv6, the format of r_addr is the
+ * US-ASCII string:
+ *
+ *	x1:x2:x3:x4:x5:x6:x7:x8.p1.p2
+ *
+ * The suffix "p1.p2" is the service port, and is computed the same way
+ * as with universal addresses for TCP and UDP over IPv4.  The prefix,
+ * "x1:x2:x3:x4:x5:x6:x7:x8", is the standard textual form for
+ * representing an IPv6 address as defined in Section 2.2 of [RFC2373].
+ * Additionally, the two alternative forms specified in Section 2.2 of
+ * [RFC2373] are also acceptable.
+ *
+ * XXX: Currently this implementation does not explicitly convert the
+ *      stored address to US-ASCII on non-ASCII systems.
+ */
+#define RPCB_MAXADDRLEN		(128u)
+
+/*
+ * r_netid
+ *
+ * Quoting RFC 3530, section 2.2:
+ *
+ * For TCP over IPv4 the value of r_netid is the string "tcp".  For UDP
+ * over IPv4 the value of r_netid is the string "udp".
+ *
+ * ...
+ *
+ * For TCP over IPv6 the value of r_netid is the string "tcp6".  For UDP
+ * over IPv6 the value of r_netid is the string "udp6".
+ */
+#define RPCB_NETID_UDP	"\165\144\160"		/* "udp" */
+#define RPCB_NETID_TCP	"\164\143\160"		/* "tcp" */
+#define RPCB_NETID_UDP6	"\165\144\160\066"	/* "udp6" */
+#define RPCB_NETID_TCP6	"\164\143\160\066"	/* "tcp6" */
+
+#define RPCB_MAXNETIDLEN	(4u)
+
+/*
+ * r_owner
+ *
+ * The "owner" is allowed to unset a service in the rpcbind database.
+ * We always use the following (arbitrary) fixed string.
+ */
+#define RPCB_OWNER_STRING	"rpcb"
+#define RPCB_MAXOWNERLEN	sizeof(RPCB_OWNER_STRING)
+
+static void			rpcb_getport_done(struct rpc_task *, void *);
+extern struct rpc_program	rpcb_program;
+
+struct rpcbind_args {
+	struct rpc_xprt *	r_xprt;
+
+	u32			r_prog;
+	u32			r_vers;
+	u32			r_prot;
+	unsigned short		r_port;
+	char *			r_netid;
+	char			r_addr[RPCB_MAXADDRLEN];
+	char *			r_owner;
+};
+
+static struct rpc_procinfo rpcb_procedures2[];
+static struct rpc_procinfo rpcb_procedures3[];
+
+static struct rpcb_info {
+	int			rpc_vers;
+	struct rpc_procinfo *	rpc_proc;
+} rpcb_next_version[];
+
+static void rpcb_getport_prepare(struct rpc_task *task, void *calldata)
+{
+	struct rpcbind_args *map = calldata;
+	struct rpc_xprt *xprt = map->r_xprt;
+	struct rpc_message msg = {
+		.rpc_proc	= rpcb_next_version[xprt->bind_index].rpc_proc,
+		.rpc_argp	= map,
+		.rpc_resp	= &map->r_port,
+	};
+
+	rpc_call_setup(task, &msg, 0);
+}
+
+static void rpcb_map_release(void *data)
+{
+	struct rpcbind_args *map = data;
+
+	xprt_put(map->r_xprt);
+	kfree(map);
+}
+
+static const struct rpc_call_ops rpcb_getport_ops = {
+	.rpc_call_prepare	= rpcb_getport_prepare,
+	.rpc_call_done		= rpcb_getport_done,
+	.rpc_release		= rpcb_map_release,
+};
+
+static void rpcb_wake_rpcbind_waiters(struct rpc_xprt *xprt, int status)
+{
+	xprt_clear_binding(xprt);
+	rpc_wake_up_status(&xprt->binding, status);
+}
+
+static struct rpc_clnt *rpcb_create(char *hostname, struct sockaddr *srvaddr,
+					int proto, int version, int privileged)
+{
+	struct rpc_create_args args = {
+		.protocol	= proto,
+		.address	= srvaddr,
+		.addrsize	= sizeof(struct sockaddr_in),
+		.servername	= hostname,
+		.program	= &rpcb_program,
+		.version	= version,
+		.authflavor	= RPC_AUTH_UNIX,
+		.flags		= (RPC_CLNT_CREATE_ONESHOT |
+				   RPC_CLNT_CREATE_NOPING),
+	};
+
+	((struct sockaddr_in *)srvaddr)->sin_port = htons(RPCBIND_PORT);
+	if (!privileged)
+		args.flags |= RPC_CLNT_CREATE_NONPRIVPORT;
+	return rpc_create(&args);
+}
+
+/**
+ * rpcb_register - set or unset a port registration with the local rpcbind svc
+ * @prog: RPC program number to bind
+ * @vers: RPC version number to bind
+ * @prot: transport protocol to use to make this request
+ * @port: port value to register
+ * @okay: result code
+ *
+ * port == 0 means unregister, port != 0 means register.
+ *
+ * This routine supports only rpcbind version 2.
+ */
+int rpcb_register(u32 prog, u32 vers, int prot, unsigned short port, int *okay)
+{
+	struct sockaddr_in sin = {
+		.sin_family		= AF_INET,
+		.sin_addr.s_addr	= htonl(INADDR_LOOPBACK),
+	};
+	struct rpcbind_args map = {
+		.r_prog		= prog,
+		.r_vers		= vers,
+		.r_prot		= prot,
+		.r_port		= port,
+	};
+	struct rpc_message msg = {
+		.rpc_proc	= &rpcb_procedures2[port ?
+					RPCBPROC_SET : RPCBPROC_UNSET],
+		.rpc_argp	= &map,
+		.rpc_resp	= okay,
+	};
+	struct rpc_clnt *rpcb_clnt;
+	int error = 0;
+
+	dprintk("RPC:       %sregistering (%u, %u, %d, %u) with local "
+			"rpcbind\n", (port ? "" : "un"),
+			prog, vers, prot, port);
+
+	rpcb_clnt = rpcb_create("localhost", (struct sockaddr *) &sin,
+					IPPROTO_UDP, 2, 1);
+	if (IS_ERR(rpcb_clnt))
+		return PTR_ERR(rpcb_clnt);
+
+	error = rpc_call_sync(rpcb_clnt, &msg, 0);
+
+	if (error < 0)
+		printk(KERN_WARNING "RPC: failed to contact local rpcbind "
+				"server (errno %d).\n", -error);
+	dprintk("RPC:       registration status %d/%d\n", error, *okay);
+
+	return error;
+}
+
+#ifdef CONFIG_ROOT_NFS
+/**
+ * rpcb_getport_external - obtain the port for an RPC service on a given host
+ * @sin: address of remote peer
+ * @prog: RPC program number to bind
+ * @vers: RPC version number to bind
+ * @prot: transport protocol to use to make this request
+ *
+ * Called from outside the RPC client in a synchronous task context.
+ *
+ * For now, this supports only version 2 queries, but is used only by
+ * mount_clnt for NFS_ROOT.
+ */
+int rpcb_getport_external(struct sockaddr_in *sin, __u32 prog,
+				__u32 vers, int prot)
+{
+	struct rpcbind_args map = {
+		.r_prog		= prog,
+		.r_vers		= vers,
+		.r_prot		= prot,
+		.r_port		= 0,
+	};
+	struct rpc_message msg = {
+		.rpc_proc	= &rpcb_procedures2[RPCBPROC_GETPORT],
+		.rpc_argp	= &map,
+		.rpc_resp	= &map.r_port,
+	};
+	struct rpc_clnt	*rpcb_clnt;
+	char hostname[40];
+	int status;
+
+	dprintk("RPC:       rpcb_getport_external(%u.%u.%u.%u, %u, %u, %d)\n",
+			NIPQUAD(sin->sin_addr.s_addr), prog, vers, prot);
+
+	sprintf(hostname, "%u.%u.%u.%u", NIPQUAD(sin->sin_addr.s_addr));
+	rpcb_clnt = rpcb_create(hostname, (struct sockaddr *)sin, prot, 2, 0);
+	if (IS_ERR(rpcb_clnt))
+		return PTR_ERR(rpcb_clnt);
+
+	status = rpc_call_sync(rpcb_clnt, &msg, 0);
+
+	if (status >= 0) {
+		if (map.r_port != 0)
+			return map.r_port;
+		status = -EACCES;
+	}
+	return status;
+}
+#endif
+
+/**
+ * rpcb_getport - obtain the port for a given RPC service on a given host
+ * @task: task that is waiting for portmapper request
+ *
+ * This one can be called for an ongoing RPC request, and can be used in
+ * an async (rpciod) context.
+ */
+void rpcb_getport(struct rpc_task *task)
+{
+	struct rpc_clnt *clnt = task->tk_client;
+	int bind_version;
+	struct rpc_xprt *xprt = task->tk_xprt;
+	struct rpc_clnt	*rpcb_clnt;
+	static struct rpcbind_args *map;
+	struct rpc_task	*child;
+	struct sockaddr addr;
+	int status;
+
+	dprintk("RPC: %5u rpcb_getport(%s, %u, %u, %d)\n",
+			task->tk_pid, clnt->cl_server,
+			clnt->cl_prog, clnt->cl_vers, xprt->prot);
+
+	/* Autobind on cloned rpc clients is discouraged */
+	BUG_ON(clnt->cl_parent != clnt);
+
+	if (xprt_test_and_set_binding(xprt)) {
+		status = -EACCES;		/* tell caller to check again */
+		dprintk("RPC: %5u rpcb_getport waiting for another binder\n",
+				task->tk_pid);
+		goto bailout_nowake;
+	}
+
+	/* Put self on queue before sending rpcbind request, in case
+	 * rpcb_getport_done completes before we return from rpc_run_task */
+	rpc_sleep_on(&xprt->binding, task, NULL, NULL);
+
+	/* Someone else may have bound if we slept */
+	if (xprt_bound(xprt)) {
+		status = 0;
+		dprintk("RPC: %5u rpcb_getport already bound\n", task->tk_pid);
+		goto bailout_nofree;
+	}
+
+	if (rpcb_next_version[xprt->bind_index].rpc_proc == NULL) {
+		xprt->bind_index = 0;
+		status = -EACCES;	/* tell caller to try again later */
+		dprintk("RPC: %5u rpcb_getport no more getport versions "
+				"available\n", task->tk_pid);
+		goto bailout_nofree;
+	}
+	bind_version = rpcb_next_version[xprt->bind_index].rpc_vers;
+
+	dprintk("RPC: %5u rpcb_getport trying rpcbind version %u\n",
+			task->tk_pid, bind_version);
+
+	map = kzalloc(sizeof(struct rpcbind_args), GFP_ATOMIC);
+	if (!map) {
+		status = -ENOMEM;
+		dprintk("RPC: %5u rpcb_getport no memory available\n",
+				task->tk_pid);
+		goto bailout_nofree;
+	}
+	map->r_prog = clnt->cl_prog;
+	map->r_vers = clnt->cl_vers;
+	map->r_prot = xprt->prot;
+	map->r_port = 0;
+	map->r_xprt = xprt_get(xprt);
+	map->r_netid = (xprt->prot == IPPROTO_TCP) ? RPCB_NETID_TCP :
+						   RPCB_NETID_UDP;
+	memcpy(&map->r_addr, rpc_peeraddr2str(clnt, RPC_DISPLAY_ADDR),
+			sizeof(map->r_addr));
+	map->r_owner = RPCB_OWNER_STRING;	/* ignored for GETADDR */
+
+	rpc_peeraddr(clnt, (void *)&addr, sizeof(addr));
+	rpcb_clnt = rpcb_create(clnt->cl_server, &addr, xprt->prot, bind_version, 0);
+	if (IS_ERR(rpcb_clnt)) {
+		status = PTR_ERR(rpcb_clnt);
+		dprintk("RPC: %5u rpcb_getport rpcb_create failed, error %ld\n",
+				task->tk_pid, PTR_ERR(rpcb_clnt));
+		goto bailout;
+	}
+
+	child = rpc_run_task(rpcb_clnt, RPC_TASK_ASYNC, &rpcb_getport_ops, map);
+	if (IS_ERR(child)) {
+		status = -EIO;
+		dprintk("RPC: %5u rpcb_getport rpc_run_task failed\n",
+				task->tk_pid);
+		goto bailout_nofree;
+	}
+	rpc_put_task(child);
+
+	task->tk_xprt->stat.bind_count++;
+	return;
+
+bailout:
+	kfree(map);
+	xprt_put(xprt);
+bailout_nofree:
+	rpcb_wake_rpcbind_waiters(xprt, status);
+bailout_nowake:
+	task->tk_status = status;
+}
+
+/*
+ * Rpcbind child task calls this callback via tk_exit.
+ */
+static void rpcb_getport_done(struct rpc_task *child, void *data)
+{
+	struct rpcbind_args *map = data;
+	struct rpc_xprt *xprt = map->r_xprt;
+	int status = child->tk_status;
+
+	/* rpcbind server doesn't support this rpcbind protocol version */
+	if (status == -EPROTONOSUPPORT)
+		xprt->bind_index++;
+
+	if (status < 0) {
+		/* rpcbind server not available on remote host? */
+		xprt->ops->set_port(xprt, 0);
+	} else if (map->r_port == 0) {
+		/* Requested RPC service wasn't registered on remote host */
+		xprt->ops->set_port(xprt, 0);
+		status = -EACCES;
+	} else {
+		/* Succeeded */
+		xprt->ops->set_port(xprt, map->r_port);
+		xprt_set_bound(xprt);
+		status = 0;
+	}
+
+	dprintk("RPC: %5u rpcb_getport_done(status %d, port %u)\n",
+			child->tk_pid, status, map->r_port);
+
+	rpcb_wake_rpcbind_waiters(xprt, status);
+}
+
+static int rpcb_encode_mapping(struct rpc_rqst *req, __be32 *p,
+			       struct rpcbind_args *rpcb)
+{
+	dprintk("RPC:       rpcb_encode_mapping(%u, %u, %d, %u)\n",
+			rpcb->r_prog, rpcb->r_vers, rpcb->r_prot, rpcb->r_port);
+	*p++ = htonl(rpcb->r_prog);
+	*p++ = htonl(rpcb->r_vers);
+	*p++ = htonl(rpcb->r_prot);
+	*p++ = htonl(rpcb->r_port);
+
+	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
+	return 0;
+}
+
+static int rpcb_decode_getport(struct rpc_rqst *req, __be32 *p,
+			       unsigned short *portp)
+{
+	*portp = (unsigned short) ntohl(*p++);
+	dprintk("RPC:      rpcb_decode_getport result %u\n",
+			*portp);
+	return 0;
+}
+
+static int rpcb_decode_set(struct rpc_rqst *req, __be32 *p,
+			   unsigned int *boolp)
+{
+	*boolp = (unsigned int) ntohl(*p++);
+	dprintk("RPC:      rpcb_decode_set result %u\n",
+			*boolp);
+	return 0;
+}
+
+static int rpcb_encode_getaddr(struct rpc_rqst *req, __be32 *p,
+			       struct rpcbind_args *rpcb)
+{
+	dprintk("RPC:       rpcb_encode_getaddr(%u, %u, %s)\n",
+			rpcb->r_prog, rpcb->r_vers, rpcb->r_addr);
+	*p++ = htonl(rpcb->r_prog);
+	*p++ = htonl(rpcb->r_vers);
+
+	p = xdr_encode_string(p, rpcb->r_netid);
+	p = xdr_encode_string(p, rpcb->r_addr);
+	p = xdr_encode_string(p, rpcb->r_owner);
+
+	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
+
+	return 0;
+}
+
+static int rpcb_decode_getaddr(struct rpc_rqst *req, __be32 *p,
+			       unsigned short *portp)
+{
+	char *addr;
+	int addr_len, c, i, f, first, val;
+
+	*portp = 0;
+	addr_len = (unsigned int) ntohl(*p++);
+	if (addr_len > RPCB_MAXADDRLEN)			/* sanity */
+		return -EINVAL;
+
+	dprintk("RPC:       rpcb_decode_getaddr returned string: '%s'\n",
+			(char *) p);
+
+	addr = (char *)p;
+	val = 0;
+	first = 1;
+	f = 1;
+	for (i = addr_len - 1; i > 0; i--) {
+		c = addr[i];
+		if (c >= '0' && c <= '9') {
+			val += (c - '0') * f;
+			f *= 10;
+		} else if (c == '.') {
+			if (first) {
+				*portp = val;
+				val = first = 0;
+				f = 1;
+			} else {
+				*portp |= (val << 8);
+				break;
+			}
+		}
+	}
+
+	dprintk("RPC:       rpcb_decode_getaddr port=%u\n", *portp);
+	return 0;
+}
+
+#define RPCB_program_sz		(1u)
+#define RPCB_version_sz		(1u)
+#define RPCB_protocol_sz	(1u)
+#define RPCB_port_sz		(1u)
+#define RPCB_boolean_sz		(1u)
+
+#define RPCB_netid_sz		(1+XDR_QUADLEN(RPCB_MAXNETIDLEN))
+#define RPCB_addr_sz		(1+XDR_QUADLEN(RPCB_MAXADDRLEN))
+#define RPCB_ownerstring_sz	(1+XDR_QUADLEN(RPCB_MAXOWNERLEN))
+
+#define RPCB_mappingargs_sz	RPCB_program_sz+RPCB_version_sz+	\
+				RPCB_protocol_sz+RPCB_port_sz
+#define RPCB_getaddrargs_sz	RPCB_program_sz+RPCB_version_sz+	\
+				RPCB_netid_sz+RPCB_addr_sz+		\
+				RPCB_ownerstring_sz
+
+#define RPCB_setres_sz		RPCB_boolean_sz
+#define RPCB_getportres_sz	RPCB_port_sz
+
+/*
+ * Note that RFC 1833 does not put any size restrictions on the
+ * address string returned by the remote rpcbind database.
+ */
+#define RPCB_getaddrres_sz	RPCB_addr_sz
+
+#define PROC(proc, argtype, restype)					\
+	[RPCBPROC_##proc] = {						\
+		.p_proc		= RPCBPROC_##proc,			\
+		.p_encode	= (kxdrproc_t) rpcb_encode_##argtype,	\
+		.p_decode	= (kxdrproc_t) rpcb_decode_##restype,	\
+		.p_arglen	= RPCB_##argtype##args_sz,		\
+		.p_replen	= RPCB_##restype##res_sz,		\
+		.p_statidx	= RPCBPROC_##proc,			\
+		.p_timer	= 0,					\
+		.p_name		= #proc,				\
+	}
+
+/*
+ * Not all rpcbind procedures described in RFC 1833 are implemented
+ * since the Linux kernel RPC code requires only these.
+ */
+static struct rpc_procinfo rpcb_procedures2[] = {
+	PROC(SET,		mapping,	set),
+	PROC(UNSET,		mapping,	set),
+	PROC(GETADDR,		mapping,	getport),
+};
+
+static struct rpc_procinfo rpcb_procedures3[] = {
+	PROC(SET,		mapping,	set),
+	PROC(UNSET,		mapping,	set),
+	PROC(GETADDR,		getaddr,	getaddr),
+};
+
+static struct rpc_procinfo rpcb_procedures4[] = {
+	PROC(SET,		mapping,	set),
+	PROC(UNSET,		mapping,	set),
+	PROC(GETVERSADDR,	getaddr,	getaddr),
+};
+
+static struct rpcb_info rpcb_next_version[] = {
+#ifdef CONFIG_SUNRPC_BIND34
+	{ 4, &rpcb_procedures4[RPCBPROC_GETVERSADDR] },
+	{ 3, &rpcb_procedures3[RPCBPROC_GETADDR] },
+#endif
+	{ 2, &rpcb_procedures2[RPCBPROC_GETPORT] },
+	{ 0, NULL },
+};
+
+static struct rpc_version rpcb_version2 = {
+	.number		= 2,
+	.nrprocs	= RPCB_HIGHPROC_2,
+	.procs		= rpcb_procedures2
+};
+
+static struct rpc_version rpcb_version3 = {
+	.number		= 3,
+	.nrprocs	= RPCB_HIGHPROC_3,
+	.procs		= rpcb_procedures3
+};
+
+static struct rpc_version rpcb_version4 = {
+	.number		= 4,
+	.nrprocs	= RPCB_HIGHPROC_4,
+	.procs		= rpcb_procedures4
+};
+
+static struct rpc_version *rpcb_version[] = {
+	NULL,
+	NULL,
+	&rpcb_version2,
+	&rpcb_version3,
+	&rpcb_version4
+};
+
+static struct rpc_stat rpcb_stats;
+
+struct rpc_program rpcb_program = {
+	.name		= "rpcbind",
+	.number		= RPCBIND_PROGRAM,
+	.nrvers		= ARRAY_SIZE(rpcb_version),
+	.version	= rpcb_version,
+	.stats		= &rpcb_stats,
+};
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c
index 6d87320..4a53e94 100644
--- a/net/sunrpc/sched.c
+++ b/net/sunrpc/sched.c
@@ -741,50 +741,53 @@
  * @task: RPC task that will use this buffer
  * @size: requested byte size
  *
- * We try to ensure that some NFS reads and writes can always proceed
- * by using a mempool when allocating 'small' buffers.
+ * To prevent rpciod from hanging, this allocator never sleeps,
+ * returning NULL if the request cannot be serviced immediately.
+ * The caller can arrange to sleep in a way that is safe for rpciod.
+ *
+ * Most requests are 'small' (under 2KiB) and can be serviced from a
+ * mempool, ensuring that NFS reads and writes can always proceed,
+ * and that there is good locality of reference for these buffers.
+ *
  * In order to avoid memory starvation triggering more writebacks of
- * NFS requests, we use GFP_NOFS rather than GFP_KERNEL.
+ * NFS requests, we avoid using GFP_KERNEL.
  */
-void * rpc_malloc(struct rpc_task *task, size_t size)
+void *rpc_malloc(struct rpc_task *task, size_t size)
 {
-	struct rpc_rqst *req = task->tk_rqstp;
-	gfp_t	gfp;
+	size_t *buf;
+	gfp_t gfp = RPC_IS_SWAPPER(task) ? GFP_ATOMIC : GFP_NOWAIT;
 
-	if (task->tk_flags & RPC_TASK_SWAPPER)
-		gfp = GFP_ATOMIC;
+	size += sizeof(size_t);
+	if (size <= RPC_BUFFER_MAXSIZE)
+		buf = mempool_alloc(rpc_buffer_mempool, gfp);
 	else
-		gfp = GFP_NOFS;
-
-	if (size > RPC_BUFFER_MAXSIZE) {
-		req->rq_buffer = kmalloc(size, gfp);
-		if (req->rq_buffer)
-			req->rq_bufsize = size;
-	} else {
-		req->rq_buffer = mempool_alloc(rpc_buffer_mempool, gfp);
-		if (req->rq_buffer)
-			req->rq_bufsize = RPC_BUFFER_MAXSIZE;
-	}
-	return req->rq_buffer;
+		buf = kmalloc(size, gfp);
+	*buf = size;
+	dprintk("RPC: %5u allocated buffer of size %u at %p\n",
+			task->tk_pid, size, buf);
+	return (void *) ++buf;
 }
 
 /**
  * rpc_free - free buffer allocated via rpc_malloc
- * @task: RPC task with a buffer to be freed
+ * @buffer: buffer to free
  *
  */
-void rpc_free(struct rpc_task *task)
+void rpc_free(void *buffer)
 {
-	struct rpc_rqst *req = task->tk_rqstp;
+	size_t size, *buf = (size_t *) buffer;
 
-	if (req->rq_buffer) {
-		if (req->rq_bufsize == RPC_BUFFER_MAXSIZE)
-			mempool_free(req->rq_buffer, rpc_buffer_mempool);
-		else
-			kfree(req->rq_buffer);
-		req->rq_buffer = NULL;
-		req->rq_bufsize = 0;
-	}
+	if (!buffer)
+		return;
+	size = *buf;
+	buf--;
+
+	dprintk("RPC:       freeing buffer of size %u at %p\n",
+			size, buf);
+	if (size <= RPC_BUFFER_MAXSIZE)
+		mempool_free(buf, rpc_buffer_mempool);
+	else
+		kfree(buf);
 }
 
 /*
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c
index b4db53f..b7503c1 100644
--- a/net/sunrpc/svc.c
+++ b/net/sunrpc/svc.c
@@ -757,7 +757,7 @@
 			if (progp->pg_vers[i]->vs_hidden)
 				continue;
 
-			error = rpc_register(progp->pg_prog, i, proto, port, &dummy);
+			error = rpcb_register(progp->pg_prog, i, proto, port, &dummy);
 			if (error < 0)
 				break;
 			if (port && !dummy) {
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index 456a145..5b05b73 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -823,7 +823,6 @@
 	req->rq_task	= task;
 	req->rq_xprt    = xprt;
 	req->rq_buffer  = NULL;
-	req->rq_bufsize = 0;
 	req->rq_xid     = xprt_alloc_xid(xprt);
 	req->rq_release_snd_buf = NULL;
 	xprt_reset_majortimeo(req);
@@ -855,7 +854,7 @@
 		mod_timer(&xprt->timer,
 				xprt->last_used + xprt->idle_timeout);
 	spin_unlock_bh(&xprt->transport_lock);
-	xprt->ops->buf_free(task);
+	xprt->ops->buf_free(req->rq_buffer);
 	task->tk_rqstp = NULL;
 	if (req->rq_release_snd_buf)
 		req->rq_release_snd_buf(req);
@@ -928,6 +927,7 @@
 	xprt->timer.data = (unsigned long) xprt;
 	xprt->last_used = jiffies;
 	xprt->cwnd = RPC_INITCWND;
+	xprt->bind_index = 0;
 
 	rpc_init_wait_queue(&xprt->binding, "xprt_binding");
 	rpc_init_wait_queue(&xprt->pending, "xprt_pending");
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index a5a3202..cc33c588 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -1476,7 +1476,7 @@
 	.set_buffer_size	= xs_udp_set_buffer_size,
 	.reserve_xprt		= xprt_reserve_xprt_cong,
 	.release_xprt		= xprt_release_xprt_cong,
-	.rpcbind		= rpc_getport,
+	.rpcbind		= rpcb_getport,
 	.set_port		= xs_set_port,
 	.connect		= xs_connect,
 	.buf_alloc		= rpc_malloc,
@@ -1493,7 +1493,7 @@
 static struct rpc_xprt_ops xs_tcp_ops = {
 	.reserve_xprt		= xprt_reserve_xprt,
 	.release_xprt		= xs_tcp_release_xprt,
-	.rpcbind		= rpc_getport,
+	.rpcbind		= rpcb_getport,
 	.set_port		= xs_set_port,
 	.connect		= xs_connect,
 	.buf_alloc		= rpc_malloc,
diff --git a/net/tipc/eth_media.c b/net/tipc/eth_media.c
index 67bb29b..0ee6ded 100644
--- a/net/tipc/eth_media.c
+++ b/net/tipc/eth_media.c
@@ -120,16 +120,18 @@
 
 static int enable_bearer(struct tipc_bearer *tb_ptr)
 {
-	struct net_device *dev = dev_base;
+	struct net_device *dev, *pdev;
 	struct eth_bearer *eb_ptr = &eth_bearers[0];
 	struct eth_bearer *stop = &eth_bearers[MAX_ETH_BEARERS];
 	char *driver_name = strchr((const char *)tb_ptr->name, ':') + 1;
 
 	/* Find device with specified name */
-
-	while (dev && dev->name && strncmp(dev->name, driver_name, IFNAMSIZ)) {
-		dev = dev->next;
-	}
+	dev = NULL;
+	for_each_netdev(pdev)
+		if (!strncmp(dev->name, driver_name, IFNAMSIZ)) {
+			dev = pdev;
+			break;
+		}
 	if (!dev)
 		return -ENODEV;
 
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 263e34e..95271e8 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -579,7 +579,7 @@
 	return 0;
 }
 
-void xfrm_spd_getinfo(struct xfrm_spdinfo *si)
+void xfrm_spd_getinfo(struct xfrmk_spdinfo *si)
 {
 	read_lock_bh(&xfrm_policy_lock);
 	si->incnt = xfrm_policy_count[XFRM_POLICY_IN];
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index f3a61eb..9955ff4 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -421,7 +421,7 @@
 }
 EXPORT_SYMBOL(xfrm_state_flush);
 
-void xfrm_sad_getinfo(struct xfrm_sadinfo *si)
+void xfrm_sad_getinfo(struct xfrmk_sadinfo *si)
 {
 	spin_lock_bh(&xfrm_state_lock);
 	si->sadcnt = xfrm_state_num;
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index 4210d91..b14c7e5 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -674,7 +674,9 @@
 
 static int build_spdinfo(struct sk_buff *skb, u32 pid, u32 seq, u32 flags)
 {
-	struct xfrm_spdinfo si;
+	struct xfrmk_spdinfo si;
+	struct xfrmu_spdinfo spc;
+	struct xfrmu_spdhinfo sph;
 	struct nlmsghdr *nlh;
 	u32 *f;
 
@@ -685,23 +687,17 @@
 	f = nlmsg_data(nlh);
 	*f = flags;
 	xfrm_spd_getinfo(&si);
+	spc.incnt = si.incnt;
+	spc.outcnt = si.outcnt;
+	spc.fwdcnt = si.fwdcnt;
+	spc.inscnt = si.inscnt;
+	spc.outscnt = si.outscnt;
+	spc.fwdscnt = si.fwdscnt;
+	sph.spdhcnt = si.spdhcnt;
+	sph.spdhmcnt = si.spdhmcnt;
 
-	if (flags & XFRM_SPD_HMASK)
-		NLA_PUT_U32(skb, XFRMA_SPDHMASK, si.spdhcnt);
-	if (flags & XFRM_SPD_HMAX)
-		NLA_PUT_U32(skb, XFRMA_SPDHMAX, si.spdhmcnt);
-	if (flags & XFRM_SPD_ICNT)
-		NLA_PUT_U32(skb, XFRMA_SPDICNT, si.incnt);
-	if (flags & XFRM_SPD_OCNT)
-		NLA_PUT_U32(skb, XFRMA_SPDOCNT, si.outcnt);
-	if (flags & XFRM_SPD_FCNT)
-		NLA_PUT_U32(skb, XFRMA_SPDFCNT, si.fwdcnt);
-	if (flags & XFRM_SPD_ISCNT)
-		NLA_PUT_U32(skb, XFRMA_SPDISCNT, si.inscnt);
-	if (flags & XFRM_SPD_OSCNT)
-		NLA_PUT_U32(skb, XFRMA_SPDOSCNT, si.inscnt);
-	if (flags & XFRM_SPD_FSCNT)
-		NLA_PUT_U32(skb, XFRMA_SPDFSCNT, si.inscnt);
+	NLA_PUT(skb, XFRMA_SPD_INFO, sizeof(spc), &spc);
+	NLA_PUT(skb, XFRMA_SPD_HINFO, sizeof(sph), &sph);
 
 	return nlmsg_end(skb, nlh);
 
@@ -719,23 +715,8 @@
 	u32 seq = nlh->nlmsg_seq;
 	int len = NLMSG_LENGTH(sizeof(u32));
 
-
-	if (*flags & XFRM_SPD_HMASK)
-		len += RTA_SPACE(sizeof(u32));
-	if (*flags & XFRM_SPD_HMAX)
-		len += RTA_SPACE(sizeof(u32));
-	if (*flags & XFRM_SPD_ICNT)
-		len += RTA_SPACE(sizeof(u32));
-	if (*flags & XFRM_SPD_OCNT)
-		len += RTA_SPACE(sizeof(u32));
-	if (*flags & XFRM_SPD_FCNT)
-		len += RTA_SPACE(sizeof(u32));
-	if (*flags & XFRM_SPD_ISCNT)
-		len += RTA_SPACE(sizeof(u32));
-	if (*flags & XFRM_SPD_OSCNT)
-		len += RTA_SPACE(sizeof(u32));
-	if (*flags & XFRM_SPD_FSCNT)
-		len += RTA_SPACE(sizeof(u32));
+	len += RTA_SPACE(sizeof(struct xfrmu_spdinfo));
+	len += RTA_SPACE(sizeof(struct xfrmu_spdhinfo));
 
 	r_skb = alloc_skb(len, GFP_ATOMIC);
 	if (r_skb == NULL)
@@ -749,7 +730,8 @@
 
 static int build_sadinfo(struct sk_buff *skb, u32 pid, u32 seq, u32 flags)
 {
-	struct xfrm_sadinfo si;
+	struct xfrmk_sadinfo si;
+	struct xfrmu_sadhinfo sh;
 	struct nlmsghdr *nlh;
 	u32 *f;
 
@@ -761,12 +743,11 @@
 	*f = flags;
 	xfrm_sad_getinfo(&si);
 
-	if (flags & XFRM_SAD_HMASK)
-		NLA_PUT_U32(skb, XFRMA_SADHMASK, si.sadhcnt);
-	if (flags & XFRM_SAD_HMAX)
-		NLA_PUT_U32(skb, XFRMA_SADHMAX, si.sadhmcnt);
-	if (flags & XFRM_SAD_CNT)
-		NLA_PUT_U32(skb, XFRMA_SADCNT, si.sadcnt);
+	sh.sadhmcnt = si.sadhmcnt;
+	sh.sadhcnt = si.sadhcnt;
+
+	NLA_PUT_U32(skb, XFRMA_SAD_CNT, si.sadcnt);
+	NLA_PUT(skb, XFRMA_SAD_HINFO, sizeof(sh), &sh);
 
 	return nlmsg_end(skb, nlh);
 
@@ -784,12 +765,8 @@
 	u32 seq = nlh->nlmsg_seq;
 	int len = NLMSG_LENGTH(sizeof(u32));
 
-	if (*flags & XFRM_SAD_HMASK)
-		len += RTA_SPACE(sizeof(u32));
-	if (*flags & XFRM_SAD_HMAX)
-		len += RTA_SPACE(sizeof(u32));
-	if (*flags & XFRM_SAD_CNT)
-		len += RTA_SPACE(sizeof(u32));
+	len += RTA_SPACE(sizeof(struct xfrmu_sadhinfo));
+	len += RTA_SPACE(sizeof(u32));
 
 	r_skb = alloc_skb(len, GFP_ATOMIC);
 
diff --git a/security/inode.c b/security/inode.c
index d7ecf89..307211a 100644
--- a/security/inode.c
+++ b/security/inode.c
@@ -321,7 +321,7 @@
 {
 	int retval;
 
-	kset_set_kset_s(&security_subsys, kernel_subsys);
+	kobj_set_kset_s(&security_subsys, kernel_subsys);
 	retval = subsystem_register(&security_subsys);
 	if (retval)
 		return retval;
diff --git a/sound/core/init.c b/sound/core/init.c
index 4a431e3..f2fe357 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -26,7 +26,6 @@
 #include <linux/slab.h>
 #include <linux/time.h>
 #include <linux/ctype.h>
-#include <linux/pci.h>
 #include <linux/pm.h>
 
 #include <sound/core.h>
diff --git a/sound/oss/au1550_ac97.c b/sound/oss/au1550_ac97.c
index a339f0c..23018a7 100644
--- a/sound/oss/au1550_ac97.c
+++ b/sound/oss/au1550_ac97.c
@@ -47,7 +47,6 @@
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <linux/poll.h>
-#include <linux/pci.h>
 #include <linux/bitops.h>
 #include <linux/spinlock.h>
 #include <linux/smp_lock.h>
diff --git a/sound/oss/dmasound/tas_ioctl.h b/sound/oss/dmasound/tas_ioctl.h
index dccae3a..9d12b37 100644
--- a/sound/oss/dmasound/tas_ioctl.h
+++ b/sound/oss/dmasound/tas_ioctl.h
@@ -1,7 +1,6 @@
 #ifndef _TAS_IOCTL_H_
 #define _TAS_IOCTL_H_
 
-#include <linux/i2c.h>
 #include <linux/soundcard.h>
 
 
diff --git a/sound/oss/soundcard.c b/sound/oss/soundcard.c
index dcd8d6d..a9c23b2 100644
--- a/sound/oss/soundcard.c
+++ b/sound/oss/soundcard.c
@@ -44,6 +44,7 @@
 #include <linux/smp_lock.h>
 #include <linux/module.h>
 #include <linux/mm.h>
+#include <linux/device.h>
 
 /*
  * This ought to be moved into include/asm/dma.h
diff --git a/sound/pci/ca0106/ca0106_mixer.c b/sound/pci/ca0106/ca0106_mixer.c
index b913a1f..9c3a9c8 100644
--- a/sound/pci/ca0106/ca0106_mixer.c
+++ b/sound/pci/ca0106/ca0106_mixer.c
@@ -62,7 +62,6 @@
 #include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
-#include <linux/pci.h>
 #include <linux/slab.h>
 #include <linux/moduleparam.h>
 #include <sound/core.h>
@@ -71,6 +70,7 @@
 #include <sound/ac97_codec.h>
 #include <sound/info.h>
 #include <sound/tlv.h>
+#include <asm/io.h>
 
 #include "ca0106.h"
 
diff --git a/sound/pci/ca0106/ca0106_proc.c b/sound/pci/ca0106/ca0106_proc.c
index 75ca421..ae80f51 100644
--- a/sound/pci/ca0106/ca0106_proc.c
+++ b/sound/pci/ca0106/ca0106_proc.c
@@ -64,7 +64,6 @@
 #include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
-#include <linux/pci.h>
 #include <linux/slab.h>
 #include <linux/moduleparam.h>
 #include <sound/core.h>
@@ -73,6 +72,7 @@
 #include <sound/ac97_codec.h>
 #include <sound/info.h>
 #include <sound/asoundef.h>
+#include <asm/io.h>
 
 #include "ca0106.h"
 
diff --git a/sound/pci/cs46xx/dsp_spos.c b/sound/pci/cs46xx/dsp_spos.c
index 89c4027..336e77e 100644
--- a/sound/pci/cs46xx/dsp_spos.c
+++ b/sound/pci/cs46xx/dsp_spos.c
@@ -23,7 +23,6 @@
 #include <sound/driver.h>
 #include <asm/io.h>
 #include <linux/delay.h>
-#include <linux/pci.h>
 #include <linux/pm.h>
 #include <linux/init.h>
 #include <linux/slab.h>
diff --git a/sound/pci/cs46xx/dsp_spos_scb_lib.c b/sound/pci/cs46xx/dsp_spos_scb_lib.c
index 343f51d..57e357d 100644
--- a/sound/pci/cs46xx/dsp_spos_scb_lib.c
+++ b/sound/pci/cs46xx/dsp_spos_scb_lib.c
@@ -24,7 +24,6 @@
 #include <sound/driver.h>
 #include <asm/io.h>
 #include <linux/delay.h>
-#include <linux/pci.h>
 #include <linux/pm.h>
 #include <linux/init.h>
 #include <linux/slab.h>
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
index 1589d2f..1e5ff0c 100644
--- a/sound/pci/hda/hda_generic.c
+++ b/sound/pci/hda/hda_generic.c
@@ -23,7 +23,6 @@
 #include <sound/driver.h>
 #include <linux/init.h>
 #include <linux/slab.h>
-#include <linux/pci.h>
 #include <sound/core.h>
 #include "hda_codec.h"
 #include "hda_local.h"
diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c
index 17df4d0..e313e68 100644
--- a/sound/pci/hda/hda_proc.c
+++ b/sound/pci/hda/hda_proc.c
@@ -23,7 +23,6 @@
 
 #include <sound/driver.h>
 #include <linux/init.h>
-#include <linux/pci.h>
 #include <sound/core.h>
 #include "hda_codec.h"
 #include "hda_local.h"
diff --git a/sound/pci/hda/patch_atihdmi.c b/sound/pci/hda/patch_atihdmi.c
index 7333f27..831469d 100644
--- a/sound/pci/hda/patch_atihdmi.c
+++ b/sound/pci/hda/patch_atihdmi.c
@@ -25,7 +25,6 @@
 #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"
diff --git a/sound/pci/hda/patch_si3054.c b/sound/pci/hda/patch_si3054.c
index ed5e45e..6fcda9b 100644
--- a/sound/pci/hda/patch_si3054.c
+++ b/sound/pci/hda/patch_si3054.c
@@ -26,7 +26,6 @@
 #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"
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c
index 4c839b0..2b11ac8 100644
--- a/sound/pci/hda/patch_via.c
+++ b/sound/pci/hda/patch_via.c
@@ -35,7 +35,6 @@
 #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"